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 } 208