OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | |
3 * | |
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 | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include <memory> | |
12 #include <signal.h> | |
13 #include <stdarg.h> | |
14 | |
15 #include "webrtc/base/gunit.h" | |
16 #include "webrtc/base/logging.h" | |
17 #include "webrtc/base/networkmonitor.h" | |
18 #include "webrtc/base/physicalsocketserver.h" | |
19 #include "webrtc/base/socket_unittest.h" | |
20 #include "webrtc/base/testutils.h" | |
21 #include "webrtc/base/thread.h" | |
22 | |
23 namespace rtc { | |
24 | |
25 #define MAYBE_SKIP_IPV4 \ | |
26 if (!HasIPv4Enabled()) { \ | |
27 LOG(LS_INFO) << "No IPv4... skipping"; \ | |
28 return; \ | |
29 } | |
30 | |
31 #define MAYBE_SKIP_IPV6 \ | |
32 if (!HasIPv6Enabled()) { \ | |
33 LOG(LS_INFO) << "No IPv6... skipping"; \ | |
34 return; \ | |
35 } | |
36 | |
37 class PhysicalSocketTest; | |
38 | |
39 class FakeSocketDispatcher : public SocketDispatcher { | |
40 public: | |
41 explicit FakeSocketDispatcher(PhysicalSocketServer* ss) | |
42 : SocketDispatcher(ss) { | |
43 } | |
44 | |
45 FakeSocketDispatcher(SOCKET s, PhysicalSocketServer* ss) | |
46 : SocketDispatcher(s, ss) { | |
47 } | |
48 | |
49 protected: | |
50 SOCKET DoAccept(SOCKET socket, sockaddr* addr, socklen_t* addrlen) override; | |
51 int DoSend(SOCKET socket, const char* buf, int len, int flags) override; | |
52 int DoSendTo(SOCKET socket, const char* buf, int len, int flags, | |
53 const struct sockaddr* dest_addr, socklen_t addrlen) override; | |
54 }; | |
55 | |
56 class FakePhysicalSocketServer : public PhysicalSocketServer { | |
57 public: | |
58 explicit FakePhysicalSocketServer(PhysicalSocketTest* test) | |
59 : test_(test) { | |
60 } | |
61 | |
62 AsyncSocket* CreateAsyncSocket(int type) override { | |
63 SocketDispatcher* dispatcher = new FakeSocketDispatcher(this); | |
64 if (!dispatcher->Create(type)) { | |
65 delete dispatcher; | |
66 return nullptr; | |
67 } | |
68 return dispatcher; | |
69 } | |
70 | |
71 AsyncSocket* CreateAsyncSocket(int family, int type) override { | |
72 SocketDispatcher* dispatcher = new FakeSocketDispatcher(this); | |
73 if (!dispatcher->Create(family, type)) { | |
74 delete dispatcher; | |
75 return nullptr; | |
76 } | |
77 return dispatcher; | |
78 } | |
79 | |
80 AsyncSocket* WrapSocket(SOCKET s) override { | |
81 SocketDispatcher* dispatcher = new FakeSocketDispatcher(s, this); | |
82 if (!dispatcher->Initialize()) { | |
83 delete dispatcher; | |
84 return nullptr; | |
85 } | |
86 return dispatcher; | |
87 } | |
88 | |
89 PhysicalSocketTest* GetTest() const { return test_; } | |
90 | |
91 private: | |
92 PhysicalSocketTest* test_; | |
93 }; | |
94 | |
95 class FakeNetworkBinder : public NetworkBinderInterface { | |
96 public: | |
97 NetworkBindingResult BindSocketToNetwork(int, const IPAddress&) override { | |
98 ++num_binds_; | |
99 return result_; | |
100 } | |
101 | |
102 void set_result(NetworkBindingResult result) { result_ = result; } | |
103 | |
104 int num_binds() { return num_binds_; } | |
105 | |
106 private: | |
107 NetworkBindingResult result_ = NetworkBindingResult::SUCCESS; | |
108 int num_binds_ = 0; | |
109 }; | |
110 | |
111 class PhysicalSocketTest : public SocketTest { | |
112 public: | |
113 // Set flag to simluate failures when calling "::accept" on a AsyncSocket. | |
114 void SetFailAccept(bool fail) { fail_accept_ = fail; } | |
115 bool FailAccept() const { return fail_accept_; } | |
116 | |
117 // Maximum size to ::send to a socket. Set to < 0 to disable limiting. | |
118 void SetMaxSendSize(int max_size) { max_send_size_ = max_size; } | |
119 int MaxSendSize() const { return max_send_size_; } | |
120 | |
121 protected: | |
122 PhysicalSocketTest() | |
123 : server_(new FakePhysicalSocketServer(this)), | |
124 thread_(server_.get()), | |
125 fail_accept_(false), | |
126 max_send_size_(-1) {} | |
127 | |
128 void ConnectInternalAcceptError(const IPAddress& loopback); | |
129 void WritableAfterPartialWrite(const IPAddress& loopback); | |
130 | |
131 std::unique_ptr<FakePhysicalSocketServer> server_; | |
132 rtc::AutoSocketServerThread thread_; | |
133 bool fail_accept_; | |
134 int max_send_size_; | |
135 }; | |
136 | |
137 SOCKET FakeSocketDispatcher::DoAccept(SOCKET socket, | |
138 sockaddr* addr, | |
139 socklen_t* addrlen) { | |
140 FakePhysicalSocketServer* ss = | |
141 static_cast<FakePhysicalSocketServer*>(socketserver()); | |
142 if (ss->GetTest()->FailAccept()) { | |
143 return INVALID_SOCKET; | |
144 } | |
145 | |
146 return SocketDispatcher::DoAccept(socket, addr, addrlen); | |
147 } | |
148 | |
149 int FakeSocketDispatcher::DoSend(SOCKET socket, const char* buf, int len, | |
150 int flags) { | |
151 FakePhysicalSocketServer* ss = | |
152 static_cast<FakePhysicalSocketServer*>(socketserver()); | |
153 if (ss->GetTest()->MaxSendSize() >= 0) { | |
154 len = std::min(len, ss->GetTest()->MaxSendSize()); | |
155 } | |
156 | |
157 return SocketDispatcher::DoSend(socket, buf, len, flags); | |
158 } | |
159 | |
160 int FakeSocketDispatcher::DoSendTo(SOCKET socket, const char* buf, int len, | |
161 int flags, const struct sockaddr* dest_addr, socklen_t addrlen) { | |
162 FakePhysicalSocketServer* ss = | |
163 static_cast<FakePhysicalSocketServer*>(socketserver()); | |
164 if (ss->GetTest()->MaxSendSize() >= 0) { | |
165 len = std::min(len, ss->GetTest()->MaxSendSize()); | |
166 } | |
167 | |
168 return SocketDispatcher::DoSendTo(socket, buf, len, flags, dest_addr, | |
169 addrlen); | |
170 } | |
171 | |
172 TEST_F(PhysicalSocketTest, TestConnectIPv4) { | |
173 MAYBE_SKIP_IPV4; | |
174 SocketTest::TestConnectIPv4(); | |
175 } | |
176 | |
177 TEST_F(PhysicalSocketTest, TestConnectIPv6) { | |
178 SocketTest::TestConnectIPv6(); | |
179 } | |
180 | |
181 TEST_F(PhysicalSocketTest, TestConnectWithDnsLookupIPv4) { | |
182 MAYBE_SKIP_IPV4; | |
183 SocketTest::TestConnectWithDnsLookupIPv4(); | |
184 } | |
185 | |
186 TEST_F(PhysicalSocketTest, TestConnectWithDnsLookupIPv6) { | |
187 SocketTest::TestConnectWithDnsLookupIPv6(); | |
188 } | |
189 | |
190 TEST_F(PhysicalSocketTest, TestConnectFailIPv4) { | |
191 MAYBE_SKIP_IPV4; | |
192 SocketTest::TestConnectFailIPv4(); | |
193 } | |
194 | |
195 void PhysicalSocketTest::ConnectInternalAcceptError(const IPAddress& loopback) { | |
196 webrtc::testing::StreamSink sink; | |
197 SocketAddress accept_addr; | |
198 | |
199 // Create two clients. | |
200 std::unique_ptr<AsyncSocket> client1( | |
201 server_->CreateAsyncSocket(loopback.family(), SOCK_STREAM)); | |
202 sink.Monitor(client1.get()); | |
203 EXPECT_EQ(AsyncSocket::CS_CLOSED, client1->GetState()); | |
204 EXPECT_PRED1(IsUnspecOrEmptyIP, client1->GetLocalAddress().ipaddr()); | |
205 | |
206 std::unique_ptr<AsyncSocket> client2( | |
207 server_->CreateAsyncSocket(loopback.family(), SOCK_STREAM)); | |
208 sink.Monitor(client2.get()); | |
209 EXPECT_EQ(AsyncSocket::CS_CLOSED, client2->GetState()); | |
210 EXPECT_PRED1(IsUnspecOrEmptyIP, client2->GetLocalAddress().ipaddr()); | |
211 | |
212 // Create server and listen. | |
213 std::unique_ptr<AsyncSocket> server( | |
214 server_->CreateAsyncSocket(loopback.family(), SOCK_STREAM)); | |
215 sink.Monitor(server.get()); | |
216 EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0))); | |
217 EXPECT_EQ(0, server->Listen(5)); | |
218 EXPECT_EQ(AsyncSocket::CS_CONNECTING, server->GetState()); | |
219 | |
220 // Ensure no pending server connections, since we haven't done anything yet. | |
221 EXPECT_FALSE(sink.Check(server.get(), webrtc::testing::SSE_READ)); | |
222 EXPECT_TRUE(nullptr == server->Accept(&accept_addr)); | |
223 EXPECT_TRUE(accept_addr.IsNil()); | |
224 | |
225 // Attempt first connect to listening socket. | |
226 EXPECT_EQ(0, client1->Connect(server->GetLocalAddress())); | |
227 EXPECT_FALSE(client1->GetLocalAddress().IsNil()); | |
228 EXPECT_NE(server->GetLocalAddress(), client1->GetLocalAddress()); | |
229 | |
230 // Client is connecting, outcome not yet determined. | |
231 EXPECT_EQ(AsyncSocket::CS_CONNECTING, client1->GetState()); | |
232 EXPECT_FALSE(sink.Check(client1.get(), webrtc::testing::SSE_OPEN)); | |
233 EXPECT_FALSE(sink.Check(client1.get(), webrtc::testing::SSE_CLOSE)); | |
234 | |
235 // Server has pending connection, try to accept it (will fail). | |
236 EXPECT_TRUE_WAIT((sink.Check(server.get(), webrtc::testing::SSE_READ)), | |
237 kTimeout); | |
238 // Simulate "::accept" returning an error. | |
239 SetFailAccept(true); | |
240 std::unique_ptr<AsyncSocket> accepted(server->Accept(&accept_addr)); | |
241 EXPECT_FALSE(accepted); | |
242 ASSERT_TRUE(accept_addr.IsNil()); | |
243 | |
244 // Ensure no more pending server connections. | |
245 EXPECT_FALSE(sink.Check(server.get(), webrtc::testing::SSE_READ)); | |
246 EXPECT_TRUE(nullptr == server->Accept(&accept_addr)); | |
247 EXPECT_TRUE(accept_addr.IsNil()); | |
248 | |
249 // Attempt second connect to listening socket. | |
250 EXPECT_EQ(0, client2->Connect(server->GetLocalAddress())); | |
251 EXPECT_FALSE(client2->GetLocalAddress().IsNil()); | |
252 EXPECT_NE(server->GetLocalAddress(), client2->GetLocalAddress()); | |
253 | |
254 // Client is connecting, outcome not yet determined. | |
255 EXPECT_EQ(AsyncSocket::CS_CONNECTING, client2->GetState()); | |
256 EXPECT_FALSE(sink.Check(client2.get(), webrtc::testing::SSE_OPEN)); | |
257 EXPECT_FALSE(sink.Check(client2.get(), webrtc::testing::SSE_CLOSE)); | |
258 | |
259 // Server has pending connection, try to accept it (will succeed). | |
260 EXPECT_TRUE_WAIT((sink.Check(server.get(), webrtc::testing::SSE_READ)), | |
261 kTimeout); | |
262 SetFailAccept(false); | |
263 std::unique_ptr<AsyncSocket> accepted2(server->Accept(&accept_addr)); | |
264 ASSERT_TRUE(accepted2); | |
265 EXPECT_FALSE(accept_addr.IsNil()); | |
266 EXPECT_EQ(accepted2->GetRemoteAddress(), accept_addr); | |
267 } | |
268 | |
269 TEST_F(PhysicalSocketTest, TestConnectAcceptErrorIPv4) { | |
270 MAYBE_SKIP_IPV4; | |
271 ConnectInternalAcceptError(kIPv4Loopback); | |
272 } | |
273 | |
274 TEST_F(PhysicalSocketTest, TestConnectAcceptErrorIPv6) { | |
275 MAYBE_SKIP_IPV6; | |
276 ConnectInternalAcceptError(kIPv6Loopback); | |
277 } | |
278 | |
279 void PhysicalSocketTest::WritableAfterPartialWrite(const IPAddress& loopback) { | |
280 // Simulate a really small maximum send size. | |
281 const int kMaxSendSize = 128; | |
282 SetMaxSendSize(kMaxSendSize); | |
283 | |
284 // Run the default send/receive socket tests with a smaller amount of data | |
285 // to avoid long running times due to the small maximum send size. | |
286 const size_t kDataSize = 128 * 1024; | |
287 TcpInternal(loopback, kDataSize, kMaxSendSize); | |
288 } | |
289 | |
290 // https://bugs.chromium.org/p/webrtc/issues/detail?id=6167 | |
291 #if defined(WEBRTC_WIN) | |
292 #define MAYBE_TestWritableAfterPartialWriteIPv4 DISABLED_TestWritableAfterPartia
lWriteIPv4 | |
293 #else | |
294 #define MAYBE_TestWritableAfterPartialWriteIPv4 TestWritableAfterPartialWriteIPv
4 | |
295 #endif | |
296 TEST_F(PhysicalSocketTest, MAYBE_TestWritableAfterPartialWriteIPv4) { | |
297 MAYBE_SKIP_IPV4; | |
298 WritableAfterPartialWrite(kIPv4Loopback); | |
299 } | |
300 | |
301 // https://bugs.chromium.org/p/webrtc/issues/detail?id=6167 | |
302 #if defined(WEBRTC_WIN) | |
303 #define MAYBE_TestWritableAfterPartialWriteIPv6 DISABLED_TestWritableAfterPartia
lWriteIPv6 | |
304 #else | |
305 #define MAYBE_TestWritableAfterPartialWriteIPv6 TestWritableAfterPartialWriteIPv
6 | |
306 #endif | |
307 TEST_F(PhysicalSocketTest, MAYBE_TestWritableAfterPartialWriteIPv6) { | |
308 MAYBE_SKIP_IPV6; | |
309 WritableAfterPartialWrite(kIPv6Loopback); | |
310 } | |
311 | |
312 TEST_F(PhysicalSocketTest, TestConnectFailIPv6) { | |
313 SocketTest::TestConnectFailIPv6(); | |
314 } | |
315 | |
316 TEST_F(PhysicalSocketTest, TestConnectWithDnsLookupFailIPv4) { | |
317 MAYBE_SKIP_IPV4; | |
318 SocketTest::TestConnectWithDnsLookupFailIPv4(); | |
319 } | |
320 | |
321 TEST_F(PhysicalSocketTest, TestConnectWithDnsLookupFailIPv6) { | |
322 SocketTest::TestConnectWithDnsLookupFailIPv6(); | |
323 } | |
324 | |
325 | |
326 TEST_F(PhysicalSocketTest, TestConnectWithClosedSocketIPv4) { | |
327 MAYBE_SKIP_IPV4; | |
328 SocketTest::TestConnectWithClosedSocketIPv4(); | |
329 } | |
330 | |
331 TEST_F(PhysicalSocketTest, TestConnectWithClosedSocketIPv6) { | |
332 SocketTest::TestConnectWithClosedSocketIPv6(); | |
333 } | |
334 | |
335 TEST_F(PhysicalSocketTest, TestConnectWhileNotClosedIPv4) { | |
336 MAYBE_SKIP_IPV4; | |
337 SocketTest::TestConnectWhileNotClosedIPv4(); | |
338 } | |
339 | |
340 TEST_F(PhysicalSocketTest, TestConnectWhileNotClosedIPv6) { | |
341 SocketTest::TestConnectWhileNotClosedIPv6(); | |
342 } | |
343 | |
344 TEST_F(PhysicalSocketTest, TestServerCloseDuringConnectIPv4) { | |
345 MAYBE_SKIP_IPV4; | |
346 SocketTest::TestServerCloseDuringConnectIPv4(); | |
347 } | |
348 | |
349 TEST_F(PhysicalSocketTest, TestServerCloseDuringConnectIPv6) { | |
350 SocketTest::TestServerCloseDuringConnectIPv6(); | |
351 } | |
352 | |
353 TEST_F(PhysicalSocketTest, TestClientCloseDuringConnectIPv4) { | |
354 MAYBE_SKIP_IPV4; | |
355 SocketTest::TestClientCloseDuringConnectIPv4(); | |
356 } | |
357 | |
358 TEST_F(PhysicalSocketTest, TestClientCloseDuringConnectIPv6) { | |
359 SocketTest::TestClientCloseDuringConnectIPv6(); | |
360 } | |
361 | |
362 TEST_F(PhysicalSocketTest, TestServerCloseIPv4) { | |
363 MAYBE_SKIP_IPV4; | |
364 SocketTest::TestServerCloseIPv4(); | |
365 } | |
366 | |
367 TEST_F(PhysicalSocketTest, TestServerCloseIPv6) { | |
368 SocketTest::TestServerCloseIPv6(); | |
369 } | |
370 | |
371 TEST_F(PhysicalSocketTest, TestCloseInClosedCallbackIPv4) { | |
372 MAYBE_SKIP_IPV4; | |
373 SocketTest::TestCloseInClosedCallbackIPv4(); | |
374 } | |
375 | |
376 TEST_F(PhysicalSocketTest, TestCloseInClosedCallbackIPv6) { | |
377 SocketTest::TestCloseInClosedCallbackIPv6(); | |
378 } | |
379 | |
380 TEST_F(PhysicalSocketTest, TestSocketServerWaitIPv4) { | |
381 MAYBE_SKIP_IPV4; | |
382 SocketTest::TestSocketServerWaitIPv4(); | |
383 } | |
384 | |
385 TEST_F(PhysicalSocketTest, TestSocketServerWaitIPv6) { | |
386 SocketTest::TestSocketServerWaitIPv6(); | |
387 } | |
388 | |
389 TEST_F(PhysicalSocketTest, TestTcpIPv4) { | |
390 MAYBE_SKIP_IPV4; | |
391 SocketTest::TestTcpIPv4(); | |
392 } | |
393 | |
394 TEST_F(PhysicalSocketTest, TestTcpIPv6) { | |
395 SocketTest::TestTcpIPv6(); | |
396 } | |
397 | |
398 TEST_F(PhysicalSocketTest, TestUdpIPv4) { | |
399 MAYBE_SKIP_IPV4; | |
400 SocketTest::TestUdpIPv4(); | |
401 } | |
402 | |
403 TEST_F(PhysicalSocketTest, TestUdpIPv6) { | |
404 SocketTest::TestUdpIPv6(); | |
405 } | |
406 | |
407 // Disable for TSan v2, see | |
408 // https://code.google.com/p/webrtc/issues/detail?id=3498 for details. | |
409 // Also disable for MSan, see: | |
410 // https://code.google.com/p/webrtc/issues/detail?id=4958 | |
411 // TODO(deadbeef): Enable again once test is reimplemented to be unflaky. | |
412 // Also disable for ASan. | |
413 // Disabled on Android: https://code.google.com/p/webrtc/issues/detail?id=4364 | |
414 // Disabled on Linux: https://bugs.chromium.org/p/webrtc/issues/detail?id=5233 | |
415 #if defined(THREAD_SANITIZER) || defined(MEMORY_SANITIZER) || \ | |
416 defined(ADDRESS_SANITIZER) || defined(WEBRTC_ANDROID) || \ | |
417 defined(WEBRTC_LINUX) | |
418 #define MAYBE_TestUdpReadyToSendIPv4 DISABLED_TestUdpReadyToSendIPv4 | |
419 #else | |
420 #define MAYBE_TestUdpReadyToSendIPv4 TestUdpReadyToSendIPv4 | |
421 #endif | |
422 TEST_F(PhysicalSocketTest, MAYBE_TestUdpReadyToSendIPv4) { | |
423 MAYBE_SKIP_IPV4; | |
424 SocketTest::TestUdpReadyToSendIPv4(); | |
425 } | |
426 | |
427 // https://bugs.chromium.org/p/webrtc/issues/detail?id=6167 | |
428 #if defined(WEBRTC_WIN) | |
429 #define MAYBE_TestUdpReadyToSendIPv6 DISABLED_TestUdpReadyToSendIPv6 | |
430 #else | |
431 #define MAYBE_TestUdpReadyToSendIPv6 TestUdpReadyToSendIPv6 | |
432 #endif | |
433 TEST_F(PhysicalSocketTest, MAYBE_TestUdpReadyToSendIPv6) { | |
434 SocketTest::TestUdpReadyToSendIPv6(); | |
435 } | |
436 | |
437 TEST_F(PhysicalSocketTest, TestGetSetOptionsIPv4) { | |
438 MAYBE_SKIP_IPV4; | |
439 SocketTest::TestGetSetOptionsIPv4(); | |
440 } | |
441 | |
442 TEST_F(PhysicalSocketTest, TestGetSetOptionsIPv6) { | |
443 SocketTest::TestGetSetOptionsIPv6(); | |
444 } | |
445 | |
446 #if defined(WEBRTC_POSIX) | |
447 | |
448 // We don't get recv timestamps on Mac. | |
449 #if !defined(WEBRTC_MAC) | |
450 TEST_F(PhysicalSocketTest, TestSocketRecvTimestampIPv4) { | |
451 MAYBE_SKIP_IPV4; | |
452 SocketTest::TestSocketRecvTimestampIPv4(); | |
453 } | |
454 | |
455 TEST_F(PhysicalSocketTest, TestSocketRecvTimestampIPv6) { | |
456 SocketTest::TestSocketRecvTimestampIPv6(); | |
457 } | |
458 #endif | |
459 | |
460 // Verify that if the socket was unable to be bound to a real network interface | |
461 // (not loopback), Bind will return an error. | |
462 TEST_F(PhysicalSocketTest, | |
463 BindFailsIfNetworkBinderFailsForNonLoopbackInterface) { | |
464 MAYBE_SKIP_IPV4; | |
465 FakeNetworkBinder fake_network_binder; | |
466 server_->set_network_binder(&fake_network_binder); | |
467 std::unique_ptr<AsyncSocket> socket( | |
468 server_->CreateAsyncSocket(AF_INET, SOCK_DGRAM)); | |
469 fake_network_binder.set_result(NetworkBindingResult::FAILURE); | |
470 EXPECT_EQ(-1, socket->Bind(SocketAddress("192.168.0.1", 0))); | |
471 server_->set_network_binder(nullptr); | |
472 } | |
473 | |
474 // Network binder shouldn't be used if the socket is bound to the "any" IP. | |
475 TEST_F(PhysicalSocketTest, | |
476 NetworkBinderIsNotUsedForAnyIp) { | |
477 MAYBE_SKIP_IPV4; | |
478 FakeNetworkBinder fake_network_binder; | |
479 server_->set_network_binder(&fake_network_binder); | |
480 std::unique_ptr<AsyncSocket> socket( | |
481 server_->CreateAsyncSocket(AF_INET, SOCK_DGRAM)); | |
482 EXPECT_EQ(0, socket->Bind(SocketAddress("0.0.0.0", 0))); | |
483 EXPECT_EQ(0, fake_network_binder.num_binds()); | |
484 server_->set_network_binder(nullptr); | |
485 } | |
486 | |
487 // For a loopback interface, failures to bind to the interface should be | |
488 // tolerated. | |
489 TEST_F(PhysicalSocketTest, | |
490 BindSucceedsIfNetworkBinderFailsForLoopbackInterface) { | |
491 MAYBE_SKIP_IPV4; | |
492 FakeNetworkBinder fake_network_binder; | |
493 server_->set_network_binder(&fake_network_binder); | |
494 std::unique_ptr<AsyncSocket> socket( | |
495 server_->CreateAsyncSocket(AF_INET, SOCK_DGRAM)); | |
496 fake_network_binder.set_result(NetworkBindingResult::FAILURE); | |
497 EXPECT_EQ(0, socket->Bind(SocketAddress(kIPv4Loopback, 0))); | |
498 server_->set_network_binder(nullptr); | |
499 } | |
500 | |
501 class PosixSignalDeliveryTest : public testing::Test { | |
502 public: | |
503 static void RecordSignal(int signum) { | |
504 signals_received_.push_back(signum); | |
505 signaled_thread_ = Thread::Current(); | |
506 } | |
507 | |
508 protected: | |
509 void SetUp() { | |
510 ss_.reset(new PhysicalSocketServer()); | |
511 } | |
512 | |
513 void TearDown() { | |
514 ss_.reset(nullptr); | |
515 signals_received_.clear(); | |
516 signaled_thread_ = nullptr; | |
517 } | |
518 | |
519 bool ExpectSignal(int signum) { | |
520 if (signals_received_.empty()) { | |
521 LOG(LS_ERROR) << "ExpectSignal(): No signal received"; | |
522 return false; | |
523 } | |
524 if (signals_received_[0] != signum) { | |
525 LOG(LS_ERROR) << "ExpectSignal(): Received signal " << | |
526 signals_received_[0] << ", expected " << signum; | |
527 return false; | |
528 } | |
529 signals_received_.erase(signals_received_.begin()); | |
530 return true; | |
531 } | |
532 | |
533 bool ExpectNone() { | |
534 bool ret = signals_received_.empty(); | |
535 if (!ret) { | |
536 LOG(LS_ERROR) << "ExpectNone(): Received signal " << signals_received_[0] | |
537 << ", expected none"; | |
538 } | |
539 return ret; | |
540 } | |
541 | |
542 static std::vector<int> signals_received_; | |
543 static Thread *signaled_thread_; | |
544 | |
545 std::unique_ptr<PhysicalSocketServer> ss_; | |
546 }; | |
547 | |
548 std::vector<int> PosixSignalDeliveryTest::signals_received_; | |
549 Thread* PosixSignalDeliveryTest::signaled_thread_ = nullptr; | |
550 | |
551 // Test receiving a synchronous signal while not in Wait() and then entering | |
552 // Wait() afterwards. | |
553 TEST_F(PosixSignalDeliveryTest, RaiseThenWait) { | |
554 ASSERT_TRUE(ss_->SetPosixSignalHandler(SIGTERM, &RecordSignal)); | |
555 raise(SIGTERM); | |
556 EXPECT_TRUE(ss_->Wait(0, true)); | |
557 EXPECT_TRUE(ExpectSignal(SIGTERM)); | |
558 EXPECT_TRUE(ExpectNone()); | |
559 } | |
560 | |
561 // Test that we can handle getting tons of repeated signals and that we see all | |
562 // the different ones. | |
563 TEST_F(PosixSignalDeliveryTest, InsanelyManySignals) { | |
564 ss_->SetPosixSignalHandler(SIGTERM, &RecordSignal); | |
565 ss_->SetPosixSignalHandler(SIGINT, &RecordSignal); | |
566 for (int i = 0; i < 10000; ++i) { | |
567 raise(SIGTERM); | |
568 } | |
569 raise(SIGINT); | |
570 EXPECT_TRUE(ss_->Wait(0, true)); | |
571 // Order will be lowest signal numbers first. | |
572 EXPECT_TRUE(ExpectSignal(SIGINT)); | |
573 EXPECT_TRUE(ExpectSignal(SIGTERM)); | |
574 EXPECT_TRUE(ExpectNone()); | |
575 } | |
576 | |
577 // Test that a signal during a Wait() call is detected. | |
578 TEST_F(PosixSignalDeliveryTest, SignalDuringWait) { | |
579 ss_->SetPosixSignalHandler(SIGALRM, &RecordSignal); | |
580 alarm(1); | |
581 EXPECT_TRUE(ss_->Wait(1500, true)); | |
582 EXPECT_TRUE(ExpectSignal(SIGALRM)); | |
583 EXPECT_TRUE(ExpectNone()); | |
584 } | |
585 | |
586 class RaiseSigTermRunnable : public Runnable { | |
587 void Run(Thread *thread) { | |
588 thread->socketserver()->Wait(1000, false); | |
589 | |
590 // Allow SIGTERM. This will be the only thread with it not masked so it will | |
591 // be delivered to us. | |
592 sigset_t mask; | |
593 sigemptyset(&mask); | |
594 pthread_sigmask(SIG_SETMASK, &mask, nullptr); | |
595 | |
596 // Raise it. | |
597 raise(SIGTERM); | |
598 } | |
599 }; | |
600 | |
601 // Test that it works no matter what thread the kernel chooses to give the | |
602 // signal to (since it's not guaranteed to be the one that Wait() runs on). | |
603 TEST_F(PosixSignalDeliveryTest, SignalOnDifferentThread) { | |
604 ss_->SetPosixSignalHandler(SIGTERM, &RecordSignal); | |
605 // Mask out SIGTERM so that it can't be delivered to this thread. | |
606 sigset_t mask; | |
607 sigemptyset(&mask); | |
608 sigaddset(&mask, SIGTERM); | |
609 EXPECT_EQ(0, pthread_sigmask(SIG_SETMASK, &mask, nullptr)); | |
610 // Start a new thread that raises it. It will have to be delivered to that | |
611 // thread. Our implementation should safely handle it and dispatch | |
612 // RecordSignal() on this thread. | |
613 std::unique_ptr<Thread> thread(new Thread()); | |
614 std::unique_ptr<RaiseSigTermRunnable> runnable(new RaiseSigTermRunnable()); | |
615 thread->Start(runnable.get()); | |
616 EXPECT_TRUE(ss_->Wait(1500, true)); | |
617 EXPECT_TRUE(ExpectSignal(SIGTERM)); | |
618 EXPECT_EQ(Thread::Current(), signaled_thread_); | |
619 EXPECT_TRUE(ExpectNone()); | |
620 } | |
621 | |
622 #endif | |
623 | |
624 } // namespace rtc | |
OLD | NEW |