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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/tcp_client_socket.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/address_list.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log_unittest.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/test_completion_callback.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/winsock_init.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/dns/mock_host_resolver.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_factory.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/socket/tcp_listen_socket.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/platform_test.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kServerReply[] = "HTTP/1.1 404 Not Found";
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ClientSocketTestTypes {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TCP,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SCTP
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TransportClientSocketTest
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public StreamListenSocket::Delegate,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public ::testing::TestWithParam<ClientSocketTestTypes> {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransportClientSocketTest()
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : listen_port_(0),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        socket_factory_(ClientSocketFactory::GetDefaultFactory()),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        close_server_socket_on_next_send_(false) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~TransportClientSocketTest() {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implement StreamListenSocket::Delegate methods
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DidAccept(StreamListenSocket* server,
5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                         scoped_ptr<StreamListenSocket> connection) OVERRIDE {
5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    connected_sock_.reset(
5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        static_cast<TCPListenSocket*>(connection.release()));
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void DidRead(StreamListenSocket*, const char* str, int len) OVERRIDE {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(dkegel): this might not be long enough to tickle some bugs.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connected_sock_->Send(kServerReply, arraysize(kServerReply) - 1,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          false /* Don't append line feed */);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (close_server_socket_on_next_send_)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CloseServerSocket();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void DidClose(StreamListenSocket* sock) OVERRIDE {}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Testcase hooks
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp();
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CloseServerSocket() {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // delete the connected_sock_, which will close it.
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    connected_sock_.reset();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PauseServerReads() {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connected_sock_->PauseReads();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ResumeServerReads() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connected_sock_->ResumeReads();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DrainClientSocket(IOBuffer* buf,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        uint32 buf_len,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        uint32 bytes_to_read,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        TestCompletionCallback* callback);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SendClientRequest();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_close_server_socket_on_next_send(bool close) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    close_server_socket_on_next_send_ = close;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int listen_port_;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapturingNetLog net_log_;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClientSocketFactory* const socket_factory_;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<StreamSocket> sock_;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_ptr<TCPListenSocket> listen_sock_;
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_ptr<TCPListenSocket> connected_sock_;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool close_server_socket_on_next_send_;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransportClientSocketTest::SetUp() {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::testing::TestWithParam<ClientSocketTestTypes>::SetUp();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find a free port to listen on
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_ptr<TCPListenSocket> sock;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int port;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Range of ports to listen on.  Shouldn't need to try many.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kMinPort = 10100;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kMaxPort = 10200;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureWinsockInit();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (port = kMinPort; port < kMaxPort; port++) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sock = TCPListenSocket::CreateAndListen("127.0.0.1", port, this);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sock.get())
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_TRUE(sock.get() != NULL);
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  listen_sock_ = sock.Pass();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listen_port_ = port;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddressList addr;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MockHostResolver resolves everything to 127.0.0.1.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HostResolver> resolver(new MockHostResolver());
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostResolver::RequestInfo info(HostPortPair("localhost", listen_port_));
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int rv = resolver->Resolve(
1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      info, DEFAULT_PRIORITY, &addr, callback.callback(), NULL, BoundNetLog());
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(ERR_IO_PENDING, rv);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback.WaitForResult();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(rv, OK);
1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  sock_ =
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      socket_factory_->CreateTransportClientSocket(addr,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   &net_log_,
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                   NetLog::Source());
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TransportClientSocketTest::DrainClientSocket(
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IOBuffer* buf, uint32 buf_len,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 bytes_to_read, TestCompletionCallback* callback) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = OK;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 bytes_read = 0;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (bytes_read < bytes_to_read) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = sock_->Read(buf, buf_len, callback->callback());
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = callback->WaitForResult();
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GE(rv, 0);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bytes_read += rv;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<int>(bytes_read);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransportClientSocketTest::SendClientRequest() {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> request_buffer(
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new IOBuffer(arraysize(request_text) - 1));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  rv = sock_->Write(
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      request_buffer.get(), arraysize(request_text) - 1, callback.callback());
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback.WaitForResult();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(rv, static_cast<int>(arraysize(request_text) - 1));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(leighton):  Add SCTP to this list when it is ready.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(StreamSocket,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        TransportClientSocketTest,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        ::testing::Values(TCP));
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(TransportClientSocketTest, Connect) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(sock_->IsConnected());
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = sock_->Connect(callback.callback());
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CapturingNetLog::CapturedEntryList net_log_entries;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.GetEntries(&net_log_entries);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(net::LogContainsBeginEvent(
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_entries, 0, net::NetLog::TYPE_SOCKET_ALIVE));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(net::LogContainsBeginEvent(
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_entries, 1, net::NetLog::TYPE_TCP_CONNECT));
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(rv, ERR_IO_PENDING);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback.WaitForResult();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(rv, OK);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sock_->IsConnected());
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.GetEntries(&net_log_entries);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(net::LogContainsEndEvent(
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_entries, -1, net::NetLog::TYPE_TCP_CONNECT));
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sock_->Disconnect();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(sock_->IsConnected());
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(TransportClientSocketTest, IsConnected) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> buf(new IOBuffer(4096));
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 bytes_read;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(sock_->IsConnected());
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(sock_->IsConnectedAndIdle());
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = sock_->Connect(callback.callback());
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(rv, ERR_IO_PENDING);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback.WaitForResult();
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(rv, OK);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sock_->IsConnected());
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sock_->IsConnectedAndIdle());
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send the request and wait for the server to respond.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendClientRequest();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Drain a single byte so we know we've received some data.
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bytes_read = DrainClientSocket(buf.get(), 1, 1, &callback);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(bytes_read, 1u);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Socket should be considered connected, but not idle, due to
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pending data.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sock_->IsConnected());
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(sock_->IsConnectedAndIdle());
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bytes_read = DrainClientSocket(
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      buf.get(), 4096, arraysize(kServerReply) - 2, &callback);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(bytes_read, arraysize(kServerReply) - 2);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // After draining the data, the socket should be back to connected
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and idle.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sock_->IsConnected());
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sock_->IsConnectedAndIdle());
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This time close the server socket immediately after the server response.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_close_server_socket_on_next_send(true);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendClientRequest();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bytes_read = DrainClientSocket(buf.get(), 1, 1, &callback);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(bytes_read, 1u);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // As above because of data.
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sock_->IsConnected());
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(sock_->IsConnectedAndIdle());
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bytes_read = DrainClientSocket(
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      buf.get(), 4096, arraysize(kServerReply) - 2, &callback);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(bytes_read, arraysize(kServerReply) - 2);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Once the data is drained, the socket should now be seen as not
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // connected.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sock_->IsConnected()) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In the unlikely event that the server's connection closure is not
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // processed in time, wait for the connection to be closed.
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rv = sock_->Read(buf.get(), 4096, callback.callback());
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, callback.GetResult(rv));
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(sock_->IsConnected());
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(sock_->IsConnectedAndIdle());
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(TransportClientSocketTest, Read) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = sock_->Connect(callback.callback());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(rv, ERR_IO_PENDING);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback.WaitForResult();
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(rv, OK);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendClientRequest();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> buf(new IOBuffer(4096));
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint32 bytes_read = DrainClientSocket(
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      buf.get(), 4096, arraysize(kServerReply) - 1, &callback);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(bytes_read, arraysize(kServerReply) - 1);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All data has been read now.  Read once more to force an ERR_IO_PENDING, and
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // then close the server socket, and note the close.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  rv = sock_->Read(buf.get(), 4096, callback.callback());
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, rv);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseServerSocket();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, callback.WaitForResult());
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(TransportClientSocketTest, Read_SmallChunks) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = sock_->Connect(callback.callback());
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(rv, ERR_IO_PENDING);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback.WaitForResult();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(rv, OK);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendClientRequest();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> buf(new IOBuffer(1));
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 bytes_read = 0;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (bytes_read < arraysize(kServerReply) - 1) {
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rv = sock_->Read(buf.get(), 1, callback.callback());
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = callback.WaitForResult();
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(1, rv);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bytes_read += rv;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All data has been read now.  Read once more to force an ERR_IO_PENDING, and
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // then close the server socket, and note the close.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  rv = sock_->Read(buf.get(), 1, callback.callback());
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, rv);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseServerSocket();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, callback.WaitForResult());
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(TransportClientSocketTest, Read_Interrupted) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = sock_->Connect(callback.callback());
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERR_IO_PENDING, rv);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback.WaitForResult();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(rv, OK);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendClientRequest();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do a partial read and then exit.  This test should not crash!
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> buf(new IOBuffer(16));
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  rv = sock_->Read(buf.get(), 16, callback.callback());
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (rv == ERR_IO_PENDING)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback.WaitForResult();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(0, rv);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(TransportClientSocketTest, DISABLED_FullDuplex_ReadFirst) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = sock_->Connect(callback.callback());
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(rv, ERR_IO_PENDING);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback.WaitForResult();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(rv, OK);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read first.  There's no data, so it should return ERR_IO_PENDING.
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kBufLen = 4096;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> buf(new IOBuffer(kBufLen));
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  rv = sock_->Read(buf.get(), kBufLen, callback.callback());
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PauseServerReads();
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kWriteBufLen = 64 * 1024;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kWriteBufLen));
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* request_data = request_buffer->data();
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(request_data, 'A', kWriteBufLen);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback write_callback;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rv = sock_->Write(
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        request_buffer.get(), kWriteBufLen, write_callback.callback());
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(rv >= 0 || rv == ERR_IO_PENDING);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING) {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ResumeServerReads();
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = write_callback.WaitForResult();
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At this point, both read and write have returned ERR_IO_PENDING, and the
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // write callback has executed.  We wait for the read callback to run now to
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // make sure that the socket can handle full duplex communications.
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback.WaitForResult();
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(rv, 0);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(TransportClientSocketTest, DISABLED_FullDuplex_WriteFirst) {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = sock_->Connect(callback.callback());
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERR_IO_PENDING, rv);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback.WaitForResult();
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, rv);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PauseServerReads();
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kWriteBufLen = 64 * 1024;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kWriteBufLen));
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* request_data = request_buffer->data();
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(request_data, 'A', kWriteBufLen);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback write_callback;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rv = sock_->Write(
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        request_buffer.get(), kWriteBufLen, write_callback.callback());
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(rv >= 0 || rv == ERR_IO_PENDING);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now we have the Write() blocked on ERR_IO_PENDING.  It's time to force the
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read() to block on ERR_IO_PENDING too.
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kBufLen = 4096;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> buf(new IOBuffer(kBufLen));
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rv = sock_->Read(buf.get(), kBufLen, callback.callback());
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(rv >= 0 || rv == ERR_IO_PENDING);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At this point, both read and write have returned ERR_IO_PENDING.  Now we
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // run the write and read callbacks to make sure they can handle full duplex
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // communications.
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResumeServerReads();
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = write_callback.WaitForResult();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(rv, 0);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's possible the read is blocked because it's already read all the data.
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close the server socket, so there will at least be a 0-byte read.
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseServerSocket();
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback.WaitForResult();
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(rv, 0);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
451