| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2015 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2015 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #include "gtest/gtest.h" | 7 #include "gtest/gtest.h" |
| 8 | 8 |
| 9 #include <errno.h> | 9 #include <errno.h> |
| 10 #include <unistd.h> |
| 11 #include <sys/types.h> |
| 12 #include <sys/socket.h> |
| 10 | 13 |
| 11 #include "native_client/src/include/build_config.h" | 14 #include "native_client/src/include/build_config.h" |
| 12 #include "native_client/src/trusted/debug_stub/transport.h" | 15 #include "native_client/src/trusted/debug_stub/transport.h" |
| 13 | 16 |
| 14 #if NACL_WINDOWS | |
| 15 #include <windows.h> | |
| 16 #else | |
| 17 #include <unistd.h> | |
| 18 #include <sys/types.h> | |
| 19 #include <sys/socket.h> | |
| 20 #endif | |
| 21 | |
| 22 static const int kBufSize = 1024; | 17 static const int kBufSize = 1024; |
| 23 static const int kDisconnectFlag = -1; | 18 static const int kDisconnectFlag = -1; |
| 24 | 19 |
| 25 class TransportIPCTests : public ::testing::Test { | 20 class TransportIPCTests : public ::testing::Test { |
| 26 protected: | 21 protected: |
| 27 port::ITransport *transport; | 22 port::ITransport *transport; |
| 28 NaClHandle fd[2]; | 23 int fd[2]; |
| 29 char buf[kBufSize]; | 24 char buf[kBufSize]; |
| 30 | 25 |
| 31 void SetUp() { | 26 void SetUp() { |
| 32 #if NACL_WINDOWS | 27 EXPECT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, fd), 0); |
| 33 const char *PIPENAME = "\\\\.\\pipe\\TestTransportIPC"; | |
| 34 | |
| 35 // Windows named pipes act more like a server-client than pipes or | |
| 36 // socket pairs on POSIX, therefore the server end of the pipe needs to | |
| 37 // call connect while creating the client end of the pipe. | |
| 38 // | |
| 39 // Since this is happening on a single thread we make the server pipe | |
| 40 // operations asynchronous. The main order of operations to mimic a | |
| 41 // socketpair is as so: | |
| 42 // 1. Create server pipe | |
| 43 // 2. Wait for connections async | |
| 44 // 3. Create client end synchronously | |
| 45 // 4. Wait on async server connection object | |
| 46 // | |
| 47 // Async is handled using overlapped objects which can be read about on: | |
| 48 // msdn.microsoft.com/en-us/library/windows/desktop/ms686358(v=vs.85).aspx | |
| 49 fd[0] = CreateNamedPipe(PIPENAME, | |
| 50 PIPE_ACCESS_DUPLEX | | |
| 51 FILE_FLAG_FIRST_PIPE_INSTANCE | | |
| 52 FILE_FLAG_OVERLAPPED, | |
| 53 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, | |
| 54 1, | |
| 55 kBufSize, | |
| 56 kBufSize, | |
| 57 5000, | |
| 58 NULL); | |
| 59 | |
| 60 EXPECT_NE(INVALID_HANDLE_VALUE, fd[0]); | |
| 61 | |
| 62 OVERLAPPED overlap; | |
| 63 | |
| 64 // If these aren't set to 0 windows will complain. | |
| 65 overlap.Offset = 0; | |
| 66 overlap.OffsetHigh = 0; | |
| 67 | |
| 68 // Create event used for async operations. | |
| 69 overlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); | |
| 70 EXPECT_NE(INVALID_HANDLE_VALUE, overlap.hEvent); | |
| 71 | |
| 72 // Run connect operation asynchronously. | |
| 73 EXPECT_FALSE(ConnectNamedPipe(fd[0], &overlap)); | |
| 74 EXPECT_EQ(ERROR_IO_PENDING, GetLastError()); | |
| 75 | |
| 76 // Connect file side of pipe. | |
| 77 fd[1] = CreateFile(PIPENAME, | |
| 78 GENERIC_READ | GENERIC_WRITE, | |
| 79 0, | |
| 80 NULL, | |
| 81 OPEN_EXISTING, | |
| 82 SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS, | |
| 83 NULL); | |
| 84 | |
| 85 EXPECT_NE(INVALID_HANDLE_VALUE, fd[1]); | |
| 86 | |
| 87 DWORD bytes; | |
| 88 // Wait for the connect operation to complete. Should already be done | |
| 89 // given the above call to CreateFile(). | |
| 90 EXPECT_TRUE(GetOverlappedResult(fd[0], &overlap, &bytes, TRUE)); | |
| 91 | |
| 92 CloseHandle(overlap.hEvent); | |
| 93 #else | |
| 94 EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, fd)); | |
| 95 #endif | |
| 96 transport = port::CreateTransportIPC(fd[1]); | 28 transport = port::CreateTransportIPC(fd[1]); |
| 97 memset(buf, 0, kBufSize); | 29 memset(buf, 0, kBufSize); |
| 98 } | 30 } |
| 99 | 31 |
| 100 void TearDown() { | 32 void TearDown() { |
| 101 #if NACL_WINDOWS | |
| 102 CloseHandle(fd[0]); | |
| 103 #else | |
| 104 close(fd[0]); | 33 close(fd[0]); |
| 105 #endif | |
| 106 delete transport; | 34 delete transport; |
| 107 } | 35 } |
| 108 }; | 36 }; |
| 109 | 37 |
| 110 static const int packet[9] = { | 38 static const int packet[9] = { |
| 111 32, // Payload size is 32 bytes. | 39 32, // Payload size is 32 bytes. |
| 112 0, 1, 2, 3, 4, 5, 6, 7 | 40 0, 1, 2, 3, 4, 5, 6, 7 |
| 113 }; | 41 }; |
| 114 | 42 |
| 115 static const int packet2[2] = { | 43 static const int packet2[2] = { |
| 116 4, // Payload size is 4 bytes. | 44 4, // Payload size is 4 bytes. |
| 117 8 | 45 8 |
| 118 }; | 46 }; |
| 119 | 47 |
| 120 static const int out_packet[4] = { | 48 static const int out_packet[4] = { |
| 121 0, 1, 2, 3 | 49 0, 1, 2, 3 |
| 122 }; | 50 }; |
| 123 | 51 |
| 124 // Block until you read len bytes. | 52 // Block until you read len bytes. |
| 125 // Return false on EOF or error, but retries on EINTR. | 53 // Return false on EOF or error, but retries on EINTR. |
| 126 bool ReadNBytes(NaClHandle handle, void *ptr, uint32_t len) { | 54 bool ReadNBytes(int fd, void *ptr, uint32_t len) { |
| 127 char *buf = reinterpret_cast<char *>(ptr); | 55 char *buf = reinterpret_cast<char *>(ptr); |
| 128 uint32_t bytes_read = 0; | 56 uint32_t bytes_read = 0; |
| 129 while (len > 0) { | 57 while (len > 0) { |
| 130 int result; | 58 int result = ::read(fd, buf + bytes_read, len); |
| 131 | 59 if (result > 0) { |
| 132 #if NACL_WINDOWS | 60 bytes_read += result; |
| 133 DWORD num_bytes; | 61 len -= result; |
| 134 OVERLAPPED overlap; | 62 } else if (result == 0 || errno != EINTR) { |
| 135 | 63 return false; |
| 136 // If these aren't set to 0 windows will complain. | |
| 137 overlap.Offset = 0; | |
| 138 overlap.OffsetHigh = 0; | |
| 139 | |
| 140 overlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); | |
| 141 | |
| 142 if (!ReadFile(handle, buf, len, &num_bytes, &overlap)) { | |
| 143 EXPECT_EQ(ERROR_IO_PENDING, GetLastError()); | |
| 144 if (!GetOverlappedResult(handle, | |
| 145 &overlap, | |
| 146 &num_bytes, | |
| 147 TRUE)) { | |
| 148 return false; | |
| 149 } | |
| 150 } | 64 } |
| 151 | |
| 152 result = static_cast<int>(num_bytes); | |
| 153 | |
| 154 CloseHandle(overlap.hEvent); | |
| 155 #else | |
| 156 result = ::read(handle, buf + bytes_read, len); | |
| 157 if (result == 0 || (result == -1 && errno != EINTR)) | |
| 158 return false; | |
| 159 #endif | |
| 160 | |
| 161 bytes_read += result; | |
| 162 len -= result; | |
| 163 } | 65 } |
| 164 return true; | 66 return true; |
| 165 } | 67 } |
| 166 | 68 |
| 167 // Keep trying until you write len bytes. | 69 // Keep trying until you write len bytes. |
| 168 // Return false on EOF or error, but retries on EINTR. | 70 // Return false on EOF or error, but retries on EINTR. |
| 169 bool WriteNBytes(NaClHandle handle, const void *ptr, uint32_t len) { | 71 bool WriteNBytes(int fd, const void *ptr, uint32_t len) { |
| 170 const char *buf = reinterpret_cast<const char *>(ptr); | 72 const char *buf = reinterpret_cast<const char *>(ptr); |
| 171 uint32_t bytes_written = 0; | 73 uint32_t bytes_read = 0; |
| 172 while (len > 0) { | 74 while (len > 0) { |
| 173 int result; | 75 int result = ::write(fd, buf + bytes_read, len); |
| 174 | 76 if (result > 0) { |
| 175 #if NACL_WINDOWS | 77 bytes_read += result; |
| 176 DWORD num_bytes; | 78 len -= result; |
| 177 OVERLAPPED overlap; | 79 } else if (result == 0 || errno != EINTR) { |
| 178 | 80 return false; |
| 179 // If these aren't set to 0 windows will complain. | |
| 180 overlap.Offset = 0; | |
| 181 overlap.OffsetHigh = 0; | |
| 182 | |
| 183 overlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); | |
| 184 | |
| 185 if (!WriteFile(handle, buf, len, &num_bytes, &overlap)) { | |
| 186 EXPECT_EQ(ERROR_IO_PENDING, GetLastError()); | |
| 187 if (!GetOverlappedResult(handle, | |
| 188 &overlap, | |
| 189 &num_bytes, | |
| 190 TRUE)) { | |
| 191 return false; | |
| 192 } | |
| 193 } | 81 } |
| 194 | |
| 195 result = static_cast<int>(num_bytes); | |
| 196 | |
| 197 CloseHandle(overlap.hEvent); | |
| 198 #else | |
| 199 result = ::write(handle, buf + bytes_written, len); | |
| 200 if (result == 0 || (result == -1 && errno != EINTR)) | |
| 201 return false; | |
| 202 #endif | |
| 203 | |
| 204 bytes_written += result; | |
| 205 len -= result; | |
| 206 } | 82 } |
| 207 return true; | 83 return true; |
| 208 } | 84 } |
| 209 | 85 |
| 210 // Test accepting multiple connections in sequence. | 86 // Test accepting multiple connections in sequence. |
| 211 TEST_F(TransportIPCTests, TestAcceptConnection) { | 87 TEST_F(TransportIPCTests, TestAcceptConnection) { |
| 212 // Write data so AcceptConnection() wont block. | 88 // Write data so AcceptConnection() wont block. |
| 213 EXPECT_TRUE(WriteNBytes(fd[0], packet, sizeof(packet))); | 89 EXPECT_EQ(WriteNBytes(fd[0], packet, sizeof(packet)), true); |
| 214 | 90 |
| 215 // Since there is data this should return true without blocking. | 91 // Since there is data this should return true without blocking. |
| 216 EXPECT_TRUE(transport->AcceptConnection()); | 92 EXPECT_EQ(transport->AcceptConnection(), true); |
| 217 | 93 |
| 218 // Write -1 so transport marks itself as disconnected. | 94 // Write -1 so transport marks itself as disconnected. |
| 219 EXPECT_TRUE(WriteNBytes(fd[0], &kDisconnectFlag, sizeof(kDisconnectFlag))); | 95 EXPECT_EQ(WriteNBytes(fd[0], &kDisconnectFlag, sizeof(kDisconnectFlag)), |
| 96 true); |
| 220 | 97 |
| 221 // Read data sent and -1 flag. | 98 // Read data sent and -1 flag. |
| 222 EXPECT_FALSE(transport->Read(buf, kBufSize)); | 99 EXPECT_EQ(transport->Read(buf, kBufSize), false); |
| 223 | 100 |
| 224 // Try to establish new connection. | 101 // Try to establish new connection. |
| 225 EXPECT_TRUE(WriteNBytes(fd[0], packet, sizeof(packet))); | 102 EXPECT_EQ(WriteNBytes(fd[0], packet, sizeof(packet)), true); |
| 226 EXPECT_TRUE(transport->AcceptConnection()); | 103 EXPECT_EQ(transport->AcceptConnection(), true); |
| 227 } | 104 } |
| 228 | 105 |
| 229 // Test reading multiple buffered packets at once. | 106 // Test reading multiple buffered packets at once. |
| 230 TEST_F(TransportIPCTests, TestReadMultiplePacketsAtOnce) { | 107 TEST_F(TransportIPCTests, TestReadMultiplePacketsAtOnce) { |
| 231 // Write initial data and accept connection. | 108 // Write initial data and accept connection. |
| 232 EXPECT_TRUE(WriteNBytes(fd[0], packet, sizeof(packet))); | 109 EXPECT_EQ(WriteNBytes(fd[0], packet, sizeof(packet)), true); |
| 233 EXPECT_TRUE(transport->AcceptConnection()); | 110 EXPECT_EQ(transport->AcceptConnection(), true); |
| 234 | 111 |
| 235 // Write a second packet. | 112 // Write a second packet. |
| 236 EXPECT_TRUE(WriteNBytes(fd[0], packet2, sizeof(packet2))); | 113 EXPECT_EQ(WriteNBytes(fd[0], packet2, sizeof(packet2)), true); |
| 237 | 114 |
| 238 // Read both packets. | 115 // Read both packets. |
| 239 EXPECT_TRUE(transport->Read(buf, 9 * sizeof(int))); | 116 EXPECT_EQ(transport->Read(buf, 9 * sizeof(int)), true); |
| 240 | 117 |
| 241 // Check if packets were both read properly. | 118 // Check if packets were both read properly. |
| 242 for (int i = 0; i < 9; i++) { | 119 for (int i = 0; i < 9; i++) { |
| 243 EXPECT_EQ(i, reinterpret_cast<int*>(buf)[i]); | 120 EXPECT_EQ(reinterpret_cast<int*>(buf)[i], i); |
| 244 } | 121 } |
| 245 } | 122 } |
| 246 | 123 |
| 247 // Test reading single packet over multiple calls to read. | 124 // Test reading single packet over multiple calls to read. |
| 248 TEST_F(TransportIPCTests, TestReadSinglePacket) { | 125 TEST_F(TransportIPCTests, TestReadSinglePacket) { |
| 249 // Write initial data and accept connection. | 126 // Write initial data and accept connection. |
| 250 EXPECT_TRUE(WriteNBytes(fd[0], packet, sizeof(packet))); | 127 EXPECT_EQ(WriteNBytes(fd[0], packet, sizeof(packet)), true); |
| 251 EXPECT_TRUE(transport->AcceptConnection()); | 128 EXPECT_EQ(transport->AcceptConnection(), true); |
| 252 | 129 |
| 253 // Read first half of the packet. | 130 // Read first half of the packet. |
| 254 EXPECT_TRUE(transport->Read(buf, 4 * sizeof(int))); | 131 EXPECT_EQ(transport->Read(buf, 4 * sizeof(int)), true); |
| 255 // Read second half of the packet. | 132 // Read second half of the packet. |
| 256 EXPECT_TRUE(transport->Read(buf + 16, 4 * sizeof(int))); | 133 EXPECT_EQ(transport->Read(buf + 16, 4 * sizeof(int)), true); |
| 257 | 134 |
| 258 // Check if entire packets were both read properly. | 135 // Check if entire packets were both read properly. |
| 259 for (int i = 0; i < 8; i++) { | 136 for (int i = 0; i < 8; i++) { |
| 260 EXPECT_EQ(i, reinterpret_cast<int*>(buf)[i]); | 137 EXPECT_EQ(reinterpret_cast<int*>(buf)[i], i); |
| 261 } | 138 } |
| 262 } | 139 } |
| 263 | 140 |
| 264 // Test IsDataAvailable() | 141 // Test IsDataAvailable() |
| 265 TEST_F(TransportIPCTests, TestIsDataAvailable) { | 142 TEST_F(TransportIPCTests, TestIsDataAvailable) { |
| 266 // Write initial data and accept connection. | 143 // Write initial data and accept connection. |
| 267 EXPECT_TRUE(WriteNBytes(fd[0], packet, sizeof(packet))); | 144 EXPECT_EQ(WriteNBytes(fd[0], packet, sizeof(packet)), true); |
| 268 EXPECT_TRUE(transport->AcceptConnection()); | 145 EXPECT_EQ(transport->AcceptConnection(), true); |
| 269 | 146 |
| 270 // Should be data available from initial write. | 147 // Should be data available from initial write. |
| 271 EXPECT_TRUE(transport->IsDataAvailable()); | 148 EXPECT_EQ(transport->IsDataAvailable(), true); |
| 272 | 149 |
| 273 // Read some of the data | 150 // Read some of the data |
| 274 EXPECT_TRUE(transport->Read(buf, 4 * sizeof(int))); | 151 EXPECT_EQ(transport->Read(buf, 4 * sizeof(int)), true); |
| 275 | 152 |
| 276 // Should still be data available from initial write. | 153 // Should still be data available from initial write. |
| 277 EXPECT_TRUE(transport->IsDataAvailable()); | 154 EXPECT_EQ(transport->IsDataAvailable(), true); |
| 278 | 155 |
| 279 // Read the rest of the data | 156 // Read the rest of the data |
| 280 EXPECT_TRUE(transport->Read(buf, 4 * sizeof(int))); | 157 EXPECT_EQ(transport->Read(buf, 4 * sizeof(int)), true); |
| 281 | 158 |
| 282 // No more data. | 159 // No more data. |
| 283 EXPECT_FALSE(transport->IsDataAvailable()); | 160 EXPECT_EQ(transport->IsDataAvailable(), false); |
| 284 } | 161 } |
| 285 | 162 |
| 286 // Test writing data. | 163 // Test writing data. |
| 287 TEST_F(TransportIPCTests, TestWrite) { | 164 TEST_F(TransportIPCTests, TestWrite) { |
| 288 // Write initial data and accept connection. | 165 // Write initial data and accept connection. |
| 289 EXPECT_TRUE(WriteNBytes(fd[0], packet, sizeof(packet))); | 166 EXPECT_EQ(WriteNBytes(fd[0], packet, sizeof(packet)), true); |
| 290 EXPECT_TRUE(transport->AcceptConnection()); | 167 EXPECT_EQ(transport->AcceptConnection(), true); |
| 291 | 168 |
| 292 // Write packet out. | 169 // Write packet out. |
| 293 EXPECT_TRUE(transport->Write(out_packet, sizeof(out_packet))); | 170 EXPECT_EQ(transport->Write(out_packet, sizeof(out_packet)), true); |
| 294 | 171 |
| 295 EXPECT_TRUE(ReadNBytes(fd[0], buf, sizeof(out_packet))); | 172 EXPECT_EQ(ReadNBytes(fd[0], buf, sizeof(out_packet)), true); |
| 296 | 173 |
| 297 // Check if out packet was written properly. | 174 // Check if out packet was written properly. |
| 298 for (int i = 0; i < 4; i++) { | 175 for (int i = 0; i < 4; i++) { |
| 299 EXPECT_EQ(i, reinterpret_cast<int*>(buf)[i]); | 176 EXPECT_EQ(reinterpret_cast<int*>(buf)[i], i); |
| 300 } | 177 } |
| 301 } | 178 } |
| 302 | 179 |
| 303 // Test disconnect. | 180 // Test disconnect. |
| 304 TEST_F(TransportIPCTests, TestDisconnect) { | 181 TEST_F(TransportIPCTests, TestDisconnect) { |
| 305 // Write initial data and accept connection. | 182 // Write initial data and accept connection. |
| 306 EXPECT_TRUE(WriteNBytes(fd[0], packet, sizeof(packet))); | 183 EXPECT_TRUE(WriteNBytes(fd[0], packet, sizeof(packet))); |
| 307 EXPECT_TRUE(transport->AcceptConnection()); | 184 EXPECT_TRUE(transport->AcceptConnection()); |
| 308 | 185 |
| 309 // Write -1 so transport can disconnect. | 186 // Write -1 so transport can disconnect. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 320 EXPECT_TRUE(transport->Read(buf, sizeof(packet) - 4)); | 197 EXPECT_TRUE(transport->Read(buf, sizeof(packet) - 4)); |
| 321 | 198 |
| 322 // Second packet should have been thrown away. | 199 // Second packet should have been thrown away. |
| 323 EXPECT_FALSE(transport->IsDataAvailable()); | 200 EXPECT_FALSE(transport->IsDataAvailable()); |
| 324 } | 201 } |
| 325 | 202 |
| 326 int main(int argc, char *argv[]) { | 203 int main(int argc, char *argv[]) { |
| 327 testing::InitGoogleTest(&argc, argv); | 204 testing::InitGoogleTest(&argc, argv); |
| 328 return RUN_ALL_TESTS(); | 205 return RUN_ALL_TESTS(); |
| 329 } | 206 } |
| OLD | NEW |