tcp_listen_socket_unittest.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/socket/tcp_listen_socket_unittest.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_byteorder.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/platform_test.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int TCPListenSocketTester::kTestPort = 9999;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kReadBufSize = 1024;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kHelloWorld[] = "HELLO, WORLD";
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMaxQueueSize = 20;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kLoopback[] = "127.0.0.1";
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kDefaultTimeoutMs = 5000;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TCPListenSocketTester::TCPListenSocketTester()
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : thread_(NULL),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      loop_(NULL),
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_(NULL),
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_(NULL),
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cv_(&lock_) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::SetUp() {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread::Options options;
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  options.message_loop_type = base::MessageLoop::TYPE_IO;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_.reset(new base::Thread("socketio_test"));
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_->StartWithOptions(options);
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  loop_ = reinterpret_cast<base::MessageLoopForIO*>(thread_->message_loop());
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_->PostTask(FROM_HERE, base::Bind(
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &TCPListenSocketTester::Listen, this));
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // verify Listen succeeded
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NextAction();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(server_ == NULL);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ACTION_LISTEN, last_action_.type());
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // verify the connect/accept and setup test_socket_
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NE(StreamListenSocket::kInvalidSocket, test_socket_);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct sockaddr_in client;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client.sin_family = AF_INET;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client.sin_addr.s_addr = inet_addr(kLoopback);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client.sin_port = base::HostToNet16(kTestPort);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ret = HANDLE_EINTR(
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connect(test_socket_, reinterpret_cast<sockaddr*>(&client),
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              sizeof(client)));
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The connect() call may be interrupted by a signal. When connect()
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is retried on EINTR, it fails with EISCONN.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ret == StreamListenSocket::kSocketError)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(EISCONN, errno);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't have signals.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NE(StreamListenSocket::kSocketError, ret);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NextAction();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ACTION_ACCEPT, last_action_.type());
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::TearDown() {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, closesocket(test_socket_));
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, HANDLE_EINTR(close(test_socket_)));
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NextAction();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ACTION_CLOSE, last_action_.type());
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_->PostTask(FROM_HERE, base::Bind(
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &TCPListenSocketTester::Shutdown, this));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NextAction();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ACTION_SHUTDOWN, last_action_.type());
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_.reset();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_ = NULL;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::ReportAction(
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TCPListenSocketTestAction& action) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock locked(lock_);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  queue_.push_back(action);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cv_.Broadcast();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::NextAction() {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock locked(lock_);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (queue_.empty())
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cv_.Wait();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_action_ = queue_.front();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  queue_.pop_front();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPListenSocketTester::ClearTestSocket() {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[kReadBufSize];
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len_ret = 0;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int len = HANDLE_EINTR(recv(test_socket_, buf, kReadBufSize, 0));
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (len == StreamListenSocket::kSocketError || len == 0) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      len_ret += len;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (true);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return len_ret;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::Shutdown() {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->Release();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_ = NULL;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_->Release();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_ = NULL;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportAction(TCPListenSocketTestAction(ACTION_SHUTDOWN));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::Listen() {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_ = DoListen();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(server_);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_->AddRef();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportAction(TCPListenSocketTestAction(ACTION_LISTEN));
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::SendFromTester() {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->Send(kHelloWorld);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportAction(TCPListenSocketTestAction(ACTION_SEND));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::TestClientSend() {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(Send(test_socket_, kHelloWorld));
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NextAction();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ACTION_READ, last_action_.type());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(last_action_.data(), kHelloWorld);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::TestClientSendLong() {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t hello_len = strlen(kHelloWorld);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string long_string;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t long_len = 0;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 200; i++) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long_string += kHelloWorld;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long_len += hello_len;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(Send(test_socket_, long_string));
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t read_len = 0;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (read_len < long_len) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NextAction();
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ACTION_READ, last_action_.type());
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string last_data = last_action_.data();
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t len = last_data.length();
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (long_string.compare(read_len, len, last_data)) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(long_string.compare(read_len, len, last_data), 0);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    read_len += last_data.length();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(read_len, long_len);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::TestServerSend() {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_->PostTask(FROM_HERE, base::Bind(
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &TCPListenSocketTester::SendFromTester, this));
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NextAction();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ACTION_SEND, last_action_.type());
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int buf_len = 200;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[buf_len+1];
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned recv_len = 0;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (recv_len < strlen(kHelloWorld)) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int r = HANDLE_EINTR(recv(test_socket_,
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              buf + recv_len, buf_len - recv_len, 0));
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_GE(r, 0);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    recv_len += static_cast<unsigned>(r);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!r)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buf[recv_len] = 0;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_STREQ(kHelloWorld, buf);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::TestServerSendMultiple() {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send enough data to exceed the socket receive window. 20kb is probably a
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // safe bet.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int send_count = (1024*20) / (sizeof(kHelloWorld)-1);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Send multiple writes. Since no reading is occurring the data should be
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // buffered in TCPListenSocket.
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < send_count; ++i) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loop_->PostTask(FROM_HERE, base::Bind(
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &TCPListenSocketTester::SendFromTester, this));
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NextAction();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ACTION_SEND, last_action_.type());
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make multiple reads. All of the data should eventually be returned.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[sizeof(kHelloWorld)];
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int buf_len = sizeof(kHelloWorld);
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < send_count; ++i) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned recv_len = 0;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (recv_len < buf_len-1) {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int r = HANDLE_EINTR(recv(test_socket_,
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                buf + recv_len, buf_len - 1 - recv_len, 0));
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_GE(r, 0);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      recv_len += static_cast<unsigned>(r);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!r)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buf[recv_len] = 0;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_STREQ(kHelloWorld, buf);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPListenSocketTester::Send(SocketDescriptor sock,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const std::string& str) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len = static_cast<int>(str.length());
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int send_len = HANDLE_EINTR(send(sock, str.data(), len, 0));
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (send_len == StreamListenSocket::kSocketError) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "send failed: " << errno;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (send_len != len) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::DidAccept(StreamListenSocket* server,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      StreamListenSocket* connection) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_ = connection;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->AddRef();
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportAction(TCPListenSocketTestAction(ACTION_ACCEPT));
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::DidRead(StreamListenSocket* connection,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const char* data,
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int len) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string str(data, len);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportAction(TCPListenSocketTestAction(ACTION_READ, str));
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::DidClose(StreamListenSocket* sock) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportAction(TCPListenSocketTestAction(ACTION_CLOSE));
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TCPListenSocketTester::~TCPListenSocketTester() {}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<TCPListenSocket> TCPListenSocketTester::DoListen() {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCPListenSocket::CreateAndListen(kLoopback, kTestPort, this);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TCPListenSocketTest: public PlatformTest {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TCPListenSocketTest() {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tester_ = NULL;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PlatformTest::SetUp();
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tester_ = new TCPListenSocketTester();
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tester_->SetUp();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PlatformTest::TearDown();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tester_->TearDown();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tester_ = NULL;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<TCPListenSocketTester> tester_;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(TCPListenSocketTest, ClientSend) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tester_->TestClientSend();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(TCPListenSocketTest, ClientSendLong) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tester_->TestClientSendLong();
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(TCPListenSocketTest, ServerSend) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tester_->TestServerSend();
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(TCPListenSocketTest, ServerSendMultiple) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tester_->TestServerSendMultiple();
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
297