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 |