Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/base/listen_socket_unittest.h"
      6 
      7 #include <fcntl.h>
      8 
      9 #include "base/eintr_wrapper.h"
     10 #include "net/base/net_util.h"
     11 #include "testing/platform_test.h"
     12 
     13 const int ListenSocketTester::kTestPort = 9999;
     14 
     15 static const int kReadBufSize = 1024;
     16 static const char* kHelloWorld = "HELLO, WORLD";
     17 static const int kMaxQueueSize = 20;
     18 static const char* kLoopback = "127.0.0.1";
     19 static const int kDefaultTimeoutMs = 5000;
     20 #if defined(OS_POSIX)
     21 static const char* kSemaphoreName = "chromium.listen_socket";
     22 #endif
     23 
     24 
     25 ListenSocket* ListenSocketTester::DoListen() {
     26   return ListenSocket::Listen(kLoopback, kTestPort, this);
     27 }
     28 
     29 void ListenSocketTester::SetUp() {
     30 #if defined(OS_WIN)
     31   InitializeCriticalSection(&lock_);
     32   semaphore_ = CreateSemaphore(NULL, 0, kMaxQueueSize, NULL);
     33   server_ = NULL;
     34   net::EnsureWinsockInit();
     35 #elif defined(OS_POSIX)
     36   ASSERT_EQ(0, pthread_mutex_init(&lock_, NULL));
     37   sem_unlink(kSemaphoreName);
     38   semaphore_ = sem_open(kSemaphoreName, O_CREAT, 0, 0);
     39   ASSERT_NE(SEM_FAILED, semaphore_);
     40 #endif
     41   base::Thread::Options options;
     42   options.message_loop_type = MessageLoop::TYPE_IO;
     43   thread_.reset(new base::Thread("socketio_test"));
     44   thread_->StartWithOptions(options);
     45   loop_ = reinterpret_cast<MessageLoopForIO*>(thread_->message_loop());
     46 
     47   loop_->PostTask(FROM_HERE, NewRunnableMethod(
     48       this, &ListenSocketTester::Listen));
     49 
     50   // verify Listen succeeded
     51   ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
     52   ASSERT_FALSE(server_ == NULL);
     53   ASSERT_EQ(ACTION_LISTEN, last_action_.type());
     54 
     55   // verify the connect/accept and setup test_socket_
     56   test_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     57   ASSERT_NE(-1, test_socket_);
     58   struct sockaddr_in client;
     59   client.sin_family = AF_INET;
     60   client.sin_addr.s_addr = inet_addr(kLoopback);
     61   client.sin_port = htons(kTestPort);
     62   int ret =
     63       HANDLE_EINTR(connect(test_socket_, reinterpret_cast<sockaddr*>(&client),
     64                            sizeof(client)));
     65   ASSERT_NE(ret, SOCKET_ERROR);
     66 
     67   net::SetNonBlocking(test_socket_);
     68   ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
     69   ASSERT_EQ(ACTION_ACCEPT, last_action_.type());
     70 }
     71 
     72 void ListenSocketTester::TearDown() {
     73   // verify close
     74 #if defined(OS_WIN)
     75   closesocket(test_socket_);
     76 #elif defined(OS_POSIX)
     77   close(test_socket_);
     78 #endif
     79   ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
     80   ASSERT_EQ(ACTION_CLOSE, last_action_.type());
     81 
     82   loop_->PostTask(FROM_HERE, NewRunnableMethod(
     83       this, &ListenSocketTester::Shutdown));
     84   ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
     85   ASSERT_EQ(ACTION_SHUTDOWN, last_action_.type());
     86 
     87 #if defined(OS_WIN)
     88   CloseHandle(semaphore_);
     89   semaphore_ = 0;
     90   DeleteCriticalSection(&lock_);
     91 #elif defined(OS_POSIX)
     92   ASSERT_EQ(0, pthread_mutex_lock(&lock_));
     93   semaphore_ = NULL;
     94   ASSERT_EQ(0, pthread_mutex_unlock(&lock_));
     95   ASSERT_EQ(0, sem_unlink(kSemaphoreName));
     96   ASSERT_EQ(0, pthread_mutex_destroy(&lock_));
     97 #endif
     98 
     99   thread_.reset();
    100   loop_ = NULL;
    101 }
    102 
    103 void ListenSocketTester::ReportAction(const ListenSocketTestAction& action) {
    104 #if defined(OS_WIN)
    105   EnterCriticalSection(&lock_);
    106   queue_.push_back(action);
    107   LeaveCriticalSection(&lock_);
    108   ReleaseSemaphore(semaphore_, 1, NULL);
    109 #elif defined(OS_POSIX)
    110   ASSERT_EQ(0, pthread_mutex_lock(&lock_));
    111   queue_.push_back(action);
    112   ASSERT_EQ(0, pthread_mutex_unlock(&lock_));
    113   ASSERT_EQ(0, sem_post(semaphore_));
    114 #endif
    115 }
    116 
    117 bool ListenSocketTester::NextAction(int timeout) {
    118 #if defined(OS_WIN)
    119   DWORD ret = ::WaitForSingleObject(semaphore_, timeout);
    120   if (ret != WAIT_OBJECT_0)
    121     return false;
    122   EnterCriticalSection(&lock_);
    123   if (queue_.size() == 0) {
    124     LeaveCriticalSection(&lock_);
    125     return false;
    126   }
    127   last_action_ = queue_.front();
    128   queue_.pop_front();
    129   LeaveCriticalSection(&lock_);
    130   return true;
    131 #elif defined(OS_POSIX)
    132   if (semaphore_ == SEM_FAILED)
    133     return false;
    134   while (true) {
    135     int result = sem_trywait(semaphore_);
    136     PlatformThread::Sleep(1);  // 1MS sleep
    137     timeout--;
    138     if (timeout <= 0)
    139       return false;
    140     if (result == 0)
    141       break;
    142   }
    143   pthread_mutex_lock(&lock_);
    144   if (queue_.size() == 0) {
    145     pthread_mutex_unlock(&lock_);
    146     return false;
    147   }
    148   last_action_ = queue_.front();
    149   queue_.pop_front();
    150   pthread_mutex_unlock(&lock_);
    151   return true;
    152 #endif
    153 }
    154 
    155 int ListenSocketTester::ClearTestSocket() {
    156   char buf[kReadBufSize];
    157   int len_ret = 0;
    158   int time_out = 0;
    159   do {
    160     int len = HANDLE_EINTR(recv(test_socket_, buf, kReadBufSize, 0));
    161 #if defined(OS_WIN)
    162     if (len == SOCKET_ERROR) {
    163       int err = WSAGetLastError();
    164       if (err == WSAEWOULDBLOCK) {
    165 #elif defined(OS_POSIX)
    166     if (len == SOCKET_ERROR) {
    167       if (errno == EWOULDBLOCK || errno == EAGAIN) {
    168 #endif
    169         PlatformThread::Sleep(1);
    170         time_out++;
    171         if (time_out > 10)
    172           break;
    173         continue;  // still trying
    174       }
    175     } else if (len == 0) {
    176       // socket closed
    177       break;
    178     } else {
    179       time_out = 0;
    180       len_ret += len;
    181     }
    182   } while (true);
    183   return len_ret;
    184 }
    185 
    186 void ListenSocketTester::Shutdown() {
    187   connection_->Release();
    188   connection_ = NULL;
    189   server_->Release();
    190   server_ = NULL;
    191   ReportAction(ListenSocketTestAction(ACTION_SHUTDOWN));
    192 }
    193 
    194 void ListenSocketTester::Listen() {
    195   server_ = DoListen();
    196   if (server_) {
    197     server_->AddRef();
    198     ReportAction(ListenSocketTestAction(ACTION_LISTEN));
    199   }
    200 }
    201 
    202 void ListenSocketTester::SendFromTester() {
    203   connection_->Send(kHelloWorld);
    204   ReportAction(ListenSocketTestAction(ACTION_SEND));
    205 }
    206 
    207 void ListenSocketTester::DidAccept(ListenSocket *server,
    208                                    ListenSocket *connection) {
    209   connection_ = connection;
    210   connection_->AddRef();
    211   ReportAction(ListenSocketTestAction(ACTION_ACCEPT));
    212 }
    213 
    214 void ListenSocketTester::DidRead(ListenSocket *connection,
    215                                  const std::string& data) {
    216   ReportAction(ListenSocketTestAction(ACTION_READ, data));
    217 }
    218 
    219 void ListenSocketTester::DidClose(ListenSocket *sock) {
    220   ReportAction(ListenSocketTestAction(ACTION_CLOSE));
    221 }
    222 
    223 bool ListenSocketTester::Send(SOCKET sock, const std::string& str) {
    224   int len = static_cast<int>(str.length());
    225   int send_len = HANDLE_EINTR(send(sock, str.data(), len, 0));
    226   if (send_len == SOCKET_ERROR) {
    227     LOG(ERROR) << "send failed: " << errno;
    228     return false;
    229   } else if (send_len != len) {
    230     return false;
    231   }
    232   return true;
    233 }
    234 
    235 void ListenSocketTester::TestClientSend() {
    236   ASSERT_TRUE(Send(test_socket_, kHelloWorld));
    237   ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
    238   ASSERT_EQ(ACTION_READ, last_action_.type());
    239   ASSERT_EQ(last_action_.data(), kHelloWorld);
    240 }
    241 
    242 void ListenSocketTester::TestClientSendLong() {
    243   int hello_len = strlen(kHelloWorld);
    244   std::string long_string;
    245   int long_len = 0;
    246   for (int i = 0; i < 200; i++) {
    247     long_string += kHelloWorld;
    248     long_len += hello_len;
    249   }
    250   ASSERT_TRUE(Send(test_socket_, long_string));
    251   int read_len = 0;
    252   while (read_len < long_len) {
    253     ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
    254     ASSERT_EQ(ACTION_READ, last_action_.type());
    255     std::string last_data = last_action_.data();
    256     size_t len = last_data.length();
    257     if (long_string.compare(read_len, len, last_data)) {
    258       ASSERT_EQ(long_string.compare(read_len, len, last_data), 0);
    259     }
    260     read_len += static_cast<int>(last_data.length());
    261   }
    262   ASSERT_EQ(read_len, long_len);
    263 }
    264 
    265 void ListenSocketTester::TestServerSend() {
    266   loop_->PostTask(FROM_HERE, NewRunnableMethod(
    267       this, &ListenSocketTester::SendFromTester));
    268   ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
    269   ASSERT_EQ(ACTION_SEND, last_action_.type());
    270   // TODO(erikkay): Without this sleep, the recv seems to fail a small amount
    271   // of the time.  I could fix this by making the socket blocking, but then
    272   // this test might hang in the case of errors.  It would be nice to do
    273   // something that felt more reliable here.
    274   PlatformThread::Sleep(10);  // sleep for 10ms
    275   const int buf_len = 200;
    276   char buf[buf_len+1];
    277   int recv_len;
    278   do {
    279     recv_len = HANDLE_EINTR(recv(test_socket_, buf, buf_len, 0));
    280 #if defined(OS_POSIX)
    281   } while (recv_len == SOCKET_ERROR && errno == EINTR);
    282 #else
    283   } while (false);
    284 #endif
    285   ASSERT_NE(recv_len, SOCKET_ERROR);
    286   buf[recv_len] = 0;
    287   ASSERT_STREQ(buf, kHelloWorld);
    288 }
    289 
    290 
    291 class ListenSocketTest: public PlatformTest {
    292  public:
    293   ListenSocketTest() {
    294     tester_ = NULL;
    295   }
    296 
    297   virtual void SetUp() {
    298     PlatformTest::SetUp();
    299     tester_ = new ListenSocketTester();
    300     tester_->SetUp();
    301   }
    302 
    303   virtual void TearDown() {
    304     PlatformTest::TearDown();
    305     tester_->TearDown();
    306     tester_ = NULL;
    307   }
    308 
    309   scoped_refptr<ListenSocketTester> tester_;
    310 };
    311 
    312 TEST_F(ListenSocketTest, ClientSend) {
    313   tester_->TestClientSend();
    314 }
    315 
    316 TEST_F(ListenSocketTest, ClientSendLong) {
    317   tester_->TestClientSendLong();
    318 }
    319 
    320 TEST_F(ListenSocketTest, ServerSend) {
    321   tester_->TestServerSend();
    322 }
    323