OSDN Git Service

Merge "Perfprofd: Factor out threaded handler" into pi-dev
[android-x86/system-extras.git] / simpleperf / UnixSocket_test.cpp
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "UnixSocket.h"
18
19 #include <gtest/gtest.h>
20
21 #include <string>
22 #include <thread>
23
24 TEST(UnixSocket, message_buffer_smoke) {
25   struct Message {
26     uint32_t len;
27     uint32_t type;
28     char data[10];
29   } send_msg;
30   constexpr size_t send_data_size = 1024;
31   std::vector<char> send_data(send_data_size);
32   std::vector<char> read_data;
33   for (size_t i = 0; i < send_data_size; ++i) {
34     send_data[i] = i & 0xff;
35   }
36   UnixSocketMessageBuffer buffer(100);
37   size_t per_msg_bytes = 0;
38   size_t send_bytes = 0;
39   while (true) {
40     // Send data as much as possible.
41     while (send_bytes < send_data_size) {
42       size_t n = std::min(per_msg_bytes, send_data_size - send_bytes);
43       per_msg_bytes = (per_msg_bytes + 1) % 10;
44       memcpy(send_msg.data, &send_data[send_bytes], n);
45       send_msg.len = sizeof(UnixSocketMessage) + n;
46       send_msg.type = n;
47       if (!buffer.StoreMessage(
48               *reinterpret_cast<UnixSocketMessage*>(&send_msg))) {
49         break;
50       }
51       send_bytes += n;
52     }
53     if (buffer.Empty()) {
54       break;
55     }
56     // Read one message.
57     std::vector<char> read_buf;
58     auto read_func = [&](size_t size) {
59       while (read_buf.size() < size) {
60         const char* p;
61         size_t n = buffer.PeekData(&p);
62         n = std::min(n, size - read_buf.size());
63         read_buf.insert(read_buf.end(), p, p + n);
64         buffer.CommitData(n);
65       }
66     };
67     read_func(sizeof(UnixSocketMessage));
68     Message* msg = reinterpret_cast<Message*>(read_buf.data());
69     size_t aligned_len = Align(msg->len, UnixSocketMessageAlignment);
70     read_func(aligned_len);
71     msg = reinterpret_cast<Message*>(read_buf.data());
72     ASSERT_EQ(msg->len, msg->type + sizeof(UnixSocketMessage));
73     read_data.insert(read_data.end(), msg->data, msg->data + msg->type);
74   }
75   ASSERT_EQ(send_data, read_data);
76 }
77
78 static void ClientToTestUndelayedMessage(const std::string& path,
79                                          bool& client_success) {
80   std::unique_ptr<UnixSocketConnection> client =
81       UnixSocketConnection::Connect(path, true);
82   ASSERT_TRUE(client != nullptr);
83   IOEventLoop loop;
84   // For each message received from the server, the client replies a msg
85   // with type + 1.
86   auto receive_message_callback = [&](const UnixSocketMessage& msg) {
87     if (msg.len != sizeof(UnixSocketMessage)) {
88       return false;
89     }
90     UnixSocketMessage reply_msg;
91     reply_msg.len = sizeof(UnixSocketMessage);
92     reply_msg.type = msg.type + 1;
93     return client->SendMessage(reply_msg, true);
94   };
95   auto close_connection_callback = [&]() { return loop.ExitLoop(); };
96   ASSERT_TRUE(client->PrepareForIO(loop, receive_message_callback,
97                                    close_connection_callback));
98   ASSERT_TRUE(loop.RunLoop());
99   client_success = true;
100 }
101
102 TEST(UnixSocket, undelayed_message) {
103   std::string path = "unix_socket_test_" + std::to_string(getpid());
104   std::unique_ptr<UnixSocketServer> server =
105       UnixSocketServer::Create(path, true);
106   ASSERT_TRUE(server != nullptr);
107   bool client_success = false;
108   std::thread thread(
109       [&]() { ClientToTestUndelayedMessage(path, client_success); });
110   std::unique_ptr<UnixSocketConnection> conn = server->AcceptConnection();
111   ASSERT_TRUE(conn != nullptr);
112   IOEventLoop loop;
113   uint32_t need_reply_type = 1;
114   // For each message received from the client, the server replies a msg
115   // with type + 1, and exits when type reaches 10.
116   auto receive_message_callback = [&](const UnixSocketMessage& msg) {
117     if (msg.len != sizeof(UnixSocketMessage) || msg.type != need_reply_type) {
118       return false;
119     }
120     if (need_reply_type >= 10) {
121       return conn->NoMoreMessage();
122     }
123     UnixSocketMessage new_msg;
124     new_msg.len = sizeof(UnixSocketMessage);
125     new_msg.type = msg.type + 1;
126     need_reply_type = msg.type + 2;
127     return conn->SendMessage(new_msg, true);
128   };
129   auto close_connection_callback = [&]() { return loop.ExitLoop(); };
130   ASSERT_TRUE(conn->PrepareForIO(loop, receive_message_callback,
131                                  close_connection_callback));
132   UnixSocketMessage msg;
133   msg.len = sizeof(UnixSocketMessage);
134   msg.type = 0;
135   ASSERT_TRUE(conn->SendMessage(msg, true));
136   ASSERT_TRUE(loop.RunLoop());
137   thread.join();
138   ASSERT_TRUE(client_success);
139 }
140
141 static void ClientToTestBufferedMessage(const std::string& path,
142                                         bool& client_success) {
143   std::unique_ptr<UnixSocketConnection> client =
144       UnixSocketConnection::Connect(path, true);
145   ASSERT_TRUE(client != nullptr);
146   IOEventLoop loop;
147   // The client exits once receiving a message from the server.
148   auto receive_message_callback = [&](const UnixSocketMessage& msg) {
149     if (msg.len != sizeof(UnixSocketMessage) || msg.type != 0) {
150       return false;
151     }
152     return client->NoMoreMessage();
153   };
154   auto close_connection_callback = [&]() { return loop.ExitLoop(); };
155   ASSERT_TRUE(client->PrepareForIO(loop, receive_message_callback,
156                                    close_connection_callback));
157   // The client sends buffered messages until the send buffer is full.
158   UnixSocketMessage msg;
159   msg.len = sizeof(UnixSocketMessage);
160   msg.type = 0;
161   while (true) {
162     msg.type++;
163     if (!client->SendMessage(msg, false)) {
164       break;
165     }
166   }
167   ASSERT_TRUE(loop.RunLoop());
168   client_success = true;
169 }
170
171 TEST(UnixSocket, buffered_message) {
172   std::string path = "unix_socket_test_" + std::to_string(getpid());
173   std::unique_ptr<UnixSocketServer> server =
174       UnixSocketServer::Create(path, true);
175   ASSERT_TRUE(server != nullptr);
176   bool client_success = false;
177   std::thread thread(
178       [&]() { ClientToTestBufferedMessage(path, client_success); });
179   std::unique_ptr<UnixSocketConnection> conn = server->AcceptConnection();
180   ASSERT_TRUE(conn != nullptr);
181   IOEventLoop loop;
182   uint32_t need_reply_type = 1;
183   auto receive_message_callback = [&](const UnixSocketMessage& msg) {
184     // The server checks if the type of received message is increased by one
185     // each time.
186     if (msg.len != sizeof(UnixSocketMessage) || msg.type != need_reply_type) {
187       return false;
188     }
189     if (need_reply_type == 1) {
190       // Notify the client to exit.
191       UnixSocketMessage new_msg;
192       new_msg.len = sizeof(UnixSocketMessage);
193       new_msg.type = 0;
194       if (!conn->SendMessage(new_msg, true)) {
195         return false;
196       }
197     }
198     need_reply_type++;
199     return true;
200   };
201   auto close_connection_callback = [&]() { return loop.ExitLoop(); };
202   ASSERT_TRUE(conn->PrepareForIO(loop, receive_message_callback,
203                                  close_connection_callback));
204   ASSERT_TRUE(loop.RunLoop());
205   thread.join();
206   ASSERT_TRUE(client_success);
207 }