Home | History | Annotate | Download | only in base
      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