Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 namespace rtc { | 22 namespace rtc { |
| 23 | 23 |
| 24 class PhysicalSocketTest; | 24 class PhysicalSocketTest; |
| 25 | 25 |
| 26 class FakeSocketDispatcher : public SocketDispatcher { | 26 class FakeSocketDispatcher : public SocketDispatcher { |
| 27 public: | 27 public: |
| 28 explicit FakeSocketDispatcher(PhysicalSocketServer* ss) | 28 explicit FakeSocketDispatcher(PhysicalSocketServer* ss) |
| 29 : SocketDispatcher(ss) { | 29 : SocketDispatcher(ss) { |
| 30 } | 30 } |
| 31 | 31 |
| 32 FakeSocketDispatcher(SOCKET s, PhysicalSocketServer* ss) | |
| 33 : SocketDispatcher(s, ss) { | |
| 34 } | |
| 35 | |
| 32 protected: | 36 protected: |
| 33 SOCKET DoAccept(SOCKET socket, sockaddr* addr, socklen_t* addrlen) override; | 37 SOCKET DoAccept(SOCKET socket, sockaddr* addr, socklen_t* addrlen) override; |
| 38 int DoSend(SOCKET socket, const char* buf, int len, int flags) override; | |
| 39 int DoSendTo(SOCKET socket, const char* buf, int len, int flags, | |
| 40 const struct sockaddr* dest_addr, socklen_t addrlen) override; | |
| 34 }; | 41 }; |
| 35 | 42 |
| 36 class FakePhysicalSocketServer : public PhysicalSocketServer { | 43 class FakePhysicalSocketServer : public PhysicalSocketServer { |
| 37 public: | 44 public: |
| 38 explicit FakePhysicalSocketServer(PhysicalSocketTest* test) | 45 explicit FakePhysicalSocketServer(PhysicalSocketTest* test) |
| 39 : test_(test) { | 46 : test_(test) { |
| 40 } | 47 } |
| 41 | 48 |
| 42 AsyncSocket* CreateAsyncSocket(int type) override { | 49 AsyncSocket* CreateAsyncSocket(int type) override { |
| 43 SocketDispatcher* dispatcher = new FakeSocketDispatcher(this); | 50 SocketDispatcher* dispatcher = new FakeSocketDispatcher(this); |
| 44 if (dispatcher->Create(type)) { | 51 if (dispatcher->Create(type)) { |
| 45 return dispatcher; | 52 return dispatcher; |
| 46 } else { | 53 } else { |
| 47 delete dispatcher; | 54 delete dispatcher; |
| 48 return nullptr; | 55 return nullptr; |
| 49 } | 56 } |
| 50 } | 57 } |
| 51 | 58 |
| 52 AsyncSocket* CreateAsyncSocket(int family, int type) override { | 59 AsyncSocket* CreateAsyncSocket(int family, int type) override { |
| 53 SocketDispatcher* dispatcher = new FakeSocketDispatcher(this); | 60 SocketDispatcher* dispatcher = new FakeSocketDispatcher(this); |
| 54 if (dispatcher->Create(family, type)) { | 61 if (dispatcher->Create(family, type)) { |
| 55 return dispatcher; | 62 return dispatcher; |
| 56 } else { | 63 } else { |
| 57 delete dispatcher; | 64 delete dispatcher; |
| 58 return nullptr; | 65 return nullptr; |
| 59 } | 66 } |
| 60 } | 67 } |
| 61 | 68 |
| 69 AsyncSocket* WrapSocket(SOCKET s) override { | |
| 70 SocketDispatcher* dispatcher = new FakeSocketDispatcher(s, this); | |
| 71 if (dispatcher->Initialize()) { | |
| 72 return dispatcher; | |
| 73 } else { | |
| 74 delete dispatcher; | |
| 75 return nullptr; | |
| 76 } | |
|
pthatcher1
2016/01/30 00:03:10
Can you flip this around?
if (!dispatcher->Initia
joachim
2016/01/31 23:29:07
Done. This was implemented similar to the existing
| |
| 77 } | |
| 78 | |
| 62 PhysicalSocketTest* GetTest() const { return test_; } | 79 PhysicalSocketTest* GetTest() const { return test_; } |
| 63 | 80 |
| 64 private: | 81 private: |
| 65 PhysicalSocketTest* test_; | 82 PhysicalSocketTest* test_; |
| 66 }; | 83 }; |
| 67 | 84 |
| 68 class PhysicalSocketTest : public SocketTest { | 85 class PhysicalSocketTest : public SocketTest { |
| 69 public: | 86 public: |
| 70 // Set flag to simluate failures when calling "::accept" on a AsyncSocket. | 87 // Set flag to simluate failures when calling "::accept" on a AsyncSocket. |
| 71 void SetFailAccept(bool fail) { fail_accept_ = fail; } | 88 void SetFailAccept(bool fail) { fail_accept_ = fail; } |
| 72 bool FailAccept() const { return fail_accept_; } | 89 bool FailAccept() const { return fail_accept_; } |
| 73 | 90 |
| 91 // Maximum size to ::send to a socket. Set to 0 to disable limiting. | |
|
pthatcher1
2016/01/30 00:03:10
Can you make "disabled limited" < 0, such as -1.
joachim
2016/01/31 23:29:06
Done.
| |
| 92 void SetMaximumSendSize(int max_size) { max_send_size_ = max_size; } | |
| 93 int MaximumSendSize() const { return max_send_size_; } | |
|
pthatcher1
2016/01/30 00:03:10
Please change MaximumSendSize => MaxSendSize in bo
joachim
2016/01/31 23:29:07
Done.
| |
| 94 | |
| 74 protected: | 95 protected: |
| 75 PhysicalSocketTest() | 96 PhysicalSocketTest() |
| 76 : server_(new FakePhysicalSocketServer(this)), | 97 : server_(new FakePhysicalSocketServer(this)), |
| 77 scope_(server_.get()), | 98 scope_(server_.get()), |
| 78 fail_accept_(false) { | 99 fail_accept_(false), |
| 100 max_send_size_(0) { | |
| 79 } | 101 } |
| 80 | 102 |
| 81 void ConnectInternalAcceptError(const IPAddress& loopback); | 103 void ConnectInternalAcceptError(const IPAddress& loopback); |
| 104 void PartialWriteStayWritable(const IPAddress& loopback); | |
|
pthatcher1
2016/01/30 00:03:10
Can you name this WritableAfterPartialWrite?
joachim
2016/01/31 23:29:06
Done.
| |
| 82 | 105 |
| 83 rtc::scoped_ptr<FakePhysicalSocketServer> server_; | 106 rtc::scoped_ptr<FakePhysicalSocketServer> server_; |
| 84 SocketServerScope scope_; | 107 SocketServerScope scope_; |
| 85 bool fail_accept_; | 108 bool fail_accept_; |
| 109 int max_send_size_; | |
| 86 }; | 110 }; |
| 87 | 111 |
| 88 SOCKET FakeSocketDispatcher::DoAccept(SOCKET socket, | 112 SOCKET FakeSocketDispatcher::DoAccept(SOCKET socket, |
| 89 sockaddr* addr, | 113 sockaddr* addr, |
| 90 socklen_t* addrlen) { | 114 socklen_t* addrlen) { |
| 91 FakePhysicalSocketServer* ss = | 115 FakePhysicalSocketServer* ss = |
| 92 static_cast<FakePhysicalSocketServer*>(socketserver()); | 116 static_cast<FakePhysicalSocketServer*>(socketserver()); |
| 93 if (ss->GetTest()->FailAccept()) { | 117 if (ss->GetTest()->FailAccept()) { |
| 94 return INVALID_SOCKET; | 118 return INVALID_SOCKET; |
| 95 } | 119 } |
| 96 | 120 |
| 97 return SocketDispatcher::DoAccept(socket, addr, addrlen); | 121 return SocketDispatcher::DoAccept(socket, addr, addrlen); |
| 98 } | 122 } |
| 99 | 123 |
| 124 int FakeSocketDispatcher::DoSend(SOCKET socket, const char* buf, int len, | |
| 125 int flags) { | |
| 126 FakePhysicalSocketServer* ss = | |
| 127 static_cast<FakePhysicalSocketServer*>(socketserver()); | |
| 128 if (ss->GetTest()->MaximumSendSize() > 0) { | |
| 129 len = std::min(len, ss->GetTest()->MaximumSendSize()); | |
| 130 } | |
| 131 | |
| 132 return SocketDispatcher::DoSend(socket, buf, len, flags); | |
| 133 } | |
| 134 | |
| 135 int FakeSocketDispatcher::DoSendTo(SOCKET socket, const char* buf, int len, | |
| 136 int flags, const struct sockaddr* dest_addr, socklen_t addrlen) { | |
| 137 FakePhysicalSocketServer* ss = | |
| 138 static_cast<FakePhysicalSocketServer*>(socketserver()); | |
| 139 if (ss->GetTest()->MaximumSendSize() > 0) { | |
| 140 len = std::min(len, ss->GetTest()->MaximumSendSize()); | |
| 141 } | |
| 142 | |
| 143 return SocketDispatcher::DoSendTo(socket, buf, len, flags, dest_addr, | |
| 144 addrlen); | |
| 145 } | |
| 146 | |
| 100 TEST_F(PhysicalSocketTest, TestConnectIPv4) { | 147 TEST_F(PhysicalSocketTest, TestConnectIPv4) { |
| 101 SocketTest::TestConnectIPv4(); | 148 SocketTest::TestConnectIPv4(); |
| 102 } | 149 } |
| 103 | 150 |
| 104 // Crashes on Linux. See webrtc:4923. | 151 // Crashes on Linux. See webrtc:4923. |
| 105 #if defined(WEBRTC_LINUX) | 152 #if defined(WEBRTC_LINUX) |
| 106 #define MAYBE_TestConnectIPv6 DISABLED_TestConnectIPv6 | 153 #define MAYBE_TestConnectIPv6 DISABLED_TestConnectIPv6 |
| 107 #else | 154 #else |
| 108 #define MAYBE_TestConnectIPv6 TestConnectIPv6 | 155 #define MAYBE_TestConnectIPv6 TestConnectIPv6 |
| 109 #endif | 156 #endif |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 202 // Crashes on Linux. See webrtc:4923. | 249 // Crashes on Linux. See webrtc:4923. |
| 203 #if defined(WEBRTC_LINUX) | 250 #if defined(WEBRTC_LINUX) |
| 204 #define MAYBE_TestConnectAcceptErrorIPv6 DISABLED_TestConnectAcceptErrorIPv6 | 251 #define MAYBE_TestConnectAcceptErrorIPv6 DISABLED_TestConnectAcceptErrorIPv6 |
| 205 #else | 252 #else |
| 206 #define MAYBE_TestConnectAcceptErrorIPv6 TestConnectAcceptErrorIPv6 | 253 #define MAYBE_TestConnectAcceptErrorIPv6 TestConnectAcceptErrorIPv6 |
| 207 #endif | 254 #endif |
| 208 TEST_F(PhysicalSocketTest, MAYBE_TestConnectAcceptErrorIPv6) { | 255 TEST_F(PhysicalSocketTest, MAYBE_TestConnectAcceptErrorIPv6) { |
| 209 ConnectInternalAcceptError(kIPv6Loopback); | 256 ConnectInternalAcceptError(kIPv6Loopback); |
| 210 } | 257 } |
| 211 | 258 |
| 259 void PhysicalSocketTest::PartialWriteStayWritable(const IPAddress& loopback) { | |
| 260 testing::StreamSink sink; | |
| 261 SocketAddress accept_addr; | |
| 262 | |
| 263 // Simulate a really small maximum send size. | |
| 264 const int kMaximumSendSize = 128; | |
|
pthatcher1
2016/01/30 00:03:10
kMaxSendSize
joachim
2016/01/31 23:29:06
Done.
| |
| 265 SetMaximumSendSize(kMaximumSendSize); | |
| 266 | |
| 267 // Create test data. | |
| 268 const size_t kDataSize = 128 * 1024; | |
| 269 scoped_ptr<char[]> send_buffer(new char[kDataSize]); | |
| 270 scoped_ptr<char[]> recv_buffer(new char[kDataSize]); | |
|
pthatcher1
2016/01/30 00:03:10
It seems like this would benefit from using rtc::B
joachim
2016/01/31 23:29:07
Done. As I used "SocketTest::TcpInternal" as base
| |
| 271 size_t send_pos = 0, recv_pos = 0; | |
|
pthatcher1
2016/01/30 00:03:10
You can replace all instances of recv_pos with rec
joachim
2016/01/31 23:29:06
Done.
| |
| 272 for (size_t i = 0; i < kDataSize; ++i) { | |
| 273 send_buffer[i] = static_cast<char>(i % 256); | |
| 274 recv_buffer[i] = 0; | |
| 275 } | |
| 276 | |
| 277 // Create client. | |
| 278 scoped_ptr<AsyncSocket> client( | |
| 279 server_->CreateAsyncSocket(loopback.family(), SOCK_STREAM)); | |
| 280 sink.Monitor(client.get()); | |
| 281 | |
| 282 // Create server and listen. | |
| 283 scoped_ptr<AsyncSocket> server( | |
| 284 server_->CreateAsyncSocket(loopback.family(), SOCK_STREAM)); | |
| 285 sink.Monitor(server.get()); | |
| 286 EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0))); | |
| 287 EXPECT_EQ(0, server->Listen(5)); | |
| 288 | |
| 289 // Attempt connection. | |
| 290 EXPECT_EQ(0, client->Connect(server->GetLocalAddress())); | |
| 291 | |
| 292 // Accept connection. | |
| 293 EXPECT_TRUE_WAIT((sink.Check(server.get(), testing::SSE_READ)), kTimeout); | |
| 294 scoped_ptr<AsyncSocket> accepted(server->Accept(&accept_addr)); | |
| 295 ASSERT_TRUE(accepted); | |
| 296 sink.Monitor(accepted.get()); | |
| 297 | |
| 298 // Both sides are now connected. | |
| 299 EXPECT_EQ_WAIT(AsyncSocket::CS_CONNECTED, client->GetState(), kTimeout); | |
| 300 EXPECT_TRUE(sink.Check(client.get(), testing::SSE_OPEN)); | |
| 301 EXPECT_EQ(client->GetRemoteAddress(), accepted->GetLocalAddress()); | |
| 302 EXPECT_EQ(accepted->GetRemoteAddress(), client->GetLocalAddress()); | |
| 303 | |
| 304 // Send and receive a bunch of data. | |
|
pthatcher1
2016/01/30 00:03:10
Can you move the definition of the send and recv b
joachim
2016/01/31 23:29:06
Done.
| |
| 305 bool send_waiting_for_writability = false; | |
|
pthatcher1
2016/01/30 00:03:10
Why not just "writable", with the reversed meaning
pthatcher1
2016/01/30 00:03:10
Can you call
sender = accepted;
receiver = clien
joachim
2016/01/31 23:29:06
Done.
joachim
2016/01/31 23:29:06
Done.
| |
| 306 bool send_expect_success = true; | |
|
pthatcher1
2016/01/30 00:03:10
Can you call this send_called = false? That would
joachim
2016/01/31 23:29:07
Done.
| |
| 307 bool recv_waiting_for_readability = true; | |
|
pthatcher1
2016/01/30 00:03:10
Similarly, "readable = false" here.
joachim
2016/01/31 23:29:06
Done.
| |
| 308 bool recv_expect_success = false; | |
|
pthatcher1
2016/01/30 00:03:10
And this "recv_called = false"?
joachim
2016/01/31 23:29:06
Done.
| |
| 309 int data_in_flight = 0; | |
| 310 while (recv_pos < kDataSize) { | |
| 311 // Send as much as we can if we've been cleared to send. | |
|
pthatcher1
2016/01/30 00:03:09
if we've been cleared to send => while we're clear
joachim
2016/01/31 23:29:06
Done.
| |
| 312 while (!send_waiting_for_writability && send_pos < kDataSize) { | |
| 313 int tosend = static_cast<int>(kDataSize - send_pos); | |
| 314 int sent = accepted->Send(send_buffer.get() + send_pos, tosend); | |
| 315 if (send_expect_success) { | |
| 316 // The first Send() after connecting or getting writability should | |
| 317 // succeed and send some data. | |
| 318 EXPECT_GT(sent, 0); | |
| 319 send_expect_success = false; | |
| 320 } | |
| 321 if (sent >= 0) { | |
| 322 EXPECT_LE(sent, tosend); | |
| 323 EXPECT_LE(sent, kMaximumSendSize); | |
| 324 send_pos += sent; | |
| 325 data_in_flight += sent; | |
|
pthatcher1
2016/01/30 00:03:10
I think you can replace all instances of data_in_f
joachim
2016/01/31 23:29:06
Done.
| |
| 326 } | |
| 327 if (sent < tosend) { | |
| 328 // Partial data or nothing sent. | |
| 329 ASSERT_TRUE(accepted->IsBlocking()); | |
| 330 send_waiting_for_writability = true; | |
| 331 } | |
| 332 } | |
| 333 | |
| 334 // Read all the sent data. | |
| 335 while (data_in_flight > 0) { | |
|
pthatcher1
2016/01/30 00:03:10
Or in this case:
while (recv_buffer.size() < sent
joachim
2016/01/31 23:29:06
Done.
| |
| 336 if (recv_waiting_for_readability) { | |
| 337 // Wait until data is available. | |
| 338 EXPECT_TRUE_WAIT(sink.Check(client.get(), testing::SSE_READ), kTimeout); | |
| 339 recv_waiting_for_readability = false; | |
| 340 recv_expect_success = true; | |
| 341 } | |
| 342 | |
| 343 // Receive as much as we can get in a single recv call. | |
| 344 int rcvd = client->Recv(recv_buffer.get() + recv_pos, | |
| 345 kDataSize - recv_pos); | |
| 346 | |
| 347 if (recv_expect_success) { | |
| 348 // The first Recv() after getting readability should succeed and receive | |
| 349 // some data. | |
| 350 EXPECT_GT(rcvd, 0); | |
| 351 recv_expect_success = false; | |
| 352 } | |
| 353 if (rcvd >= 0) { | |
| 354 EXPECT_LE(rcvd, data_in_flight); | |
| 355 recv_pos += rcvd; | |
| 356 data_in_flight -= rcvd; | |
| 357 } else { | |
| 358 ASSERT_TRUE(client->IsBlocking()); | |
| 359 recv_waiting_for_readability = true; | |
| 360 } | |
| 361 } | |
| 362 | |
| 363 // Once all that we've sent has been rcvd, expect to be able to send again. | |
| 364 if (send_waiting_for_writability) { | |
| 365 EXPECT_TRUE_WAIT(sink.Check(accepted.get(), testing::SSE_WRITE), | |
| 366 kTimeout); | |
| 367 send_waiting_for_writability = false; | |
| 368 send_expect_success = true; | |
| 369 } | |
| 370 } | |
| 371 | |
| 372 // The received data matches the sent data. | |
| 373 EXPECT_EQ(kDataSize, send_pos); | |
| 374 EXPECT_EQ(kDataSize, recv_pos); | |
| 375 EXPECT_EQ(0, memcmp(recv_buffer.get(), send_buffer.get(), kDataSize)); | |
| 376 | |
| 377 // Close down. | |
| 378 accepted->Close(); | |
| 379 EXPECT_EQ_WAIT(AsyncSocket::CS_CLOSED, client->GetState(), kTimeout); | |
| 380 EXPECT_TRUE(sink.Check(client.get(), testing::SSE_CLOSE)); | |
| 381 client->Close(); | |
| 382 } | |
| 383 | |
| 384 TEST_F(PhysicalSocketTest, TestPartialWriteStayWritableIPv4) { | |
| 385 PartialWriteStayWritable(kIPv4Loopback); | |
| 386 } | |
| 387 | |
| 388 // Crashes on Linux. See webrtc:4923. | |
| 389 #if defined(WEBRTC_LINUX) | |
| 390 #define MAYBE_TestPartialWriteStayWritableIPv6 \ | |
| 391 DISABLED_TestPartialWriteStayWritableIPv6 | |
| 392 #else | |
| 393 #define MAYBE_TestPartialWriteStayWritableIPv6 TestPartialWriteStayWritableIPv6 | |
| 394 #endif | |
| 395 TEST_F(PhysicalSocketTest, MAYBE_TestPartialWriteStayWritableIPv6) { | |
| 396 PartialWriteStayWritable(kIPv6Loopback); | |
| 397 } | |
| 398 | |
| 212 // Crashes on Linux. See webrtc:4923. | 399 // Crashes on Linux. See webrtc:4923. |
| 213 #if defined(WEBRTC_LINUX) | 400 #if defined(WEBRTC_LINUX) |
| 214 #define MAYBE_TestConnectFailIPv6 DISABLED_TestConnectFailIPv6 | 401 #define MAYBE_TestConnectFailIPv6 DISABLED_TestConnectFailIPv6 |
| 215 #else | 402 #else |
| 216 #define MAYBE_TestConnectFailIPv6 TestConnectFailIPv6 | 403 #define MAYBE_TestConnectFailIPv6 TestConnectFailIPv6 |
| 217 #endif | 404 #endif |
| 218 TEST_F(PhysicalSocketTest, MAYBE_TestConnectFailIPv6) { | 405 TEST_F(PhysicalSocketTest, MAYBE_TestConnectFailIPv6) { |
| 219 SocketTest::TestConnectFailIPv6(); | 406 SocketTest::TestConnectFailIPv6(); |
| 220 } | 407 } |
| 221 | 408 |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 517 thread->Start(runnable.get()); | 704 thread->Start(runnable.get()); |
| 518 EXPECT_TRUE(ss_->Wait(1500, true)); | 705 EXPECT_TRUE(ss_->Wait(1500, true)); |
| 519 EXPECT_TRUE(ExpectSignal(SIGTERM)); | 706 EXPECT_TRUE(ExpectSignal(SIGTERM)); |
| 520 EXPECT_EQ(Thread::Current(), signaled_thread_); | 707 EXPECT_EQ(Thread::Current(), signaled_thread_); |
| 521 EXPECT_TRUE(ExpectNone()); | 708 EXPECT_TRUE(ExpectNone()); |
| 522 } | 709 } |
| 523 | 710 |
| 524 #endif | 711 #endif |
| 525 | 712 |
| 526 } // namespace rtc | 713 } // namespace rtc |
| OLD | NEW |