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