Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2010 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 #include <sys/types.h>
      9 
     10 #include "base/eintr_wrapper.h"
     11 #include "net/base/net_util.h"
     12 #include "testing/platform_test.h"
     13 
     14 const int ListenSocketTester::kTestPort = 9999;
     15 
     16 static const int kReadBufSize = 1024;
     17 static const char kHelloWorld[] = "HELLO, WORLD";
     18 static const int kMaxQueueSize = 20;
     19 static const char kLoopback[] = "127.0.0.1";
     20 static const int kDefaultTimeoutMs = 5000;
     21 
     22 ListenSocketTester::ListenSocketTester()
     23     : thread_(NULL),
     24       loop_(NULL),
     25       server_(NULL),
     26       connection_(NULL),
     27       cv_(&lock_) {
     28 }
     29 
     30 void ListenSocketTester::SetUp() {
     31   base::Thread::Options options;
     32   options.message_loop_type = MessageLoop::TYPE_IO;
     33   thread_.reset(new base::Thread("socketio_test"));
     34   thread_->StartWithOptions(options);
     35   loop_ = reinterpret_cast<MessageLoopForIO*>(thread_->message_loop());
     36 
     37   loop_->PostTask(FROM_HERE, NewRunnableMethod(
     38       this, &ListenSocketTester::Listen));
     39 
     40   // verify Listen succeeded
     41   NextAction();
     42   ASSERT_FALSE(server_ == NULL);
     43   ASSERT_EQ(ACTION_LISTEN, last_action_.type());
     44 
     45   // verify the connect/accept and setup test_socket_
     46   test_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     47   ASSERT_NE(INVALID_SOCKET, test_socket_);
     48   struct sockaddr_in client;
     49   client.sin_family = AF_INET;
     50   client.sin_addr.s_addr = inet_addr(kLoopback);
     51   client.sin_port = htons(kTestPort);
     52   int ret = HANDLE_EINTR(
     53       connect(test_socket_, reinterpret_cast<sockaddr*>(&client),
     54               sizeof(client)));
     55   ASSERT_NE(ret, SOCKET_ERROR);
     56 
     57   NextAction();
     58   ASSERT_EQ(ACTION_ACCEPT, last_action_.type());
     59 }
     60 
     61 void ListenSocketTester::TearDown() {
     62 #if defined(OS_WIN)
     63   ASSERT_EQ(0, closesocket(test_socket_));
     64 #elif defined(OS_POSIX)
     65   ASSERT_EQ(0, HANDLE_EINTR(close(test_socket_)));
     66 #endif
     67   NextAction();
     68   ASSERT_EQ(ACTION_CLOSE, last_action_.type());
     69 
     70   loop_->PostTask(FROM_HERE, NewRunnableMethod(
     71       this, &ListenSocketTester::Shutdown));
     72   NextAction();
     73   ASSERT_EQ(ACTION_SHUTDOWN, last_action_.type());
     74 
     75   thread_.reset();
     76   loop_ = NULL;
     77 }
     78 
     79 void ListenSocketTester::ReportAction(const ListenSocketTestAction& action) {
     80   base::AutoLock locked(lock_);
     81   queue_.push_back(action);
     82   cv_.Broadcast();
     83 }
     84 
     85 void ListenSocketTester::NextAction() {
     86   base::AutoLock locked(lock_);
     87   while (queue_.empty())
     88     cv_.Wait();
     89   last_action_ = queue_.front();
     90   queue_.pop_front();
     91 }
     92 
     93 int ListenSocketTester::ClearTestSocket() {
     94   char buf[kReadBufSize];
     95   int len_ret = 0;
     96   do {
     97     int len = HANDLE_EINTR(recv(test_socket_, buf, kReadBufSize, 0));
     98     if (len == SOCKET_ERROR || len == 0) {
     99       break;
    100     } else {
    101       len_ret += len;
    102     }
    103   } while (true);
    104   return len_ret;
    105 }
    106 
    107 void ListenSocketTester::Shutdown() {
    108   connection_->Release();
    109   connection_ = NULL;
    110   server_->Release();
    111   server_ = NULL;
    112   ReportAction(ListenSocketTestAction(ACTION_SHUTDOWN));
    113 }
    114 
    115 void ListenSocketTester::Listen() {
    116   server_ = DoListen();
    117   if (server_) {
    118     server_->AddRef();
    119     ReportAction(ListenSocketTestAction(ACTION_LISTEN));
    120   }
    121 }
    122 
    123 void ListenSocketTester::SendFromTester() {
    124   connection_->Send(kHelloWorld);
    125   ReportAction(ListenSocketTestAction(ACTION_SEND));
    126 }
    127 
    128 void ListenSocketTester::TestClientSend() {
    129   ASSERT_TRUE(Send(test_socket_, kHelloWorld));
    130   NextAction();
    131   ASSERT_EQ(ACTION_READ, last_action_.type());
    132   ASSERT_EQ(last_action_.data(), kHelloWorld);
    133 }
    134 
    135 void ListenSocketTester::TestClientSendLong() {
    136   size_t hello_len = strlen(kHelloWorld);
    137   std::string long_string;
    138   size_t long_len = 0;
    139   for (int i = 0; i < 200; i++) {
    140     long_string += kHelloWorld;
    141     long_len += hello_len;
    142   }
    143   ASSERT_TRUE(Send(test_socket_, long_string));
    144   size_t read_len = 0;
    145   while (read_len < long_len) {
    146     NextAction();
    147     ASSERT_EQ(ACTION_READ, last_action_.type());
    148     std::string last_data = last_action_.data();
    149     size_t len = last_data.length();
    150     if (long_string.compare(read_len, len, last_data)) {
    151       ASSERT_EQ(long_string.compare(read_len, len, last_data), 0);
    152     }
    153     read_len += last_data.length();
    154   }
    155   ASSERT_EQ(read_len, long_len);
    156 }
    157 
    158 void ListenSocketTester::TestServerSend() {
    159   loop_->PostTask(FROM_HERE, NewRunnableMethod(
    160       this, &ListenSocketTester::SendFromTester));
    161   NextAction();
    162   ASSERT_EQ(ACTION_SEND, last_action_.type());
    163   const int buf_len = 200;
    164   char buf[buf_len+1];
    165   unsigned recv_len = 0;
    166   while (recv_len < strlen(kHelloWorld)) {
    167     int r = HANDLE_EINTR(recv(test_socket_, buf, buf_len, 0));
    168     ASSERT_GE(r, 0);
    169     recv_len += static_cast<unsigned>(r);
    170     if (!r)
    171       break;
    172   }
    173   buf[recv_len] = 0;
    174   ASSERT_STREQ(buf, kHelloWorld);
    175 }
    176 
    177 bool ListenSocketTester::Send(SOCKET sock, const std::string& str) {
    178   int len = static_cast<int>(str.length());
    179   int send_len = HANDLE_EINTR(send(sock, str.data(), len, 0));
    180   if (send_len == SOCKET_ERROR) {
    181     LOG(ERROR) << "send failed: " << errno;
    182     return false;
    183   } else if (send_len != len) {
    184     return false;
    185   }
    186   return true;
    187 }
    188 
    189 void ListenSocketTester::DidAccept(ListenSocket *server,
    190                                    ListenSocket *connection) {
    191   connection_ = connection;
    192   connection_->AddRef();
    193   ReportAction(ListenSocketTestAction(ACTION_ACCEPT));
    194 }
    195 
    196 void ListenSocketTester::DidRead(ListenSocket *connection,
    197                                  const char* data,
    198                                  int len) {
    199   std::string str(data, len);
    200   ReportAction(ListenSocketTestAction(ACTION_READ, str));
    201 }
    202 
    203 void ListenSocketTester::DidClose(ListenSocket *sock) {
    204   ReportAction(ListenSocketTestAction(ACTION_CLOSE));
    205 }
    206 
    207 ListenSocketTester::~ListenSocketTester() {}
    208 
    209 ListenSocket* ListenSocketTester::DoListen() {
    210   return ListenSocket::Listen(kLoopback, kTestPort, this);
    211 }
    212 
    213 
    214 class ListenSocketTest: public PlatformTest {
    215  public:
    216   ListenSocketTest() {
    217     tester_ = NULL;
    218   }
    219 
    220   virtual void SetUp() {
    221     PlatformTest::SetUp();
    222     tester_ = new ListenSocketTester();
    223     tester_->SetUp();
    224   }
    225 
    226   virtual void TearDown() {
    227     PlatformTest::TearDown();
    228     tester_->TearDown();
    229     tester_ = NULL;
    230   }
    231 
    232   scoped_refptr<ListenSocketTester> tester_;
    233 };
    234 
    235 TEST_F(ListenSocketTest, ClientSend) {
    236   tester_->TestClientSend();
    237 }
    238 
    239 TEST_F(ListenSocketTest, ClientSendLong) {
    240   tester_->TestClientSendLong();
    241 }
    242 
    243 TEST_F(ListenSocketTest, ServerSend) {
    244   tester_->TestServerSend();
    245 }
    246