Home | History | Annotate | Download | only in spdy
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/spdy/spdy_proxy_client_socket.h"
      6 
      7 #include "base/utf_string_conversions.h"
      8 #include "net/base/address_list.h"
      9 #include "net/base/net_log.h"
     10 #include "net/base/net_log_unittest.h"
     11 #include "net/base/mock_host_resolver.h"
     12 #include "net/base/test_completion_callback.h"
     13 #include "net/base/winsock_init.h"
     14 #include "net/http/http_response_info.h"
     15 #include "net/http/http_response_headers.h"
     16 #include "net/socket/client_socket_factory.h"
     17 #include "net/socket/tcp_client_socket.h"
     18 #include "net/socket/socket_test_util.h"
     19 #include "net/spdy/spdy_http_utils.h"
     20 #include "net/spdy/spdy_protocol.h"
     21 #include "net/spdy/spdy_session_pool.h"
     22 #include "net/spdy/spdy_test_util.h"
     23 #include "testing/platform_test.h"
     24 #include "testing/gtest/include/gtest/gtest.h"
     25 
     26 //-----------------------------------------------------------------------------
     27 
     28 namespace {
     29 
     30 static const char kUrl[] = "https://www.google.com/";
     31 static const char kOriginHost[] = "www.google.com";
     32 static const int kOriginPort = 443;
     33 static const char kOriginHostPort[] = "www.google.com:443";
     34 static const char kProxyUrl[] = "http://myproxy:6121/";
     35 static const char kProxyHost[] = "myproxy";
     36 static const int kProxyPort = 6121;
     37 static const char kUserAgent[] = "Mozilla/1.0";
     38 
     39 static const int kStreamId = 1;
     40 
     41 static const char kMsg1[] = "\0hello!\xff";
     42 static const int kLen1 = 8;
     43 static const char kMsg2[] = "\012345678\0";
     44 static const int kLen2 = 10;
     45 static const char kMsg3[] = "bye!";
     46 static const int kLen3 = 4;
     47 static const char kMsg33[] = "bye!bye!";
     48 static const int kLen33 = kLen3 + kLen3;
     49 static const char kMsg333[] = "bye!bye!bye!";
     50 static const int kLen333 = kLen3 + kLen3 + kLen3;
     51 
     52 }  // anonymous namespace
     53 
     54 namespace net {
     55 
     56 class SpdyProxyClientSocketTest : public PlatformTest {
     57  public:
     58   SpdyProxyClientSocketTest();
     59 
     60   virtual void TearDown();
     61 
     62  protected:
     63   void Initialize(MockRead* reads, size_t reads_count, MockWrite* writes,
     64                   size_t writes_count);
     65   spdy::SpdyFrame* ConstructConnectRequestFrame();
     66   spdy::SpdyFrame* ConstructConnectAuthRequestFrame();
     67   spdy::SpdyFrame* ConstructConnectReplyFrame();
     68   spdy::SpdyFrame* ConstructConnectAuthReplyFrame();
     69   spdy::SpdyFrame* ConstructConnectErrorReplyFrame();
     70   spdy::SpdyFrame* ConstructBodyFrame(const char* data, int length);
     71   scoped_refptr<IOBufferWithSize> CreateBuffer(const char* data, int size);
     72   void AssertConnectSucceeds();
     73   void AssertConnectFails(int result);
     74   void AssertConnectionEstablished();
     75   void AssertSyncReadEquals(const char* data, int len);
     76   void AssertAsyncReadEquals(const char* data, int len);
     77   void AssertReadStarts(const char* data, int len);
     78   void AssertReadReturns(const char* data, int len);
     79   void AssertAsyncWriteSucceeds(const char* data, int len);
     80   void AssertWriteReturns(const char* data, int len, int rv);
     81   void AssertWriteLength(int len);
     82   void AssertAsyncWriteWithReadsSucceeds(const char* data, int len,
     83                                         int num_reads);
     84 
     85   void AddAuthToCache() {
     86     const string16 kFoo(ASCIIToUTF16("foo"));
     87     const string16 kBar(ASCIIToUTF16("bar"));
     88     session_->http_auth_cache()->Add(GURL(kProxyUrl),
     89                                      "MyRealm1",
     90                                      HttpAuth::AUTH_SCHEME_BASIC,
     91                                      "Basic realm=MyRealm1",
     92                                      kFoo,
     93                                      kBar,
     94                                      "/");
     95   }
     96 
     97   void Run(int steps) {
     98     data_->StopAfter(steps);
     99     data_->Run();
    100   }
    101 
    102   scoped_ptr<SpdyProxyClientSocket> sock_;
    103   TestCompletionCallback read_callback_;
    104   TestCompletionCallback write_callback_;
    105   scoped_refptr<DeterministicSocketData> data_;
    106 
    107  private:
    108   scoped_refptr<HttpNetworkSession> session_;
    109   scoped_refptr<IOBuffer> read_buf_;
    110   SpdySessionDependencies session_deps_;
    111   MockConnect connect_data_;
    112   scoped_refptr<SpdySession> spdy_session_;
    113   scoped_refptr<SpdyStream> spdy_stream_;
    114   spdy::SpdyFramer framer_;
    115 
    116   std::string user_agent_;
    117   GURL url_;
    118   HostPortPair proxy_host_port_;
    119   HostPortPair endpoint_host_port_pair_;
    120   ProxyServer proxy_;
    121   HostPortProxyPair endpoint_host_port_proxy_pair_;
    122   scoped_refptr<TransportSocketParams> transport_params_;
    123 
    124   DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocketTest);
    125 };
    126 
    127 SpdyProxyClientSocketTest::SpdyProxyClientSocketTest()
    128     : sock_(NULL),
    129       read_callback_(),
    130       write_callback_(),
    131       data_(NULL),
    132       session_(NULL),
    133       read_buf_(NULL),
    134       session_deps_(),
    135       connect_data_(false, OK),
    136       spdy_session_(NULL),
    137       spdy_stream_(NULL),
    138       framer_(),
    139       user_agent_(kUserAgent),
    140       url_(kUrl),
    141       proxy_host_port_(kProxyHost, kProxyPort),
    142       endpoint_host_port_pair_(kOriginHost, kOriginPort),
    143       proxy_(ProxyServer::SCHEME_HTTPS, proxy_host_port_),
    144       endpoint_host_port_proxy_pair_(endpoint_host_port_pair_, proxy_),
    145       transport_params_(new TransportSocketParams(proxy_host_port_,
    146                                             LOWEST,
    147                                             url_,
    148                                             false,
    149                                             false)) {
    150 }
    151 
    152 void SpdyProxyClientSocketTest::TearDown() {
    153   if (session_ != NULL)
    154     session_->spdy_session_pool()->CloseAllSessions();
    155 
    156   spdy::SpdyFramer::set_enable_compression_default(true);
    157   // Empty the current queue.
    158   MessageLoop::current()->RunAllPending();
    159   PlatformTest::TearDown();
    160 }
    161 
    162 void SpdyProxyClientSocketTest::Initialize(MockRead* reads,
    163                                            size_t reads_count,
    164                                            MockWrite* writes,
    165                                            size_t writes_count) {
    166   data_ = new DeterministicSocketData(reads, reads_count, writes, writes_count);
    167   data_->set_connect_data(connect_data_);
    168   data_->SetStop(2);
    169 
    170   session_deps_.deterministic_socket_factory->AddSocketDataProvider(
    171       data_.get());
    172   session_deps_.host_resolver->set_synchronous_mode(true);
    173 
    174   session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
    175       &session_deps_);
    176   SpdySession::SetSSLMode(false);
    177   spdy::SpdyFramer::set_enable_compression_default(false);
    178 
    179   // Creates a new spdy session
    180   spdy_session_ =
    181       session_->spdy_session_pool()->Get(endpoint_host_port_proxy_pair_,
    182                                          BoundNetLog());
    183 
    184   // Perform the TCP connect
    185   scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
    186   EXPECT_EQ(OK,
    187             connection->Init(endpoint_host_port_pair_.ToString(),
    188                              transport_params_,
    189                              LOWEST, NULL, session_->transport_socket_pool(),
    190                              BoundNetLog()));
    191   spdy_session_->InitializeWithSocket(connection.release(), false, OK);
    192 
    193   // Create the SPDY Stream
    194   ASSERT_EQ(
    195       OK,
    196       spdy_session_->CreateStream(url_, LOWEST, &spdy_stream_, BoundNetLog(),
    197                                   NULL));
    198 
    199   // Create the SpdyProxyClientSocket
    200   sock_.reset(
    201       new SpdyProxyClientSocket(spdy_stream_, user_agent_,
    202                                 endpoint_host_port_pair_, url_,
    203                                 proxy_host_port_, session_->http_auth_cache(),
    204                                 session_->http_auth_handler_factory()));
    205 }
    206 
    207 scoped_refptr<IOBufferWithSize> SpdyProxyClientSocketTest::CreateBuffer(
    208     const char* data, int size) {
    209   scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(size));
    210   memcpy(buf->data(), data, size);
    211   return buf;
    212 }
    213 
    214 void SpdyProxyClientSocketTest::AssertConnectSucceeds() {
    215   ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(&read_callback_));
    216   data_->Run();
    217   ASSERT_EQ(OK, read_callback_.WaitForResult());
    218 }
    219 
    220 void SpdyProxyClientSocketTest::AssertConnectFails(int result) {
    221   ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(&read_callback_));
    222   data_->Run();
    223   ASSERT_EQ(result, read_callback_.WaitForResult());
    224 }
    225 
    226 void SpdyProxyClientSocketTest::AssertConnectionEstablished() {
    227   const HttpResponseInfo* response = sock_->GetConnectResponseInfo();
    228   ASSERT_TRUE(response != NULL);
    229   ASSERT_EQ(200, response->headers->response_code());
    230   ASSERT_EQ("Connection Established", response->headers->GetStatusText());
    231 }
    232 
    233 void SpdyProxyClientSocketTest::AssertSyncReadEquals(const char* data,
    234                                                      int len) {
    235   scoped_refptr<IOBuffer> buf(new IOBuffer(len));
    236   ASSERT_EQ(len, sock_->Read(buf, len, NULL));
    237   ASSERT_EQ(std::string(data, len), std::string(buf->data(), len));
    238   ASSERT_TRUE(sock_->IsConnected());
    239 }
    240 
    241 void SpdyProxyClientSocketTest::AssertAsyncReadEquals(const char* data,
    242                                                      int len) {
    243   data_->StopAfter(1);
    244   // Issue the read, which will be completed asynchronously
    245   scoped_refptr<IOBuffer> buf(new IOBuffer(len));
    246   ASSERT_EQ(ERR_IO_PENDING, sock_->Read(buf, len, &read_callback_));
    247   EXPECT_TRUE(sock_->IsConnected());
    248   data_->Run();
    249 
    250   EXPECT_TRUE(sock_->IsConnected());
    251 
    252   // Now the read will return
    253   EXPECT_EQ(len, read_callback_.WaitForResult());
    254   ASSERT_EQ(std::string(data, len), std::string(buf->data(), len));
    255 }
    256 
    257 void SpdyProxyClientSocketTest::AssertReadStarts(const char* data, int len) {
    258   data_->StopAfter(1);
    259   // Issue the read, which will be completed asynchronously
    260   read_buf_ = new IOBuffer(len);
    261   ASSERT_EQ(ERR_IO_PENDING, sock_->Read(read_buf_, len, &read_callback_));
    262   EXPECT_TRUE(sock_->IsConnected());
    263 }
    264 
    265 void SpdyProxyClientSocketTest::AssertReadReturns(const char* data, int len) {
    266   EXPECT_TRUE(sock_->IsConnected());
    267 
    268   // Now the read will return
    269   EXPECT_EQ(len, read_callback_.WaitForResult());
    270   ASSERT_EQ(std::string(data, len), std::string(read_buf_->data(), len));
    271 }
    272 
    273 void SpdyProxyClientSocketTest::AssertAsyncWriteSucceeds(const char* data,
    274                                                         int len) {
    275   AssertWriteReturns(data, len, ERR_IO_PENDING);
    276   data_->RunFor(1);
    277   AssertWriteLength(len);
    278 }
    279 
    280 void SpdyProxyClientSocketTest::AssertWriteReturns(const char* data, int len,
    281                                                    int rv) {
    282   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(data, len));
    283   EXPECT_EQ(rv, sock_->Write(buf, buf->size(), &write_callback_));
    284 }
    285 
    286 void SpdyProxyClientSocketTest::AssertWriteLength(int len) {
    287   EXPECT_EQ(len, write_callback_.WaitForResult());
    288 }
    289 
    290 void SpdyProxyClientSocketTest::AssertAsyncWriteWithReadsSucceeds(
    291     const char* data, int len, int num_reads) {
    292   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(data, len));
    293 
    294   EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), &write_callback_));
    295 
    296   for (int i = 0; i < num_reads; i++) {
    297     Run(1);
    298     AssertSyncReadEquals(kMsg2, kLen2);
    299   }
    300 
    301   write_callback_.WaitForResult();
    302 }
    303 
    304 // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
    305 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectRequestFrame() {
    306   const SpdyHeaderInfo kSynStartHeader = {
    307     spdy::SYN_STREAM,
    308     kStreamId,
    309     0,
    310     net::ConvertRequestPriorityToSpdyPriority(LOWEST),
    311     spdy::CONTROL_FLAG_NONE,
    312     false,
    313     spdy::INVALID,
    314     NULL,
    315     0,
    316     spdy::DATA_FLAG_NONE
    317   };
    318   const char* const kConnectHeaders[] = {
    319     "method", "CONNECT",
    320     "url", kOriginHostPort,
    321     "host", kOriginHost,
    322     "user-agent", kUserAgent,
    323     "version", "HTTP/1.1",
    324   };
    325   return ConstructSpdyPacket(
    326       kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2);
    327 }
    328 
    329 // Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes
    330 // Proxy-Authorization headers.
    331 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() {
    332   const SpdyHeaderInfo kSynStartHeader = {
    333     spdy::SYN_STREAM,
    334     kStreamId,
    335     0,
    336     net::ConvertRequestPriorityToSpdyPriority(LOWEST),
    337     spdy::CONTROL_FLAG_NONE,
    338     false,
    339     spdy::INVALID,
    340     NULL,
    341     0,
    342     spdy::DATA_FLAG_NONE
    343   };
    344   const char* const kConnectHeaders[] = {
    345     "method", "CONNECT",
    346     "url", kOriginHostPort,
    347     "host", kOriginHost,
    348     "user-agent", kUserAgent,
    349     "version", "HTTP/1.1",
    350     "proxy-authorization", "Basic Zm9vOmJhcg==",
    351   };
    352   return ConstructSpdyPacket(
    353       kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2);
    354 }
    355 
    356 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT.
    357 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() {
    358   const char* const kStandardReplyHeaders[] = {
    359       "status", "200 Connection Established",
    360       "version", "HTTP/1.1"
    361   };
    362   return ConstructSpdyControlFrame(NULL,
    363                                    0,
    364                                    false,
    365                                    kStreamId,
    366                                    LOWEST,
    367                                    spdy::SYN_REPLY,
    368                                    spdy::CONTROL_FLAG_NONE,
    369                                    kStandardReplyHeaders,
    370                                    arraysize(kStandardReplyHeaders));
    371 }
    372 
    373 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT.
    374 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() {
    375   const char* const kStandardReplyHeaders[] = {
    376       "status", "407 Proxy Authentication Required",
    377       "version", "HTTP/1.1",
    378       "proxy-authenticate", "Basic realm=\"MyRealm1\"",
    379   };
    380 
    381   return ConstructSpdyControlFrame(NULL,
    382                                    0,
    383                                    false,
    384                                    kStreamId,
    385                                    LOWEST,
    386                                    spdy::SYN_REPLY,
    387                                    spdy::CONTROL_FLAG_NONE,
    388                                    kStandardReplyHeaders,
    389                                    arraysize(kStandardReplyHeaders));
    390 }
    391 
    392 // Constructs a SPDY SYN_REPLY frame with an HTTP 500 error.
    393 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() {
    394   const char* const kStandardReplyHeaders[] = {
    395       "status", "500 Internal Server Error",
    396       "version", "HTTP/1.1",
    397   };
    398 
    399   return ConstructSpdyControlFrame(NULL,
    400                                    0,
    401                                    false,
    402                                    kStreamId,
    403                                    LOWEST,
    404                                    spdy::SYN_REPLY,
    405                                    spdy::CONTROL_FLAG_NONE,
    406                                    kStandardReplyHeaders,
    407                                    arraysize(kStandardReplyHeaders));
    408 }
    409 
    410 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructBodyFrame(const char* data,
    411                                                                int length) {
    412   return framer_.CreateDataFrame(kStreamId, data, length, spdy::DATA_FLAG_NONE);
    413 }
    414 
    415 // ----------- Connect
    416 
    417 TEST_F(SpdyProxyClientSocketTest, ConnectSendsCorrectRequest) {
    418   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    419   MockWrite writes[] = {
    420     CreateMockWrite(*conn, 0, false),
    421   };
    422 
    423   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    424   MockRead reads[] = {
    425     CreateMockRead(*resp, 1, true),
    426     MockRead(true, 0, 3),  // EOF
    427   };
    428 
    429   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    430 
    431   ASSERT_FALSE(sock_->IsConnected());
    432 
    433   AssertConnectSucceeds();
    434 
    435   AssertConnectionEstablished();
    436 }
    437 
    438 TEST_F(SpdyProxyClientSocketTest, ConnectWithAuthRequested) {
    439   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    440   MockWrite writes[] = {
    441     CreateMockWrite(*conn, 0, false),
    442   };
    443 
    444   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectAuthReplyFrame());
    445   MockRead reads[] = {
    446     CreateMockRead(*resp, 1, true),
    447     MockRead(true, 0, 3),  // EOF
    448   };
    449 
    450   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    451 
    452   AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED);
    453 
    454   const HttpResponseInfo* response = sock_->GetConnectResponseInfo();
    455   ASSERT_TRUE(response != NULL);
    456   ASSERT_EQ(407, response->headers->response_code());
    457   ASSERT_EQ("Proxy Authentication Required",
    458             response->headers->GetStatusText());
    459 }
    460 
    461 TEST_F(SpdyProxyClientSocketTest, ConnectWithAuthCredentials) {
    462   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectAuthRequestFrame());
    463   MockWrite writes[] = {
    464     CreateMockWrite(*conn, 0, false),
    465   };
    466 
    467   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    468   MockRead reads[] = {
    469     CreateMockRead(*resp, 1, true),
    470     MockRead(true, 0, 3),  // EOF
    471   };
    472 
    473   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    474   AddAuthToCache();
    475 
    476   AssertConnectSucceeds();
    477 
    478   AssertConnectionEstablished();
    479 }
    480 
    481 TEST_F(SpdyProxyClientSocketTest, ConnectFails) {
    482   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    483   MockWrite writes[] = {
    484     CreateMockWrite(*conn, 0, false),
    485   };
    486 
    487   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    488   MockRead reads[] = {
    489     MockRead(true, 0, 1),  // EOF
    490   };
    491 
    492   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    493 
    494   ASSERT_FALSE(sock_->IsConnected());
    495 
    496   AssertConnectFails(ERR_CONNECTION_CLOSED);
    497 
    498   ASSERT_FALSE(sock_->IsConnected());
    499 }
    500 
    501 // ----------- WasEverUsed
    502 
    503 TEST_F(SpdyProxyClientSocketTest, WasEverUsedReturnsCorrectValues) {
    504   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    505   MockWrite writes[] = {
    506     CreateMockWrite(*conn, 0, false),
    507   };
    508 
    509   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    510   MockRead reads[] = {
    511     CreateMockRead(*resp, 1, true),
    512     MockRead(true, 0, 2),  // EOF
    513   };
    514 
    515   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    516 
    517   EXPECT_FALSE(sock_->WasEverUsed());
    518   AssertConnectSucceeds();
    519   EXPECT_TRUE(sock_->WasEverUsed());
    520   sock_->Disconnect();
    521   EXPECT_TRUE(sock_->WasEverUsed());
    522 }
    523 
    524 // ----------- GetPeerAddress
    525 
    526 TEST_F(SpdyProxyClientSocketTest, GetPeerAddressReturnsCorrectValues) {
    527   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    528   MockWrite writes[] = {
    529     CreateMockWrite(*conn, 0, false),
    530   };
    531 
    532   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    533   MockRead reads[] = {
    534     CreateMockRead(*resp, 1, true),
    535     MockRead(true, 0, 2),  // EOF
    536   };
    537 
    538   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    539 
    540   net::AddressList addr;
    541   EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr));
    542 
    543   AssertConnectSucceeds();
    544   EXPECT_TRUE(sock_->IsConnected());
    545   EXPECT_EQ(OK, sock_->GetPeerAddress(&addr));
    546 
    547   sock_->Disconnect();
    548   EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr));
    549 }
    550 
    551 // ----------- Write
    552 
    553 TEST_F(SpdyProxyClientSocketTest, WriteSendsDataInDataFrame) {
    554   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    555   scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
    556   scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
    557   MockWrite writes[] = {
    558     CreateMockWrite(*conn, 0, false),
    559     CreateMockWrite(*msg1, 2, false),
    560     CreateMockWrite(*msg2, 3, false),
    561   };
    562 
    563   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    564   MockRead reads[] = {
    565     CreateMockRead(*resp, 1, true),
    566     MockRead(true, 0, 4),  // EOF
    567   };
    568 
    569   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    570 
    571   AssertConnectSucceeds();
    572 
    573   AssertAsyncWriteSucceeds(kMsg1, kLen1);
    574   AssertAsyncWriteSucceeds(kMsg2, kLen2);
    575 }
    576 
    577 TEST_F(SpdyProxyClientSocketTest, WriteSplitsLargeDataIntoMultipleFrames) {
    578   std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
    579   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    580   scoped_ptr<spdy::SpdyFrame> chunk(ConstructBodyFrame(chunk_data.data(),
    581                                                        chunk_data.length()));
    582   MockWrite writes[] = {
    583     CreateMockWrite(*conn, 0, false),
    584     CreateMockWrite(*chunk, 2, false),
    585     CreateMockWrite(*chunk, 3, false),
    586     CreateMockWrite(*chunk, 4, false)
    587   };
    588 
    589   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    590   MockRead reads[] = {
    591     CreateMockRead(*resp, 1, true),
    592     MockRead(true, 0, 5),  // EOF
    593   };
    594 
    595   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    596 
    597   AssertConnectSucceeds();
    598 
    599   std::string big_data(kMaxSpdyFrameChunkSize * 3, 'x');
    600   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(big_data.data(),
    601                                                    big_data.length()));
    602 
    603   EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), &write_callback_));
    604   data_->RunFor(3);
    605 
    606   EXPECT_EQ(buf->size(), write_callback_.WaitForResult());
    607 }
    608 
    609 // ----------- Read
    610 
    611 TEST_F(SpdyProxyClientSocketTest, ReadReadsDataInDataFrame) {
    612   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    613   MockWrite writes[] = {
    614     CreateMockWrite(*conn, 0, false),
    615   };
    616 
    617   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    618   scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
    619   MockRead reads[] = {
    620     CreateMockRead(*resp, 1, true),
    621     CreateMockRead(*msg1, 2, true),
    622     MockRead(true, 0, 3),  // EOF
    623   };
    624 
    625   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    626 
    627   AssertConnectSucceeds();
    628 
    629   Run(1);  // SpdySession consumes the next read and sends it to
    630            // sock_ to be buffered.
    631   AssertSyncReadEquals(kMsg1, kLen1);
    632 }
    633 
    634 TEST_F(SpdyProxyClientSocketTest, ReadDataFromBufferedFrames) {
    635   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    636   MockWrite writes[] = {
    637     CreateMockWrite(*conn, 0, false),
    638   };
    639 
    640   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    641   scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
    642   scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
    643   MockRead reads[] = {
    644     CreateMockRead(*resp, 1, true),
    645     CreateMockRead(*msg1, 2, true),
    646     CreateMockRead(*msg2, 3, true),
    647     MockRead(true, 0, 4),  // EOF
    648   };
    649 
    650   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    651 
    652   AssertConnectSucceeds();
    653 
    654   Run(1);  // SpdySession consumes the next read and sends it to
    655            // sock_ to be buffered.
    656   AssertSyncReadEquals(kMsg1, kLen1);
    657   Run(1);  // SpdySession consumes the next read and sends it to
    658            // sock_ to be buffered.
    659   AssertSyncReadEquals(kMsg2, kLen2);
    660 }
    661 
    662 TEST_F(SpdyProxyClientSocketTest, ReadDataMultipleBufferedFrames) {
    663   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    664   MockWrite writes[] = {
    665     CreateMockWrite(*conn, 0, false),
    666   };
    667 
    668   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    669   scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
    670   scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
    671   MockRead reads[] = {
    672     CreateMockRead(*resp, 1, true),
    673     CreateMockRead(*msg1, 2, true),
    674     CreateMockRead(*msg2, 3, true),
    675     MockRead(true, 0, 4),  // EOF
    676   };
    677 
    678   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    679 
    680   AssertConnectSucceeds();
    681 
    682   Run(2);  // SpdySession consumes the next two reads and sends then to
    683            // sock_ to be buffered.
    684   AssertSyncReadEquals(kMsg1, kLen1);
    685   AssertSyncReadEquals(kMsg2, kLen2);
    686 }
    687 
    688 TEST_F(SpdyProxyClientSocketTest, LargeReadWillMergeDataFromDifferentFrames) {
    689   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    690   MockWrite writes[] = {
    691     CreateMockWrite(*conn, 0, false),
    692   };
    693 
    694   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    695   scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
    696   scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
    697   MockRead reads[] = {
    698     CreateMockRead(*resp, 1, true),
    699     CreateMockRead(*msg3, 2, true),
    700     CreateMockRead(*msg3, 3, true),
    701     MockRead(true, 0, 4),  // EOF
    702   };
    703 
    704   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    705 
    706   AssertConnectSucceeds();
    707 
    708   Run(2);  // SpdySession consumes the next two reads and sends then to
    709            // sock_ to be buffered.
    710   // The payload from two data frames, each with kMsg3 will be combined
    711   // together into a single read().
    712   AssertSyncReadEquals(kMsg33, kLen33);
    713 }
    714 
    715 TEST_F(SpdyProxyClientSocketTest, MultipleShortReadsThenMoreRead) {
    716   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    717   MockWrite writes[] = {
    718     CreateMockWrite(*conn, 0, false),
    719   };
    720 
    721   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    722   scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
    723   scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
    724   scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
    725   MockRead reads[] = {
    726     CreateMockRead(*resp, 1, true),
    727     CreateMockRead(*msg1, 2, true),
    728     CreateMockRead(*msg3, 3, true),
    729     CreateMockRead(*msg3, 4, true),
    730     CreateMockRead(*msg2, 5, true),
    731     MockRead(true, 0, 6),  // EOF
    732   };
    733 
    734   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    735 
    736   AssertConnectSucceeds();
    737 
    738   Run(4);  // SpdySession consumes the next four reads and sends then to
    739            // sock_ to be buffered.
    740   AssertSyncReadEquals(kMsg1, kLen1);
    741   // The payload from two data frames, each with kMsg3 will be combined
    742   // together into a single read().
    743   AssertSyncReadEquals(kMsg33, kLen33);
    744   AssertSyncReadEquals(kMsg2, kLen2);
    745 }
    746 
    747 TEST_F(SpdyProxyClientSocketTest, ReadWillSplitDataFromLargeFrame) {
    748   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    749   MockWrite writes[] = {
    750     CreateMockWrite(*conn, 0, false),
    751   };
    752 
    753   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    754   scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
    755   scoped_ptr<spdy::SpdyFrame> msg33(ConstructBodyFrame(kMsg33, kLen33));
    756   scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
    757   MockRead reads[] = {
    758     CreateMockRead(*resp, 1, true),
    759     CreateMockRead(*msg1, 2, true),
    760     CreateMockRead(*msg33, 3, true),
    761     MockRead(true, 0, 4),  // EOF
    762   };
    763 
    764   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    765 
    766   AssertConnectSucceeds();
    767 
    768   Run(2);  // SpdySession consumes the next two reads and sends then to
    769            // sock_ to be buffered.
    770   AssertSyncReadEquals(kMsg1, kLen1);
    771   // The payload from the single large data frame will be read across
    772   // two different reads.
    773   AssertSyncReadEquals(kMsg3, kLen3);
    774   AssertSyncReadEquals(kMsg3, kLen3);
    775 }
    776 
    777 TEST_F(SpdyProxyClientSocketTest, MultipleReadsFromSameLargeFrame) {
    778   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    779   MockWrite writes[] = {
    780     CreateMockWrite(*conn, 0, false),
    781   };
    782 
    783   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    784   scoped_ptr<spdy::SpdyFrame> msg333(ConstructBodyFrame(kMsg333, kLen333));
    785   MockRead reads[] = {
    786     CreateMockRead(*resp, 1, true),
    787     CreateMockRead(*msg333, 2, true),
    788     MockRead(true, 0, 3),  // EOF
    789   };
    790 
    791   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    792 
    793   AssertConnectSucceeds();
    794 
    795   Run(1);  // SpdySession consumes the next read and sends it to
    796            // sock_ to be buffered.
    797   // The payload from the single large data frame will be read across
    798   // two different reads.
    799   AssertSyncReadEquals(kMsg33, kLen33);
    800 
    801   // Now attempt to do a read of more data than remains buffered
    802   scoped_refptr<IOBuffer> buf(new IOBuffer(kLen33));
    803   ASSERT_EQ(kLen3, sock_->Read(buf, kLen33, &read_callback_));
    804   ASSERT_EQ(std::string(kMsg3, kLen3), std::string(buf->data(), kLen3));
    805   ASSERT_TRUE(sock_->IsConnected());
    806 }
    807 
    808 TEST_F(SpdyProxyClientSocketTest, ReadAuthResponseBody) {
    809   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    810   MockWrite writes[] = {
    811     CreateMockWrite(*conn, 0, false),
    812   };
    813 
    814   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectAuthReplyFrame());
    815   scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
    816   scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
    817   MockRead reads[] = {
    818     CreateMockRead(*resp, 1, true),
    819     CreateMockRead(*msg1, 2, true),
    820     CreateMockRead(*msg2, 3, true),
    821     MockRead(true, 0, 4),  // EOF
    822   };
    823 
    824   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    825 
    826   AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED);
    827 
    828   Run(2);  // SpdySession consumes the next two reads and sends then to
    829            // sock_ to be buffered.
    830   AssertSyncReadEquals(kMsg1, kLen1);
    831   AssertSyncReadEquals(kMsg2, kLen2);
    832 }
    833 
    834 TEST_F(SpdyProxyClientSocketTest, ReadErrorResponseBody) {
    835   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    836   MockWrite writes[] = {
    837     CreateMockWrite(*conn, 0, false),
    838   };
    839 
    840   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectErrorReplyFrame());
    841   scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
    842   scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
    843   MockRead reads[] = {
    844     CreateMockRead(*resp, 1, true),
    845     CreateMockRead(*msg1, 2, true),
    846     CreateMockRead(*msg2, 3, true),
    847     MockRead(true, 0, 4),  // EOF
    848   };
    849 
    850   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    851 
    852   AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
    853 
    854   Run(2);  // SpdySession consumes the next two reads and sends then to
    855            // sock_ to be buffered.
    856   EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->Read(NULL, 1, NULL));
    857   scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1 + kLen2));
    858   scoped_ptr<HttpStream> stream(sock_->CreateConnectResponseStream());
    859   stream->ReadResponseBody(buf, kLen1 + kLen2, &read_callback_);
    860 }
    861 
    862 // ----------- Reads and Writes
    863 
    864 TEST_F(SpdyProxyClientSocketTest, AsyncReadAroundWrite) {
    865   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    866   scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
    867   MockWrite writes[] = {
    868     CreateMockWrite(*conn, 0, false),
    869     CreateMockWrite(*msg2, 3, false),
    870   };
    871 
    872   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    873   scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
    874   scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
    875   MockRead reads[] = {
    876     CreateMockRead(*resp, 1, true),
    877     CreateMockRead(*msg1, 2, true),  // sync read
    878     CreateMockRead(*msg3, 4, true),  // async read
    879     MockRead(true, 0, 5),  // EOF
    880   };
    881 
    882   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    883 
    884   AssertConnectSucceeds();
    885 
    886   Run(1);
    887   AssertSyncReadEquals(kMsg1, kLen1);
    888 
    889   AssertReadStarts(kMsg3, kLen3);
    890   // Read should block until after the write succeeds
    891 
    892   AssertAsyncWriteSucceeds(kMsg2, kLen2);  // Runs 1 step
    893 
    894   ASSERT_FALSE(read_callback_.have_result());
    895   Run(1);
    896   // Now the read will return
    897   AssertReadReturns(kMsg3, kLen3);
    898 }
    899 
    900 TEST_F(SpdyProxyClientSocketTest, AsyncWriteAroundReads) {
    901   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    902   scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
    903   MockWrite writes[] = {
    904     CreateMockWrite(*conn, 0, false),
    905     CreateMockWrite(*msg2, 4, true),
    906   };
    907 
    908   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    909   scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
    910   scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
    911   MockRead reads[] = {
    912     CreateMockRead(*resp, 1, true),
    913     CreateMockRead(*msg1, 2, true),
    914     CreateMockRead(*msg3, 3, true),
    915     MockRead(true, 0, 5),  // EOF
    916   };
    917 
    918   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    919 
    920   AssertConnectSucceeds();
    921 
    922   Run(1);
    923   AssertSyncReadEquals(kMsg1, kLen1);
    924   // Write should block until the read completes
    925   AssertWriteReturns(kMsg2, kLen2, ERR_IO_PENDING);
    926 
    927   AssertAsyncReadEquals(kMsg3, kLen3);
    928 
    929   ASSERT_FALSE(write_callback_.have_result());
    930 
    931   // Now the write will complete
    932   Run(1);
    933   AssertWriteLength(kLen2);
    934 }
    935 
    936 // ----------- Reading/Writing on Closed socket
    937 
    938 // Reading from an already closed socket should return 0
    939 TEST_F(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsZero) {
    940   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    941   MockWrite writes[] = {
    942     CreateMockWrite(*conn, 0, false),
    943   };
    944 
    945   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    946   MockRead reads[] = {
    947     CreateMockRead(*resp, 1, true),
    948     MockRead(true, 0, 2),  // EOF
    949   };
    950 
    951   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    952 
    953   AssertConnectSucceeds();
    954 
    955   Run(1);
    956 
    957   ASSERT_EQ(0, sock_->Read(NULL, 1, NULL));
    958   ASSERT_EQ(ERR_CONNECTION_CLOSED, sock_->Read(NULL, 1, NULL));
    959   ASSERT_EQ(ERR_CONNECTION_CLOSED, sock_->Read(NULL, 1, NULL));
    960 }
    961 
    962 // Read pending when socket is closed should return 0
    963 TEST_F(SpdyProxyClientSocketTest, PendingReadOnCloseReturnsZero) {
    964   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    965   MockWrite writes[] = {
    966     CreateMockWrite(*conn, 0, false),
    967   };
    968 
    969   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    970   MockRead reads[] = {
    971     CreateMockRead(*resp, 1, true),
    972     MockRead(true, 0, 2),  // EOF
    973   };
    974 
    975   Initialize(reads, arraysize(reads), writes, arraysize(writes));
    976 
    977   AssertConnectSucceeds();
    978 
    979   AssertReadStarts(kMsg1, kLen1);
    980 
    981   Run(1);
    982 
    983   ASSERT_EQ(0, read_callback_.WaitForResult());
    984 }
    985 
    986 // Reading from a disconnected socket is an error
    987 TEST_F(SpdyProxyClientSocketTest, ReadOnDisconnectSocketReturnsNotConnected) {
    988   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
    989   MockWrite writes[] = {
    990     CreateMockWrite(*conn, 0, false),
    991   };
    992 
    993   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
    994   MockRead reads[] = {
    995     CreateMockRead(*resp, 1, true),
    996     MockRead(true, 0, 2),  // EOF
    997   };
    998 
    999   Initialize(reads, arraysize(reads), writes, arraysize(writes));
   1000 
   1001   AssertConnectSucceeds();
   1002 
   1003   sock_->Disconnect();
   1004 
   1005   ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->Read(NULL, 1, NULL));
   1006 }
   1007 
   1008 // Reading buffered data from an already closed socket should return
   1009 // buffered data, then 0.
   1010 TEST_F(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsBufferedData) {
   1011   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
   1012   MockWrite writes[] = {
   1013     CreateMockWrite(*conn, 0, false),
   1014   };
   1015 
   1016   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
   1017   scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
   1018   MockRead reads[] = {
   1019     CreateMockRead(*resp, 1, true),
   1020     CreateMockRead(*msg1, 2, true),
   1021     MockRead(true, 0, 3),  // EOF
   1022   };
   1023 
   1024   Initialize(reads, arraysize(reads), writes, arraysize(writes));
   1025 
   1026   AssertConnectSucceeds();
   1027 
   1028   Run(2);
   1029 
   1030   AssertSyncReadEquals(kMsg1, kLen1);
   1031   ASSERT_EQ(0, sock_->Read(NULL, 1, NULL));
   1032   ASSERT_EQ(ERR_CONNECTION_CLOSED, sock_->Read(NULL, 1, NULL));
   1033   // Verify that read *still* returns ERR_CONNECTION_CLOSED
   1034   ASSERT_EQ(ERR_CONNECTION_CLOSED, sock_->Read(NULL, 1, NULL));
   1035 }
   1036 
   1037 // Calling Write() on a closed socket is an error
   1038 TEST_F(SpdyProxyClientSocketTest, WriteOnClosedStream) {
   1039   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
   1040   MockWrite writes[] = {
   1041     CreateMockWrite(*conn, 0, false),
   1042   };
   1043 
   1044   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
   1045   scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
   1046   MockRead reads[] = {
   1047     CreateMockRead(*resp, 1, true),
   1048     MockRead(true, 0, 2),  // EOF
   1049   };
   1050 
   1051   Initialize(reads, arraysize(reads), writes, arraysize(writes));
   1052 
   1053   AssertConnectSucceeds();
   1054 
   1055   Run(1);  // Read EOF which will close the stream
   1056   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1));
   1057   EXPECT_EQ(ERR_CONNECTION_CLOSED, sock_->Write(buf, buf->size(), NULL));
   1058 }
   1059 
   1060 // Calling Write() on a disconnected socket is an error
   1061 TEST_F(SpdyProxyClientSocketTest, WriteOnDisconnectedSocket) {
   1062   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
   1063   MockWrite writes[] = {
   1064     CreateMockWrite(*conn, 0, false),
   1065   };
   1066 
   1067   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
   1068   scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
   1069   MockRead reads[] = {
   1070     CreateMockRead(*resp, 1, true),
   1071     MockRead(true, 0, 2),  // EOF
   1072   };
   1073 
   1074   Initialize(reads, arraysize(reads), writes, arraysize(writes));
   1075 
   1076   AssertConnectSucceeds();
   1077 
   1078   sock_->Disconnect();
   1079 
   1080   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1));
   1081   EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->Write(buf, buf->size(), NULL));
   1082 }
   1083 
   1084 // If the socket is closed with a pending Write(), the callback
   1085 // should be called with ERR_CONNECTION_CLOSED.
   1086 TEST_F(SpdyProxyClientSocketTest, WritePendingOnClose) {
   1087   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
   1088   MockWrite writes[] = {
   1089     CreateMockWrite(*conn, 0, false),
   1090     MockWrite(true, ERR_IO_PENDING, 2),
   1091   };
   1092 
   1093   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
   1094   MockRead reads[] = {
   1095     CreateMockRead(*resp, 1, true),
   1096     MockRead(true, 0, 3),  // EOF
   1097   };
   1098 
   1099   Initialize(reads, arraysize(reads), writes, arraysize(writes));
   1100 
   1101   AssertConnectSucceeds();
   1102 
   1103   EXPECT_TRUE(sock_->IsConnected());
   1104 
   1105   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1));
   1106   EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), &write_callback_));
   1107 
   1108   Run(1);
   1109 
   1110   EXPECT_EQ(ERR_CONNECTION_CLOSED, write_callback_.WaitForResult());
   1111 }
   1112 
   1113 // If the socket is Disconnected with a pending Write(), the callback
   1114 // should not be called.
   1115 TEST_F(SpdyProxyClientSocketTest, DisconnectWithWritePending) {
   1116   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
   1117   MockWrite writes[] = {
   1118     CreateMockWrite(*conn, 0, false),
   1119     MockWrite(false, 0, 2),  // EOF
   1120   };
   1121 
   1122   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
   1123   MockRead reads[] = {
   1124     CreateMockRead(*resp, 1, true),
   1125     MockRead(true, 0, 3),  // EOF
   1126   };
   1127 
   1128   Initialize(reads, arraysize(reads), writes, arraysize(writes));
   1129 
   1130   AssertConnectSucceeds();
   1131 
   1132   EXPECT_TRUE(sock_->IsConnected());
   1133 
   1134   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1));
   1135   EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), &write_callback_));
   1136 
   1137   sock_->Disconnect();
   1138 
   1139   EXPECT_FALSE(sock_->IsConnected());
   1140   EXPECT_FALSE(write_callback_.have_result());
   1141 }
   1142 
   1143 // If the socket is Disconnected with a pending Read(), the callback
   1144 // should not be called.
   1145 TEST_F(SpdyProxyClientSocketTest, DisconnectWithReadPending) {
   1146   scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
   1147   MockWrite writes[] = {
   1148     CreateMockWrite(*conn, 0, false),
   1149   };
   1150 
   1151   scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
   1152   MockRead reads[] = {
   1153     CreateMockRead(*resp, 1, true),
   1154     MockRead(true, 0, 2),  // EOF
   1155   };
   1156 
   1157   Initialize(reads, arraysize(reads), writes, arraysize(writes));
   1158 
   1159   AssertConnectSucceeds();
   1160 
   1161   EXPECT_TRUE(sock_->IsConnected());
   1162 
   1163   scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1));
   1164   ASSERT_EQ(ERR_IO_PENDING, sock_->Read(buf, kLen1, &read_callback_));
   1165 
   1166   sock_->Disconnect();
   1167 
   1168   EXPECT_FALSE(sock_->IsConnected());
   1169   EXPECT_FALSE(read_callback_.have_result());
   1170 }
   1171 
   1172 }  // namespace net
   1173