• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AddAuthToCache()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 
Run(int steps)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 
SpdyProxyClientSocketTest()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 
TearDown()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 
Initialize(MockRead * reads,size_t reads_count,MockWrite * writes,size_t writes_count)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 
CreateBuffer(const char * data,int size)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 
AssertConnectSucceeds()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 
AssertConnectFails(int result)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 
AssertConnectionEstablished()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 
AssertSyncReadEquals(const char * data,int len)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 
AssertAsyncReadEquals(const char * data,int len)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 
AssertReadStarts(const char * data,int len)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 
AssertReadReturns(const char * data,int len)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 
AssertAsyncWriteSucceeds(const char * data,int len)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 
AssertWriteReturns(const char * data,int len,int rv)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 
AssertWriteLength(int len)286 void SpdyProxyClientSocketTest::AssertWriteLength(int len) {
287   EXPECT_EQ(len, write_callback_.WaitForResult());
288 }
289 
AssertAsyncWriteWithReadsSucceeds(const char * data,int len,int num_reads)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.
ConstructConnectRequestFrame()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.
ConstructConnectAuthRequestFrame()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.
ConstructConnectReplyFrame()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.
ConstructConnectAuthReplyFrame()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.
ConstructConnectErrorReplyFrame()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 
ConstructBodyFrame(const char * data,int length)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 
TEST_F(SpdyProxyClientSocketTest,ConnectSendsCorrectRequest)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 
TEST_F(SpdyProxyClientSocketTest,ConnectWithAuthRequested)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 
TEST_F(SpdyProxyClientSocketTest,ConnectWithAuthCredentials)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 
TEST_F(SpdyProxyClientSocketTest,ConnectFails)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 
TEST_F(SpdyProxyClientSocketTest,WasEverUsedReturnsCorrectValues)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 
TEST_F(SpdyProxyClientSocketTest,GetPeerAddressReturnsCorrectValues)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 
TEST_F(SpdyProxyClientSocketTest,WriteSendsDataInDataFrame)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 
TEST_F(SpdyProxyClientSocketTest,WriteSplitsLargeDataIntoMultipleFrames)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 
TEST_F(SpdyProxyClientSocketTest,ReadReadsDataInDataFrame)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 
TEST_F(SpdyProxyClientSocketTest,ReadDataFromBufferedFrames)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 
TEST_F(SpdyProxyClientSocketTest,ReadDataMultipleBufferedFrames)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 
TEST_F(SpdyProxyClientSocketTest,LargeReadWillMergeDataFromDifferentFrames)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 
TEST_F(SpdyProxyClientSocketTest,MultipleShortReadsThenMoreRead)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 
TEST_F(SpdyProxyClientSocketTest,ReadWillSplitDataFromLargeFrame)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 
TEST_F(SpdyProxyClientSocketTest,MultipleReadsFromSameLargeFrame)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 
TEST_F(SpdyProxyClientSocketTest,ReadAuthResponseBody)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 
TEST_F(SpdyProxyClientSocketTest,ReadErrorResponseBody)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 
TEST_F(SpdyProxyClientSocketTest,AsyncReadAroundWrite)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 
TEST_F(SpdyProxyClientSocketTest,AsyncWriteAroundReads)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
TEST_F(SpdyProxyClientSocketTest,ReadOnClosedSocketReturnsZero)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
TEST_F(SpdyProxyClientSocketTest,PendingReadOnCloseReturnsZero)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
TEST_F(SpdyProxyClientSocketTest,ReadOnDisconnectSocketReturnsNotConnected)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.
TEST_F(SpdyProxyClientSocketTest,ReadOnClosedSocketReturnsBufferedData)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
TEST_F(SpdyProxyClientSocketTest,WriteOnClosedStream)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
TEST_F(SpdyProxyClientSocketTest,WriteOnDisconnectedSocket)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.
TEST_F(SpdyProxyClientSocketTest,WritePendingOnClose)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.
TEST_F(SpdyProxyClientSocketTest,DisconnectWithWritePending)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.
TEST_F(SpdyProxyClientSocketTest,DisconnectWithReadPending)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