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"
13424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/base/ip_endpoint.h"
14424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/base/net_errors.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/socket/socket_descriptor.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/platform_test.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kReadBufSize = 1024;
2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kHelloWorld[] = "HELLO, WORLD";
2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kLoopback[] = "127.0.0.1";
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TCPListenSocketTester::TCPListenSocketTester()
26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    : loop_(NULL),
27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      cv_(&lock_),
28424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      server_port_(0) {}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::SetUp() {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread::Options options;
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  options.message_loop_type = base::MessageLoop::TYPE_IO;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_.reset(new base::Thread("socketio_test"));
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_->StartWithOptions(options);
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  loop_ = reinterpret_cast<base::MessageLoopForIO*>(thread_->message_loop());
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_->PostTask(FROM_HERE, base::Bind(
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &TCPListenSocketTester::Listen, this));
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // verify Listen succeeded
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NextAction();
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_FALSE(server_.get() == NULL);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ACTION_LISTEN, last_action_.type());
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int server_port = GetServerPort();
46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_GT(server_port, 0);
47424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // verify the connect/accept and setup test_socket_
49424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  test_socket_ = CreatePlatformSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
50424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_NE(kInvalidSocket, test_socket_);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct sockaddr_in client;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client.sin_family = AF_INET;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client.sin_addr.s_addr = inet_addr(kLoopback);
54424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  client.sin_port = base::HostToNet16(server_port);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ret = HANDLE_EINTR(
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connect(test_socket_, reinterpret_cast<sockaddr*>(&client),
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              sizeof(client)));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The connect() call may be interrupted by a signal. When connect()
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is retried on EINTR, it fails with EISCONN.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ret == StreamListenSocket::kSocketError)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(EISCONN, errno);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't have signals.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NE(StreamListenSocket::kSocketError, ret);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NextAction();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ACTION_ACCEPT, last_action_.type());
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::TearDown() {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, closesocket(test_socket_));
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_EQ(0, IGNORE_EINTR(close(test_socket_)));
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NextAction();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ACTION_CLOSE, last_action_.type());
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_->PostTask(FROM_HERE, base::Bind(
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &TCPListenSocketTester::Shutdown, this));
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NextAction();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ACTION_SHUTDOWN, last_action_.type());
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_.reset();
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_ = NULL;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::ReportAction(
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TCPListenSocketTestAction& action) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock locked(lock_);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  queue_.push_back(action);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cv_.Broadcast();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::NextAction() {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock locked(lock_);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (queue_.empty())
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cv_.Wait();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_action_ = queue_.front();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  queue_.pop_front();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPListenSocketTester::ClearTestSocket() {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[kReadBufSize];
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len_ret = 0;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int len = HANDLE_EINTR(recv(test_socket_, buf, kReadBufSize, 0));
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (len == StreamListenSocket::kSocketError || len == 0) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      len_ret += len;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (true);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return len_ret;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::Shutdown() {
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  connection_.reset();
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  server_.reset();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportAction(TCPListenSocketTestAction(ACTION_SHUTDOWN));
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::Listen() {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_ = DoListen();
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_TRUE(server_.get());
128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
129424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // The server's port will be needed to open the client socket.
130424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  IPEndPoint local_address;
131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_EQ(OK, server_->GetLocalAddress(&local_address));
132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  SetServerPort(local_address.port());
133424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportAction(TCPListenSocketTestAction(ACTION_LISTEN));
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::SendFromTester() {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->Send(kHelloWorld);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportAction(TCPListenSocketTestAction(ACTION_SEND));
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::TestClientSend() {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(Send(test_socket_, kHelloWorld));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NextAction();
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ACTION_READ, last_action_.type());
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(last_action_.data(), kHelloWorld);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::TestClientSendLong() {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t hello_len = strlen(kHelloWorld);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string long_string;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t long_len = 0;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 200; i++) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long_string += kHelloWorld;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long_len += hello_len;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(Send(test_socket_, long_string));
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t read_len = 0;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (read_len < long_len) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NextAction();
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ACTION_READ, last_action_.type());
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string last_data = last_action_.data();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t len = last_data.length();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (long_string.compare(read_len, len, last_data)) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(long_string.compare(read_len, len, last_data), 0);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    read_len += last_data.length();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(read_len, long_len);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::TestServerSend() {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_->PostTask(FROM_HERE, base::Bind(
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &TCPListenSocketTester::SendFromTester, this));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NextAction();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ACTION_SEND, last_action_.type());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int buf_len = 200;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[buf_len+1];
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned recv_len = 0;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (recv_len < strlen(kHelloWorld)) {
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int r = HANDLE_EINTR(recv(test_socket_,
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              buf + recv_len, buf_len - recv_len, 0));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_GE(r, 0);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    recv_len += static_cast<unsigned>(r);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!r)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buf[recv_len] = 0;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_STREQ(kHelloWorld, buf);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::TestServerSendMultiple() {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send enough data to exceed the socket receive window. 20kb is probably a
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // safe bet.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int send_count = (1024*20) / (sizeof(kHelloWorld)-1);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Send multiple writes. Since no reading is occurring the data should be
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // buffered in TCPListenSocket.
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < send_count; ++i) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loop_->PostTask(FROM_HERE, base::Bind(
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &TCPListenSocketTester::SendFromTester, this));
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NextAction();
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ACTION_SEND, last_action_.type());
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make multiple reads. All of the data should eventually be returned.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[sizeof(kHelloWorld)];
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int buf_len = sizeof(kHelloWorld);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < send_count; ++i) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned recv_len = 0;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (recv_len < buf_len-1) {
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int r = HANDLE_EINTR(recv(test_socket_,
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                buf + recv_len, buf_len - 1 - recv_len, 0));
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_GE(r, 0);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      recv_len += static_cast<unsigned>(r);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!r)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buf[recv_len] = 0;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_STREQ(kHelloWorld, buf);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPListenSocketTester::Send(SocketDescriptor sock,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const std::string& str) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len = static_cast<int>(str.length());
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int send_len = HANDLE_EINTR(send(sock, str.data(), len, 0));
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (send_len == StreamListenSocket::kSocketError) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "send failed: " << errno;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (send_len != len) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TCPListenSocketTester::DidAccept(
23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    StreamListenSocket* server,
23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_ptr<StreamListenSocket> connection) {
24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  connection_ = connection.Pass();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportAction(TCPListenSocketTestAction(ACTION_ACCEPT));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::DidRead(StreamListenSocket* connection,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const char* data,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int len) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string str(data, len);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportAction(TCPListenSocketTestAction(ACTION_READ, str));
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPListenSocketTester::DidClose(StreamListenSocket* sock) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportAction(TCPListenSocketTestAction(ACTION_CLOSE));
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TCPListenSocketTester::~TCPListenSocketTester() {}
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)scoped_ptr<TCPListenSocket> TCPListenSocketTester::DoListen() {
258424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Let the OS pick a free port.
259424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return TCPListenSocket::CreateAndListen(kLoopback, 0, this);
260424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
261424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
262424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int TCPListenSocketTester::GetServerPort() {
263424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  base::AutoLock locked(lock_);
264424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return server_port_;
265424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
266424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
267424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void TCPListenSocketTester::SetServerPort(int server_port) {
268424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  base::AutoLock locked(lock_);
269424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  server_port_ = server_port;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
272424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)class TCPListenSocketTest : public PlatformTest {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TCPListenSocketTest() {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tester_ = NULL;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PlatformTest::SetUp();
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tester_ = new TCPListenSocketTester();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tester_->SetUp();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PlatformTest::TearDown();
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tester_->TearDown();
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tester_ = NULL;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<TCPListenSocketTester> tester_;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(TCPListenSocketTest, ClientSend) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tester_->TestClientSend();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(TCPListenSocketTest, ClientSendLong) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tester_->TestClientSendLong();
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(TCPListenSocketTest, ServerSend) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tester_->TestServerSend();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(TCPListenSocketTest, ServerSendMultiple) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tester_->TestServerSendMultiple();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
310