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 <signal.h> 12 #include <stdarg.h> 13 14 #include "webrtc/base/gunit.h" 15 #include "webrtc/base/logging.h" 16 #include "webrtc/base/physicalsocketserver.h" 17 #include "webrtc/base/scoped_ptr.h" 18 #include "webrtc/base/socket_unittest.h" 19 #include "webrtc/base/testutils.h" 20 #include "webrtc/base/thread.h" 21 22 namespace rtc { 23 24 class PhysicalSocketTest : public SocketTest { 25 }; 26 27 TEST_F(PhysicalSocketTest, TestConnectIPv4) { 28 SocketTest::TestConnectIPv4(); 29 } 30 31 TEST_F(PhysicalSocketTest, TestConnectIPv6) { 32 SocketTest::TestConnectIPv6(); 33 } 34 35 TEST_F(PhysicalSocketTest, TestConnectWithDnsLookupIPv4) { 36 SocketTest::TestConnectWithDnsLookupIPv4(); 37 } 38 39 TEST_F(PhysicalSocketTest, TestConnectWithDnsLookupIPv6) { 40 SocketTest::TestConnectWithDnsLookupIPv6(); 41 } 42 43 TEST_F(PhysicalSocketTest, TestConnectFailIPv4) { 44 SocketTest::TestConnectFailIPv4(); 45 } 46 47 TEST_F(PhysicalSocketTest, TestConnectFailIPv6) { 48 SocketTest::TestConnectFailIPv6(); 49 } 50 51 TEST_F(PhysicalSocketTest, TestConnectWithDnsLookupFailIPv4) { 52 SocketTest::TestConnectWithDnsLookupFailIPv4(); 53 } 54 55 56 TEST_F(PhysicalSocketTest, TestConnectWithDnsLookupFailIPv6) { 57 SocketTest::TestConnectWithDnsLookupFailIPv6(); 58 } 59 60 61 TEST_F(PhysicalSocketTest, TestConnectWithClosedSocketIPv4) { 62 SocketTest::TestConnectWithClosedSocketIPv4(); 63 } 64 65 TEST_F(PhysicalSocketTest, TestConnectWithClosedSocketIPv6) { 66 SocketTest::TestConnectWithClosedSocketIPv6(); 67 } 68 69 TEST_F(PhysicalSocketTest, TestConnectWhileNotClosedIPv4) { 70 SocketTest::TestConnectWhileNotClosedIPv4(); 71 } 72 73 TEST_F(PhysicalSocketTest, TestConnectWhileNotClosedIPv6) { 74 SocketTest::TestConnectWhileNotClosedIPv6(); 75 } 76 77 TEST_F(PhysicalSocketTest, TestServerCloseDuringConnectIPv4) { 78 SocketTest::TestServerCloseDuringConnectIPv4(); 79 } 80 81 TEST_F(PhysicalSocketTest, TestServerCloseDuringConnectIPv6) { 82 SocketTest::TestServerCloseDuringConnectIPv6(); 83 } 84 85 TEST_F(PhysicalSocketTest, TestClientCloseDuringConnectIPv4) { 86 SocketTest::TestClientCloseDuringConnectIPv4(); 87 } 88 89 TEST_F(PhysicalSocketTest, TestClientCloseDuringConnectIPv6) { 90 SocketTest::TestClientCloseDuringConnectIPv6(); 91 } 92 93 TEST_F(PhysicalSocketTest, TestServerCloseIPv4) { 94 SocketTest::TestServerCloseIPv4(); 95 } 96 97 TEST_F(PhysicalSocketTest, TestServerCloseIPv6) { 98 SocketTest::TestServerCloseIPv6(); 99 } 100 101 TEST_F(PhysicalSocketTest, TestCloseInClosedCallbackIPv4) { 102 SocketTest::TestCloseInClosedCallbackIPv4(); 103 } 104 105 TEST_F(PhysicalSocketTest, TestCloseInClosedCallbackIPv6) { 106 SocketTest::TestCloseInClosedCallbackIPv6(); 107 } 108 109 TEST_F(PhysicalSocketTest, TestSocketServerWaitIPv4) { 110 SocketTest::TestSocketServerWaitIPv4(); 111 } 112 113 TEST_F(PhysicalSocketTest, TestSocketServerWaitIPv6) { 114 SocketTest::TestSocketServerWaitIPv6(); 115 } 116 117 TEST_F(PhysicalSocketTest, TestTcpIPv4) { 118 SocketTest::TestTcpIPv4(); 119 } 120 121 TEST_F(PhysicalSocketTest, TestTcpIPv6) { 122 SocketTest::TestTcpIPv6(); 123 } 124 125 TEST_F(PhysicalSocketTest, TestUdpIPv4) { 126 SocketTest::TestUdpIPv4(); 127 } 128 129 TEST_F(PhysicalSocketTest, TestUdpIPv6) { 130 SocketTest::TestUdpIPv6(); 131 } 132 133 TEST_F(PhysicalSocketTest, TestUdpReadyToSendIPv4) { 134 SocketTest::TestUdpReadyToSendIPv4(); 135 } 136 137 TEST_F(PhysicalSocketTest, TestUdpReadyToSendIPv6) { 138 SocketTest::TestUdpReadyToSendIPv6(); 139 } 140 141 TEST_F(PhysicalSocketTest, TestGetSetOptionsIPv4) { 142 SocketTest::TestGetSetOptionsIPv4(); 143 } 144 145 TEST_F(PhysicalSocketTest, TestGetSetOptionsIPv6) { 146 SocketTest::TestGetSetOptionsIPv6(); 147 } 148 149 #if defined(WEBRTC_POSIX) 150 151 class PosixSignalDeliveryTest : public testing::Test { 152 public: 153 static void RecordSignal(int signum) { 154 signals_received_.push_back(signum); 155 signaled_thread_ = Thread::Current(); 156 } 157 158 protected: 159 void SetUp() { 160 ss_.reset(new PhysicalSocketServer()); 161 } 162 163 void TearDown() { 164 ss_.reset(NULL); 165 signals_received_.clear(); 166 signaled_thread_ = NULL; 167 } 168 169 bool ExpectSignal(int signum) { 170 if (signals_received_.empty()) { 171 LOG(LS_ERROR) << "ExpectSignal(): No signal received"; 172 return false; 173 } 174 if (signals_received_[0] != signum) { 175 LOG(LS_ERROR) << "ExpectSignal(): Received signal " << 176 signals_received_[0] << ", expected " << signum; 177 return false; 178 } 179 signals_received_.erase(signals_received_.begin()); 180 return true; 181 } 182 183 bool ExpectNone() { 184 bool ret = signals_received_.empty(); 185 if (!ret) { 186 LOG(LS_ERROR) << "ExpectNone(): Received signal " << signals_received_[0] 187 << ", expected none"; 188 } 189 return ret; 190 } 191 192 static std::vector<int> signals_received_; 193 static Thread *signaled_thread_; 194 195 scoped_ptr<PhysicalSocketServer> ss_; 196 }; 197 198 std::vector<int> PosixSignalDeliveryTest::signals_received_; 199 Thread *PosixSignalDeliveryTest::signaled_thread_ = NULL; 200 201 // Test receiving a synchronous signal while not in Wait() and then entering 202 // Wait() afterwards. 203 TEST_F(PosixSignalDeliveryTest, RaiseThenWait) { 204 ASSERT_TRUE(ss_->SetPosixSignalHandler(SIGTERM, &RecordSignal)); 205 raise(SIGTERM); 206 EXPECT_TRUE(ss_->Wait(0, true)); 207 EXPECT_TRUE(ExpectSignal(SIGTERM)); 208 EXPECT_TRUE(ExpectNone()); 209 } 210 211 // Test that we can handle getting tons of repeated signals and that we see all 212 // the different ones. 213 TEST_F(PosixSignalDeliveryTest, InsanelyManySignals) { 214 ss_->SetPosixSignalHandler(SIGTERM, &RecordSignal); 215 ss_->SetPosixSignalHandler(SIGINT, &RecordSignal); 216 for (int i = 0; i < 10000; ++i) { 217 raise(SIGTERM); 218 } 219 raise(SIGINT); 220 EXPECT_TRUE(ss_->Wait(0, true)); 221 // Order will be lowest signal numbers first. 222 EXPECT_TRUE(ExpectSignal(SIGINT)); 223 EXPECT_TRUE(ExpectSignal(SIGTERM)); 224 EXPECT_TRUE(ExpectNone()); 225 } 226 227 // Test that a signal during a Wait() call is detected. 228 TEST_F(PosixSignalDeliveryTest, SignalDuringWait) { 229 ss_->SetPosixSignalHandler(SIGALRM, &RecordSignal); 230 alarm(1); 231 EXPECT_TRUE(ss_->Wait(1500, true)); 232 EXPECT_TRUE(ExpectSignal(SIGALRM)); 233 EXPECT_TRUE(ExpectNone()); 234 } 235 236 class RaiseSigTermRunnable : public Runnable { 237 void Run(Thread *thread) { 238 thread->socketserver()->Wait(1000, false); 239 240 // Allow SIGTERM. This will be the only thread with it not masked so it will 241 // be delivered to us. 242 sigset_t mask; 243 sigemptyset(&mask); 244 pthread_sigmask(SIG_SETMASK, &mask, NULL); 245 246 // Raise it. 247 raise(SIGTERM); 248 } 249 }; 250 251 // Test that it works no matter what thread the kernel chooses to give the 252 // signal to (since it's not guaranteed to be the one that Wait() runs on). 253 TEST_F(PosixSignalDeliveryTest, SignalOnDifferentThread) { 254 ss_->SetPosixSignalHandler(SIGTERM, &RecordSignal); 255 // Mask out SIGTERM so that it can't be delivered to this thread. 256 sigset_t mask; 257 sigemptyset(&mask); 258 sigaddset(&mask, SIGTERM); 259 EXPECT_EQ(0, pthread_sigmask(SIG_SETMASK, &mask, NULL)); 260 // Start a new thread that raises it. It will have to be delivered to that 261 // thread. Our implementation should safely handle it and dispatch 262 // RecordSignal() on this thread. 263 scoped_ptr<Thread> thread(new Thread()); 264 scoped_ptr<RaiseSigTermRunnable> runnable(new RaiseSigTermRunnable()); 265 thread->Start(runnable.get()); 266 EXPECT_TRUE(ss_->Wait(1500, true)); 267 EXPECT_TRUE(ExpectSignal(SIGTERM)); 268 EXPECT_EQ(Thread::Current(), signaled_thread_); 269 EXPECT_TRUE(ExpectNone()); 270 } 271 272 #endif 273 274 } // namespace rtc 275