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
TEST(UnixSocket,message_buffer_smoke)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
ClientToTestUndelayedMessage(const std::string & path,bool & client_success)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
TEST(UnixSocket,undelayed_message)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
ClientToTestBufferedMessage(const std::string & path,bool & client_success)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
TEST(UnixSocket,buffered_message)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 }
208