- add sources.
[platform/framework/web/crosswalk.git] / src / net / spdy / spdy_proxy_client_socket_unittest.cc
1 // Copyright (c) 2012 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/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "net/base/address_list.h"
11 #include "net/base/capturing_net_log.h"
12 #include "net/base/net_log.h"
13 #include "net/base/net_log_unittest.h"
14 #include "net/base/test_completion_callback.h"
15 #include "net/base/winsock_init.h"
16 #include "net/dns/mock_host_resolver.h"
17 #include "net/http/http_response_headers.h"
18 #include "net/http/http_response_info.h"
19 #include "net/socket/client_socket_factory.h"
20 #include "net/socket/next_proto.h"
21 #include "net/socket/socket_test_util.h"
22 #include "net/socket/tcp_client_socket.h"
23 #include "net/spdy/buffered_spdy_framer.h"
24 #include "net/spdy/spdy_http_utils.h"
25 #include "net/spdy/spdy_protocol.h"
26 #include "net/spdy/spdy_session_pool.h"
27 #include "net/spdy/spdy_test_util_common.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "testing/platform_test.h"
30
31 //-----------------------------------------------------------------------------
32
33 namespace {
34
35 static const char kRequestUrl[] = "https://www.google.com/";
36 static const char kOriginHost[] = "www.google.com";
37 static const int kOriginPort = 443;
38 static const char kOriginHostPort[] = "www.google.com:443";
39 static const char kProxyUrl[] = "https://myproxy:6121/";
40 static const char kProxyHost[] = "myproxy";
41 static const int kProxyPort = 6121;
42 static const char kUserAgent[] = "Mozilla/1.0";
43
44 static const int kStreamId = 1;
45
46 static const char kMsg1[] = "\0hello!\xff";
47 static const int kLen1 = 8;
48 static const char kMsg2[] = "\00012345678\0";
49 static const int kLen2 = 10;
50 static const char kMsg3[] = "bye!";
51 static const int kLen3 = 4;
52 static const char kMsg33[] = "bye!bye!";
53 static const int kLen33 = kLen3 + kLen3;
54 static const char kMsg333[] = "bye!bye!bye!";
55 static const int kLen333 = kLen3 + kLen3 + kLen3;
56
57 static const char kRedirectUrl[] = "https://example.com/";
58
59 }  // anonymous namespace
60
61 namespace net {
62
63 class SpdyProxyClientSocketTest
64     : public PlatformTest,
65       public testing::WithParamInterface<NextProto> {
66  public:
67   SpdyProxyClientSocketTest();
68
69   virtual void TearDown();
70
71  protected:
72   void Initialize(MockRead* reads, size_t reads_count, MockWrite* writes,
73                   size_t writes_count);
74   SpdyFrame* ConstructConnectRequestFrame();
75   SpdyFrame* ConstructConnectAuthRequestFrame();
76   SpdyFrame* ConstructConnectReplyFrame();
77   SpdyFrame* ConstructConnectAuthReplyFrame();
78   SpdyFrame* ConstructConnectRedirectReplyFrame();
79   SpdyFrame* ConstructConnectErrorReplyFrame();
80   SpdyFrame* ConstructBodyFrame(const char* data, int length);
81   scoped_refptr<IOBufferWithSize> CreateBuffer(const char* data, int size);
82   void AssertConnectSucceeds();
83   void AssertConnectFails(int result);
84   void AssertConnectionEstablished();
85   void AssertSyncReadEquals(const char* data, int len);
86   void AssertAsyncReadEquals(const char* data, int len);
87   void AssertReadStarts(const char* data, int len);
88   void AssertReadReturns(const char* data, int len);
89   void AssertAsyncWriteSucceeds(const char* data, int len);
90   void AssertWriteReturns(const char* data, int len, int rv);
91   void AssertWriteLength(int len);
92   void AssertAsyncWriteWithReadsSucceeds(const char* data, int len,
93                                         int num_reads);
94
95   void AddAuthToCache() {
96     const base::string16 kFoo(ASCIIToUTF16("foo"));
97     const base::string16 kBar(ASCIIToUTF16("bar"));
98     session_->http_auth_cache()->Add(GURL(kProxyUrl),
99                                      "MyRealm1",
100                                      HttpAuth::AUTH_SCHEME_BASIC,
101                                      "Basic realm=MyRealm1",
102                                      AuthCredentials(kFoo, kBar),
103                                      "/");
104   }
105
106   void Run(int steps) {
107     data_->StopAfter(steps);
108     data_->Run();
109   }
110
111   void CloseSpdySession(net::Error error, const std::string& description) {
112     spdy_session_->CloseSessionOnError(error, description);
113   }
114
115   SpdyTestUtil spdy_util_;
116   scoped_ptr<SpdyProxyClientSocket> sock_;
117   TestCompletionCallback read_callback_;
118   TestCompletionCallback write_callback_;
119   scoped_ptr<DeterministicSocketData> data_;
120   CapturingBoundNetLog net_log_;
121
122  private:
123   scoped_refptr<HttpNetworkSession> session_;
124   scoped_refptr<IOBuffer> read_buf_;
125   SpdySessionDependencies session_deps_;
126   MockConnect connect_data_;
127   base::WeakPtr<SpdySession> spdy_session_;
128   BufferedSpdyFramer framer_;
129
130   std::string user_agent_;
131   GURL url_;
132   HostPortPair proxy_host_port_;
133   HostPortPair endpoint_host_port_pair_;
134   ProxyServer proxy_;
135   SpdySessionKey endpoint_spdy_session_key_;
136
137   DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocketTest);
138 };
139
140 INSTANTIATE_TEST_CASE_P(
141     NextProto,
142     SpdyProxyClientSocketTest,
143     testing::Values(kProtoDeprecatedSPDY2,
144                     kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
145                     kProtoHTTP2Draft04));
146
147 SpdyProxyClientSocketTest::SpdyProxyClientSocketTest()
148     : spdy_util_(GetParam()),
149       session_(NULL),
150       read_buf_(NULL),
151       session_deps_(GetParam()),
152       connect_data_(SYNCHRONOUS, OK),
153       framer_(spdy_util_.spdy_version(), false),
154       user_agent_(kUserAgent),
155       url_(kRequestUrl),
156       proxy_host_port_(kProxyHost, kProxyPort),
157       endpoint_host_port_pair_(kOriginHost, kOriginPort),
158       proxy_(ProxyServer::SCHEME_HTTPS, proxy_host_port_),
159       endpoint_spdy_session_key_(endpoint_host_port_pair_,
160                                  proxy_,
161                                  kPrivacyModeDisabled) {
162   session_deps_.net_log = net_log_.bound().net_log();
163 }
164
165 void SpdyProxyClientSocketTest::TearDown() {
166   sock_.reset(NULL);
167   if (session_.get() != NULL)
168     session_->spdy_session_pool()->CloseAllSessions();
169
170   // Empty the current queue.
171   base::MessageLoop::current()->RunUntilIdle();
172   PlatformTest::TearDown();
173 }
174
175 void SpdyProxyClientSocketTest::Initialize(MockRead* reads,
176                                                 size_t reads_count,
177                                                 MockWrite* writes,
178                                                 size_t writes_count) {
179   data_.reset(new DeterministicSocketData(reads, reads_count,
180                                           writes, writes_count));
181   data_->set_connect_data(connect_data_);
182   data_->SetStop(2);
183
184   session_deps_.deterministic_socket_factory->AddSocketDataProvider(
185       data_.get());
186   session_deps_.host_resolver->set_synchronous_mode(true);
187
188   session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
189       &session_deps_);
190
191   // Creates the SPDY session and stream.
192   spdy_session_ =
193       CreateInsecureSpdySession(
194           session_, endpoint_spdy_session_key_, BoundNetLog());
195   base::WeakPtr<SpdyStream> spdy_stream(
196       CreateStreamSynchronously(
197           SPDY_BIDIRECTIONAL_STREAM, spdy_session_, url_, LOWEST,
198           net_log_.bound()));
199   ASSERT_TRUE(spdy_stream.get() != NULL);
200
201   // Create the SpdyProxyClientSocket.
202   sock_.reset(
203       new SpdyProxyClientSocket(spdy_stream, user_agent_,
204                                 endpoint_host_port_pair_, url_,
205                                 proxy_host_port_, net_log_.bound(),
206                                 session_->http_auth_cache(),
207                                 session_->http_auth_handler_factory()));
208 }
209
210 scoped_refptr<IOBufferWithSize> SpdyProxyClientSocketTest::CreateBuffer(
211     const char* data, int size) {
212   scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(size));
213   memcpy(buf->data(), data, size);
214   return buf;
215 }
216
217 void SpdyProxyClientSocketTest::AssertConnectSucceeds() {
218   ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(read_callback_.callback()));
219   data_->Run();
220   ASSERT_EQ(OK, read_callback_.WaitForResult());
221 }
222
223 void SpdyProxyClientSocketTest::AssertConnectFails(int result) {
224   ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(read_callback_.callback()));
225   data_->Run();
226   ASSERT_EQ(result, read_callback_.WaitForResult());
227 }
228
229 void SpdyProxyClientSocketTest::AssertConnectionEstablished() {
230   const HttpResponseInfo* response = sock_->GetConnectResponseInfo();
231   ASSERT_TRUE(response != NULL);
232   ASSERT_EQ(200, response->headers->response_code());
233   ASSERT_EQ("Connection Established", response->headers->GetStatusText());
234 }
235
236 void SpdyProxyClientSocketTest::AssertSyncReadEquals(const char* data,
237                                                      int len) {
238   scoped_refptr<IOBuffer> buf(new IOBuffer(len));
239   ASSERT_EQ(len, sock_->Read(buf.get(), len, CompletionCallback()));
240   ASSERT_EQ(std::string(data, len), std::string(buf->data(), len));
241   ASSERT_TRUE(sock_->IsConnected());
242 }
243
244 void SpdyProxyClientSocketTest::AssertAsyncReadEquals(const char* data,
245                                                            int len) {
246   data_->StopAfter(1);
247   // Issue the read, which will be completed asynchronously
248   scoped_refptr<IOBuffer> buf(new IOBuffer(len));
249   ASSERT_EQ(ERR_IO_PENDING,
250             sock_->Read(buf.get(), len, read_callback_.callback()));
251   EXPECT_TRUE(sock_->IsConnected());
252   data_->Run();
253
254   EXPECT_TRUE(sock_->IsConnected());
255
256   // Now the read will return
257   EXPECT_EQ(len, read_callback_.WaitForResult());
258   ASSERT_EQ(std::string(data, len), std::string(buf->data(), len));
259 }
260
261 void SpdyProxyClientSocketTest::AssertReadStarts(const char* data,
262                                                       int len) {
263   data_->StopAfter(1);
264   // Issue the read, which will be completed asynchronously
265   read_buf_ = new IOBuffer(len);
266   ASSERT_EQ(ERR_IO_PENDING,
267             sock_->Read(read_buf_.get(), len, read_callback_.callback()));
268   EXPECT_TRUE(sock_->IsConnected());
269 }
270
271 void SpdyProxyClientSocketTest::AssertReadReturns(const char* data,
272                                                        int len) {
273   EXPECT_TRUE(sock_->IsConnected());
274
275   // Now the read will return
276   EXPECT_EQ(len, read_callback_.WaitForResult());
277   ASSERT_EQ(std::string(data, len), std::string(read_buf_->data(), len));
278 }
279
280 void SpdyProxyClientSocketTest::AssertAsyncWriteSucceeds(const char* data,
281                                                               int len) {
282   AssertWriteReturns(data, len, ERR_IO_PENDING);
283   data_->RunFor(1);
284   AssertWriteLength(len);
285 }
286
287 void SpdyProxyClientSocketTest::AssertWriteReturns(const char* data,
288                                                         int len,
289                                                         int rv) {
290   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(data, len));
291   EXPECT_EQ(rv,
292             sock_->Write(buf.get(), buf->size(), write_callback_.callback()));
293 }
294
295 void SpdyProxyClientSocketTest::AssertWriteLength(int len) {
296   EXPECT_EQ(len, write_callback_.WaitForResult());
297 }
298
299 void SpdyProxyClientSocketTest::AssertAsyncWriteWithReadsSucceeds(
300     const char* data, int len, int num_reads) {
301   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(data, len));
302
303   EXPECT_EQ(ERR_IO_PENDING,
304             sock_->Write(buf.get(), buf->size(), write_callback_.callback()));
305
306   for (int i = 0; i < num_reads; i++) {
307     Run(1);
308     AssertSyncReadEquals(kMsg2, kLen2);
309   }
310
311   write_callback_.WaitForResult();
312 }
313
314 // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
315 SpdyFrame*
316 SpdyProxyClientSocketTest::ConstructConnectRequestFrame() {
317   const SpdyHeaderInfo kSynStartHeader = {
318     SYN_STREAM,
319     kStreamId,
320     0,
321     net::ConvertRequestPriorityToSpdyPriority(
322         LOWEST, spdy_util_.spdy_version()),
323     0,
324     CONTROL_FLAG_NONE,
325     false,
326     RST_STREAM_INVALID,
327     NULL,
328     0,
329     DATA_FLAG_NONE
330   };
331   bool spdy2 = spdy_util_.is_spdy2();
332   const char* const kConnectHeaders[] = {
333     spdy2 ? "method"  : ":method",  "CONNECT",
334     spdy2 ? "url"     : ":path",    kOriginHostPort,
335     spdy2 ? "host"    : ":host",    kOriginHost,
336     "user-agent", kUserAgent,
337     spdy2 ? "version" : ":version", "HTTP/1.1",
338   };
339   return spdy_util_.ConstructSpdyFrame(
340       kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2);
341 }
342
343 // Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes
344 // Proxy-Authorization headers.
345 SpdyFrame*
346 SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() {
347   const SpdyHeaderInfo kSynStartHeader = {
348     SYN_STREAM,
349     kStreamId,
350     0,
351     net::ConvertRequestPriorityToSpdyPriority(
352         LOWEST, spdy_util_.spdy_version()),
353     0,
354     CONTROL_FLAG_NONE,
355     false,
356     RST_STREAM_INVALID,
357     NULL,
358     0,
359     DATA_FLAG_NONE
360   };
361   bool spdy2 = spdy_util_.is_spdy2();
362   const char* const kConnectHeaders[] = {
363     spdy2 ? "method"  : ":method",  "CONNECT",
364     spdy2 ? "url"     : ":path",    kOriginHostPort,
365     spdy2 ? "host"    : ":host",    kOriginHost,
366     "user-agent", kUserAgent,
367     spdy2 ? "version" : ":version", "HTTP/1.1",
368     "proxy-authorization", "Basic Zm9vOmJhcg==",
369   };
370   return spdy_util_.ConstructSpdyFrame(
371       kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2);
372 }
373
374 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT.
375 SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() {
376   bool spdy2 = spdy_util_.is_spdy2();
377   const char* const kStandardReplyHeaders[] = {
378       spdy2 ? "status"  : ":status",  "200 Connection Established",
379       spdy2 ? "version" : ":version", "HTTP/1.1"
380   };
381   return spdy_util_.ConstructSpdyControlFrame(NULL,
382                                               0,
383                                               false,
384                                               kStreamId,
385                                               LOWEST,
386                                               SYN_REPLY,
387                                               CONTROL_FLAG_NONE,
388                                               kStandardReplyHeaders,
389                                               arraysize(kStandardReplyHeaders),
390                                               0);
391 }
392
393 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT.
394 SpdyFrame*
395 SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() {
396   bool spdy2 = spdy_util_.is_spdy2();
397
398   const char* const kStandardReplyHeaders[] = {
399       spdy2 ? "status"  : ":status",  "407 Proxy Authentication Required",
400       spdy2 ? "version" : ":version", "HTTP/1.1",
401       "proxy-authenticate", "Basic realm=\"MyRealm1\"",
402   };
403
404   return spdy_util_.ConstructSpdyControlFrame(NULL,
405                                               0,
406                                               false,
407                                               kStreamId,
408                                               LOWEST,
409                                               SYN_REPLY,
410                                               CONTROL_FLAG_NONE,
411                                               kStandardReplyHeaders,
412                                               arraysize(kStandardReplyHeaders),
413                                               0);
414 }
415
416 // Constructs a SPDY SYN_REPLY frame with an HTTP 302 redirect.
417 SpdyFrame*
418 SpdyProxyClientSocketTest::ConstructConnectRedirectReplyFrame() {
419   bool spdy2 = spdy_util_.is_spdy2();
420
421   const char* const kStandardReplyHeaders[] = {
422       spdy2 ? "status"  : ":status",  "302 Found",
423       spdy2 ? "version" : ":version", "HTTP/1.1",
424       "location", kRedirectUrl,
425       "set-cookie", "foo=bar"
426   };
427
428   return spdy_util_.ConstructSpdyControlFrame(NULL,
429                                               0,
430                                               false,
431                                               kStreamId,
432                                               LOWEST,
433                                               SYN_REPLY,
434                                               CONTROL_FLAG_NONE,
435                                               kStandardReplyHeaders,
436                                               arraysize(kStandardReplyHeaders),
437                                               0);
438 }
439
440 // Constructs a SPDY SYN_REPLY frame with an HTTP 500 error.
441 SpdyFrame*
442 SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() {
443   bool spdy2 = spdy_util_.is_spdy2();
444
445   const char* const kStandardReplyHeaders[] = {
446       spdy2 ? "status"  : ":status",  "500 Internal Server Error",
447       spdy2 ? "version" : ":version", "HTTP/1.1",
448   };
449
450   return spdy_util_.ConstructSpdyControlFrame(NULL,
451                                               0,
452                                               false,
453                                               kStreamId,
454                                               LOWEST,
455                                               SYN_REPLY,
456                                               CONTROL_FLAG_NONE,
457                                               kStandardReplyHeaders,
458                                               arraysize(kStandardReplyHeaders),
459                                               0);
460 }
461
462 SpdyFrame* SpdyProxyClientSocketTest::ConstructBodyFrame(
463     const char* data,
464     int length) {
465   return framer_.CreateDataFrame(kStreamId, data, length, DATA_FLAG_NONE);
466 }
467
468 // ----------- Connect
469
470 TEST_P(SpdyProxyClientSocketTest, ConnectSendsCorrectRequest) {
471   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
472   MockWrite writes[] = {
473     CreateMockWrite(*conn, 0, SYNCHRONOUS),
474   };
475
476   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
477   MockRead reads[] = {
478     CreateMockRead(*resp, 1, ASYNC),
479     MockRead(ASYNC, 0, 2),  // EOF
480   };
481
482   Initialize(reads, arraysize(reads), writes, arraysize(writes));
483
484   ASSERT_FALSE(sock_->IsConnected());
485
486   AssertConnectSucceeds();
487
488   AssertConnectionEstablished();
489 }
490
491 TEST_P(SpdyProxyClientSocketTest, ConnectWithAuthRequested) {
492   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
493   MockWrite writes[] = {
494     CreateMockWrite(*conn, 0, SYNCHRONOUS),
495   };
496
497   scoped_ptr<SpdyFrame> resp(ConstructConnectAuthReplyFrame());
498   MockRead reads[] = {
499     CreateMockRead(*resp, 1, ASYNC),
500     MockRead(ASYNC, 0, 2),  // EOF
501   };
502
503   Initialize(reads, arraysize(reads), writes, arraysize(writes));
504
505   AssertConnectFails(ERR_PROXY_AUTH_REQUESTED);
506
507   const HttpResponseInfo* response = sock_->GetConnectResponseInfo();
508   ASSERT_TRUE(response != NULL);
509   ASSERT_EQ(407, response->headers->response_code());
510   ASSERT_EQ("Proxy Authentication Required",
511             response->headers->GetStatusText());
512 }
513
514 TEST_P(SpdyProxyClientSocketTest, ConnectWithAuthCredentials) {
515   scoped_ptr<SpdyFrame> conn(ConstructConnectAuthRequestFrame());
516   MockWrite writes[] = {
517     CreateMockWrite(*conn, 0, SYNCHRONOUS),
518   };
519
520   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
521   MockRead reads[] = {
522     CreateMockRead(*resp, 1, ASYNC),
523     MockRead(ASYNC, 0, 2),  // EOF
524   };
525
526   Initialize(reads, arraysize(reads), writes, arraysize(writes));
527   AddAuthToCache();
528
529   AssertConnectSucceeds();
530
531   AssertConnectionEstablished();
532 }
533
534 TEST_P(SpdyProxyClientSocketTest, ConnectRedirects) {
535   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
536   MockWrite writes[] = {
537     CreateMockWrite(*conn, 0, SYNCHRONOUS),
538   };
539
540   scoped_ptr<SpdyFrame> resp(ConstructConnectRedirectReplyFrame());
541   MockRead reads[] = {
542     CreateMockRead(*resp, 1, ASYNC),
543     MockRead(ASYNC, 0, 2),  // EOF
544   };
545
546   Initialize(reads, arraysize(reads), writes, arraysize(writes));
547
548   AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
549
550   const HttpResponseInfo* response = sock_->GetConnectResponseInfo();
551   ASSERT_TRUE(response != NULL);
552
553   const HttpResponseHeaders* headers = response->headers.get();
554   ASSERT_EQ(302, headers->response_code());
555   ASSERT_FALSE(headers->HasHeader("set-cookie"));
556   ASSERT_TRUE(headers->HasHeaderValue("content-length", "0"));
557
558   std::string location;
559   ASSERT_TRUE(headers->IsRedirect(&location));
560   ASSERT_EQ(location, kRedirectUrl);
561 }
562
563 TEST_P(SpdyProxyClientSocketTest, ConnectFails) {
564   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
565   MockWrite writes[] = {
566     CreateMockWrite(*conn, 0, SYNCHRONOUS),
567   };
568
569   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
570   MockRead reads[] = {
571     MockRead(ASYNC, 0, 1),  // EOF
572   };
573
574   Initialize(reads, arraysize(reads), writes, arraysize(writes));
575
576   ASSERT_FALSE(sock_->IsConnected());
577
578   AssertConnectFails(ERR_CONNECTION_CLOSED);
579
580   ASSERT_FALSE(sock_->IsConnected());
581 }
582
583 // ----------- WasEverUsed
584
585 TEST_P(SpdyProxyClientSocketTest, WasEverUsedReturnsCorrectValues) {
586   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
587   MockWrite writes[] = {
588     CreateMockWrite(*conn, 0, SYNCHRONOUS),
589   };
590
591   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
592   MockRead reads[] = {
593     CreateMockRead(*resp, 1, ASYNC),
594     MockRead(ASYNC, 0, 2),  // EOF
595   };
596
597   Initialize(reads, arraysize(reads), writes, arraysize(writes));
598
599   EXPECT_FALSE(sock_->WasEverUsed());
600   AssertConnectSucceeds();
601   EXPECT_TRUE(sock_->WasEverUsed());
602   sock_->Disconnect();
603   EXPECT_TRUE(sock_->WasEverUsed());
604 }
605
606 // ----------- GetPeerAddress
607
608 TEST_P(SpdyProxyClientSocketTest, GetPeerAddressReturnsCorrectValues) {
609   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
610   MockWrite writes[] = {
611     CreateMockWrite(*conn, 0, SYNCHRONOUS),
612   };
613
614   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
615   MockRead reads[] = {
616     CreateMockRead(*resp, 1, ASYNC),
617     MockRead(ASYNC, 0, 2),  // EOF
618   };
619
620   Initialize(reads, arraysize(reads), writes, arraysize(writes));
621
622   net::IPEndPoint addr;
623   EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr));
624
625   AssertConnectSucceeds();
626   EXPECT_TRUE(sock_->IsConnected());
627   EXPECT_EQ(OK, sock_->GetPeerAddress(&addr));
628
629   Run(1);
630
631   EXPECT_FALSE(sock_->IsConnected());
632   EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr));
633
634   sock_->Disconnect();
635
636   EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr));
637 }
638
639 // ----------- Write
640
641 TEST_P(SpdyProxyClientSocketTest, WriteSendsDataInDataFrame) {
642   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
643   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
644   scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
645   MockWrite writes[] = {
646     CreateMockWrite(*conn, 0, SYNCHRONOUS),
647     CreateMockWrite(*msg1, 2, SYNCHRONOUS),
648     CreateMockWrite(*msg2, 3, SYNCHRONOUS),
649   };
650
651   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
652   MockRead reads[] = {
653     CreateMockRead(*resp, 1, ASYNC),
654     MockRead(ASYNC, 0, 4),  // EOF
655   };
656
657   Initialize(reads, arraysize(reads), writes, arraysize(writes));
658
659   AssertConnectSucceeds();
660
661   AssertAsyncWriteSucceeds(kMsg1, kLen1);
662   AssertAsyncWriteSucceeds(kMsg2, kLen2);
663 }
664
665 TEST_P(SpdyProxyClientSocketTest, WriteSplitsLargeDataIntoMultipleFrames) {
666   std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
667   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
668   scoped_ptr<SpdyFrame> chunk(ConstructBodyFrame(chunk_data.data(),
669                                                        chunk_data.length()));
670   MockWrite writes[] = {
671     CreateMockWrite(*conn, 0, SYNCHRONOUS),
672     CreateMockWrite(*chunk, 2, SYNCHRONOUS),
673     CreateMockWrite(*chunk, 3, SYNCHRONOUS),
674     CreateMockWrite(*chunk, 4, SYNCHRONOUS)
675   };
676
677   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
678   MockRead reads[] = {
679     CreateMockRead(*resp, 1, ASYNC),
680     MockRead(ASYNC, 0, 5),  // EOF
681   };
682
683   Initialize(reads, arraysize(reads), writes, arraysize(writes));
684
685   AssertConnectSucceeds();
686
687   std::string big_data(kMaxSpdyFrameChunkSize * 3, 'x');
688   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(big_data.data(),
689                                                    big_data.length()));
690
691   EXPECT_EQ(ERR_IO_PENDING,
692             sock_->Write(buf.get(), buf->size(), write_callback_.callback()));
693   data_->RunFor(3);
694
695   EXPECT_EQ(buf->size(), write_callback_.WaitForResult());
696 }
697
698 // ----------- Read
699
700 TEST_P(SpdyProxyClientSocketTest, ReadReadsDataInDataFrame) {
701   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
702   MockWrite writes[] = {
703     CreateMockWrite(*conn, 0, SYNCHRONOUS),
704   };
705
706   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
707   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
708   MockRead reads[] = {
709     CreateMockRead(*resp, 1, ASYNC),
710     CreateMockRead(*msg1, 2, ASYNC),
711     MockRead(ASYNC, 0, 3),  // EOF
712   };
713
714   Initialize(reads, arraysize(reads), writes, arraysize(writes));
715
716   AssertConnectSucceeds();
717
718   Run(1);  // SpdySession consumes the next read and sends it to
719            // sock_ to be buffered.
720   AssertSyncReadEquals(kMsg1, kLen1);
721 }
722
723 TEST_P(SpdyProxyClientSocketTest, ReadDataFromBufferedFrames) {
724   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
725   MockWrite writes[] = {
726     CreateMockWrite(*conn, 0, SYNCHRONOUS),
727   };
728
729   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
730   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
731   scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
732   MockRead reads[] = {
733     CreateMockRead(*resp, 1, ASYNC),
734     CreateMockRead(*msg1, 2, ASYNC),
735     CreateMockRead(*msg2, 3, ASYNC),
736     MockRead(ASYNC, 0, 4),  // EOF
737   };
738
739   Initialize(reads, arraysize(reads), writes, arraysize(writes));
740
741   AssertConnectSucceeds();
742
743   Run(1);  // SpdySession consumes the next read and sends it to
744            // sock_ to be buffered.
745   AssertSyncReadEquals(kMsg1, kLen1);
746   Run(1);  // SpdySession consumes the next read and sends it to
747            // sock_ to be buffered.
748   AssertSyncReadEquals(kMsg2, kLen2);
749 }
750
751 TEST_P(SpdyProxyClientSocketTest, ReadDataMultipleBufferedFrames) {
752   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
753   MockWrite writes[] = {
754     CreateMockWrite(*conn, 0, SYNCHRONOUS),
755   };
756
757   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
758   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
759   scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
760   MockRead reads[] = {
761     CreateMockRead(*resp, 1, ASYNC),
762     CreateMockRead(*msg1, 2, ASYNC),
763     CreateMockRead(*msg2, 3, ASYNC),
764     MockRead(ASYNC, 0, 4),  // EOF
765   };
766
767   Initialize(reads, arraysize(reads), writes, arraysize(writes));
768
769   AssertConnectSucceeds();
770
771   Run(2);  // SpdySession consumes the next two reads and sends then to
772            // sock_ to be buffered.
773   AssertSyncReadEquals(kMsg1, kLen1);
774   AssertSyncReadEquals(kMsg2, kLen2);
775 }
776
777 TEST_P(SpdyProxyClientSocketTest,
778        LargeReadWillMergeDataFromDifferentFrames) {
779   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
780   MockWrite writes[] = {
781     CreateMockWrite(*conn, 0, SYNCHRONOUS),
782   };
783
784   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
785   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
786   scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
787   MockRead reads[] = {
788     CreateMockRead(*resp, 1, ASYNC),
789     CreateMockRead(*msg3, 2, ASYNC),
790     CreateMockRead(*msg3, 3, ASYNC),
791     MockRead(ASYNC, 0, 4),  // EOF
792   };
793
794   Initialize(reads, arraysize(reads), writes, arraysize(writes));
795
796   AssertConnectSucceeds();
797
798   Run(2);  // SpdySession consumes the next two reads and sends then to
799            // sock_ to be buffered.
800   // The payload from two data frames, each with kMsg3 will be combined
801   // together into a single read().
802   AssertSyncReadEquals(kMsg33, kLen33);
803 }
804
805 TEST_P(SpdyProxyClientSocketTest, MultipleShortReadsThenMoreRead) {
806   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
807   MockWrite writes[] = {
808     CreateMockWrite(*conn, 0, SYNCHRONOUS),
809   };
810
811   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
812   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
813   scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
814   scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
815   MockRead reads[] = {
816     CreateMockRead(*resp, 1, ASYNC),
817     CreateMockRead(*msg1, 2, ASYNC),
818     CreateMockRead(*msg3, 3, ASYNC),
819     CreateMockRead(*msg3, 4, ASYNC),
820     CreateMockRead(*msg2, 5, ASYNC),
821     MockRead(ASYNC, 0, 6),  // EOF
822   };
823
824   Initialize(reads, arraysize(reads), writes, arraysize(writes));
825
826   AssertConnectSucceeds();
827
828   Run(4);  // SpdySession consumes the next four reads and sends then to
829            // sock_ to be buffered.
830   AssertSyncReadEquals(kMsg1, kLen1);
831   // The payload from two data frames, each with kMsg3 will be combined
832   // together into a single read().
833   AssertSyncReadEquals(kMsg33, kLen33);
834   AssertSyncReadEquals(kMsg2, kLen2);
835 }
836
837 TEST_P(SpdyProxyClientSocketTest, ReadWillSplitDataFromLargeFrame) {
838   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
839   MockWrite writes[] = {
840     CreateMockWrite(*conn, 0, SYNCHRONOUS),
841   };
842
843   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
844   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
845   scoped_ptr<SpdyFrame> msg33(ConstructBodyFrame(kMsg33, kLen33));
846   scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
847   MockRead reads[] = {
848     CreateMockRead(*resp, 1, ASYNC),
849     CreateMockRead(*msg1, 2, ASYNC),
850     CreateMockRead(*msg33, 3, ASYNC),
851     MockRead(ASYNC, 0, 4),  // EOF
852   };
853
854   Initialize(reads, arraysize(reads), writes, arraysize(writes));
855
856   AssertConnectSucceeds();
857
858   Run(2);  // SpdySession consumes the next two reads and sends then to
859            // sock_ to be buffered.
860   AssertSyncReadEquals(kMsg1, kLen1);
861   // The payload from the single large data frame will be read across
862   // two different reads.
863   AssertSyncReadEquals(kMsg3, kLen3);
864   AssertSyncReadEquals(kMsg3, kLen3);
865 }
866
867 TEST_P(SpdyProxyClientSocketTest, MultipleReadsFromSameLargeFrame) {
868   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
869   MockWrite writes[] = {
870     CreateMockWrite(*conn, 0, SYNCHRONOUS),
871   };
872
873   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
874   scoped_ptr<SpdyFrame> msg333(ConstructBodyFrame(kMsg333, kLen333));
875   MockRead reads[] = {
876     CreateMockRead(*resp, 1, ASYNC),
877     CreateMockRead(*msg333, 2, ASYNC),
878     MockRead(ASYNC, 0, 3),  // EOF
879   };
880
881   Initialize(reads, arraysize(reads), writes, arraysize(writes));
882
883   AssertConnectSucceeds();
884
885   Run(1);  // SpdySession consumes the next read and sends it to
886            // sock_ to be buffered.
887   // The payload from the single large data frame will be read across
888   // two different reads.
889   AssertSyncReadEquals(kMsg33, kLen33);
890
891   // Now attempt to do a read of more data than remains buffered
892   scoped_refptr<IOBuffer> buf(new IOBuffer(kLen33));
893   ASSERT_EQ(kLen3, sock_->Read(buf.get(), kLen33, read_callback_.callback()));
894   ASSERT_EQ(std::string(kMsg3, kLen3), std::string(buf->data(), kLen3));
895   ASSERT_TRUE(sock_->IsConnected());
896 }
897
898 TEST_P(SpdyProxyClientSocketTest, ReadAuthResponseBody) {
899   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
900   MockWrite writes[] = {
901     CreateMockWrite(*conn, 0, SYNCHRONOUS),
902   };
903
904   scoped_ptr<SpdyFrame> resp(ConstructConnectAuthReplyFrame());
905   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
906   scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
907   MockRead reads[] = {
908     CreateMockRead(*resp, 1, ASYNC),
909     CreateMockRead(*msg1, 2, ASYNC),
910     CreateMockRead(*msg2, 3, ASYNC),
911     MockRead(ASYNC, 0, 4),  // EOF
912   };
913
914   Initialize(reads, arraysize(reads), writes, arraysize(writes));
915
916   AssertConnectFails(ERR_PROXY_AUTH_REQUESTED);
917
918   Run(2);  // SpdySession consumes the next two reads and sends then to
919            // sock_ to be buffered.
920   AssertSyncReadEquals(kMsg1, kLen1);
921   AssertSyncReadEquals(kMsg2, kLen2);
922 }
923
924 TEST_P(SpdyProxyClientSocketTest, ReadErrorResponseBody) {
925   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
926   MockWrite writes[] = {
927     CreateMockWrite(*conn, 0, SYNCHRONOUS),
928   };
929
930   scoped_ptr<SpdyFrame> resp(ConstructConnectErrorReplyFrame());
931   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
932   scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
933   MockRead reads[] = {
934     CreateMockRead(*resp, 1, ASYNC),
935     CreateMockRead(*msg1, 2, ASYNC),
936     CreateMockRead(*msg2, 3, ASYNC),
937     MockRead(ASYNC, 0, 4),  // EOF
938   };
939
940   Initialize(reads, arraysize(reads), writes, arraysize(writes));
941
942   AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED);
943 }
944
945 // ----------- Reads and Writes
946
947 TEST_P(SpdyProxyClientSocketTest, AsyncReadAroundWrite) {
948   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
949   scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
950   MockWrite writes[] = {
951     CreateMockWrite(*conn, 0, SYNCHRONOUS),
952     CreateMockWrite(*msg2, 3, SYNCHRONOUS),
953   };
954
955   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
956   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
957   scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
958   MockRead reads[] = {
959     CreateMockRead(*resp, 1, ASYNC),
960     CreateMockRead(*msg1, 2, ASYNC),  // sync read
961     CreateMockRead(*msg3, 4, ASYNC),  // async read
962     MockRead(ASYNC, 0, 5),  // EOF
963   };
964
965   Initialize(reads, arraysize(reads), writes, arraysize(writes));
966
967   AssertConnectSucceeds();
968
969   Run(1);
970   AssertSyncReadEquals(kMsg1, kLen1);
971
972   AssertReadStarts(kMsg3, kLen3);
973   // Read should block until after the write succeeds
974
975   AssertAsyncWriteSucceeds(kMsg2, kLen2);  // Runs 1 step
976
977   ASSERT_FALSE(read_callback_.have_result());
978   Run(1);
979   // Now the read will return
980   AssertReadReturns(kMsg3, kLen3);
981 }
982
983 TEST_P(SpdyProxyClientSocketTest, AsyncWriteAroundReads) {
984   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
985   scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
986   MockWrite writes[] = {
987     CreateMockWrite(*conn, 0, SYNCHRONOUS),
988     CreateMockWrite(*msg2, 4, ASYNC),
989   };
990
991   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
992   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
993   scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
994   MockRead reads[] = {
995     CreateMockRead(*resp, 1, ASYNC),
996     CreateMockRead(*msg1, 2, ASYNC),
997     CreateMockRead(*msg3, 3, ASYNC),
998     MockRead(ASYNC, 0, 5),  // EOF
999   };
1000
1001   Initialize(reads, arraysize(reads), writes, arraysize(writes));
1002
1003   AssertConnectSucceeds();
1004
1005   Run(1);
1006   AssertSyncReadEquals(kMsg1, kLen1);
1007   // Write should block until the read completes
1008   AssertWriteReturns(kMsg2, kLen2, ERR_IO_PENDING);
1009
1010   AssertAsyncReadEquals(kMsg3, kLen3);
1011
1012   ASSERT_FALSE(write_callback_.have_result());
1013
1014   // Now the write will complete
1015   Run(1);
1016   AssertWriteLength(kLen2);
1017 }
1018
1019 // ----------- Reading/Writing on Closed socket
1020
1021 // Reading from an already closed socket should return 0
1022 TEST_P(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsZero) {
1023   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
1024   MockWrite writes[] = {
1025     CreateMockWrite(*conn, 0, SYNCHRONOUS),
1026   };
1027
1028   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
1029   MockRead reads[] = {
1030     CreateMockRead(*resp, 1, ASYNC),
1031     MockRead(ASYNC, 0, 2),  // EOF
1032   };
1033
1034   Initialize(reads, arraysize(reads), writes, arraysize(writes));
1035
1036   AssertConnectSucceeds();
1037
1038   Run(1);
1039
1040   ASSERT_FALSE(sock_->IsConnected());
1041   ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback()));
1042   ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback()));
1043   ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback()));
1044   ASSERT_FALSE(sock_->IsConnectedAndIdle());
1045 }
1046
1047 // Read pending when socket is closed should return 0
1048 TEST_P(SpdyProxyClientSocketTest, PendingReadOnCloseReturnsZero) {
1049   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
1050   MockWrite writes[] = {
1051     CreateMockWrite(*conn, 0, SYNCHRONOUS),
1052   };
1053
1054   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
1055   MockRead reads[] = {
1056     CreateMockRead(*resp, 1, ASYNC),
1057     MockRead(ASYNC, 0, 2),  // EOF
1058   };
1059
1060   Initialize(reads, arraysize(reads), writes, arraysize(writes));
1061
1062   AssertConnectSucceeds();
1063
1064   AssertReadStarts(kMsg1, kLen1);
1065
1066   Run(1);
1067
1068   ASSERT_EQ(0, read_callback_.WaitForResult());
1069 }
1070
1071 // Reading from a disconnected socket is an error
1072 TEST_P(SpdyProxyClientSocketTest,
1073        ReadOnDisconnectSocketReturnsNotConnected) {
1074   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
1075   MockWrite writes[] = {
1076     CreateMockWrite(*conn, 0, SYNCHRONOUS),
1077   };
1078
1079   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
1080   MockRead reads[] = {
1081     CreateMockRead(*resp, 1, ASYNC),
1082     MockRead(ASYNC, 0, 2),  // EOF
1083   };
1084
1085   Initialize(reads, arraysize(reads), writes, arraysize(writes));
1086
1087   AssertConnectSucceeds();
1088
1089   sock_->Disconnect();
1090
1091   ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED,
1092             sock_->Read(NULL, 1, CompletionCallback()));
1093 }
1094
1095 // Reading buffered data from an already closed socket should return
1096 // buffered data, then 0.
1097 TEST_P(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsBufferedData) {
1098   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
1099   MockWrite writes[] = {
1100     CreateMockWrite(*conn, 0, SYNCHRONOUS),
1101   };
1102
1103   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
1104   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
1105   MockRead reads[] = {
1106     CreateMockRead(*resp, 1, ASYNC),
1107     CreateMockRead(*msg1, 2, ASYNC),
1108     MockRead(ASYNC, 0, 3),  // EOF
1109   };
1110
1111   Initialize(reads, arraysize(reads), writes, arraysize(writes));
1112
1113   AssertConnectSucceeds();
1114
1115   Run(2);
1116
1117   ASSERT_FALSE(sock_->IsConnected());
1118   scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1));
1119   ASSERT_EQ(kLen1, sock_->Read(buf.get(), kLen1, CompletionCallback()));
1120   ASSERT_EQ(std::string(kMsg1, kLen1), std::string(buf->data(), kLen1));
1121
1122   ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback()));
1123   ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback()));
1124   sock_->Disconnect();
1125   ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED,
1126             sock_->Read(NULL, 1, CompletionCallback()));
1127 }
1128
1129 // Calling Write() on a closed socket is an error
1130 TEST_P(SpdyProxyClientSocketTest, WriteOnClosedStream) {
1131   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
1132   MockWrite writes[] = {
1133     CreateMockWrite(*conn, 0, SYNCHRONOUS),
1134   };
1135
1136   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
1137   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
1138   MockRead reads[] = {
1139     CreateMockRead(*resp, 1, ASYNC),
1140     MockRead(ASYNC, 0, 2),  // EOF
1141   };
1142
1143   Initialize(reads, arraysize(reads), writes, arraysize(writes));
1144
1145   AssertConnectSucceeds();
1146
1147   Run(1);  // Read EOF which will close the stream
1148   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1));
1149   EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED,
1150             sock_->Write(buf.get(), buf->size(), CompletionCallback()));
1151 }
1152
1153 // Calling Write() on a disconnected socket is an error
1154 TEST_P(SpdyProxyClientSocketTest, WriteOnDisconnectedSocket) {
1155   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
1156   MockWrite writes[] = {
1157     CreateMockWrite(*conn, 0, SYNCHRONOUS),
1158   };
1159
1160   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
1161   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
1162   MockRead reads[] = {
1163     CreateMockRead(*resp, 1, ASYNC),
1164     MockRead(ASYNC, 0, 2),  // EOF
1165   };
1166
1167   Initialize(reads, arraysize(reads), writes, arraysize(writes));
1168
1169   AssertConnectSucceeds();
1170
1171   sock_->Disconnect();
1172
1173   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1));
1174   EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED,
1175             sock_->Write(buf.get(), buf->size(), CompletionCallback()));
1176 }
1177
1178 // If the socket is closed with a pending Write(), the callback
1179 // should be called with ERR_CONNECTION_CLOSED.
1180 TEST_P(SpdyProxyClientSocketTest, WritePendingOnClose) {
1181   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
1182   MockWrite writes[] = {
1183     CreateMockWrite(*conn, 0, SYNCHRONOUS),
1184     MockWrite(ASYNC, ERR_ABORTED, 2),
1185   };
1186
1187   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
1188   MockRead reads[] = {
1189     CreateMockRead(*resp, 1, ASYNC),
1190     MockRead(ASYNC, 0, 3),  // EOF
1191   };
1192
1193   Initialize(reads, arraysize(reads), writes, arraysize(writes));
1194
1195   AssertConnectSucceeds();
1196
1197   EXPECT_TRUE(sock_->IsConnected());
1198
1199   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1));
1200   EXPECT_EQ(ERR_IO_PENDING,
1201             sock_->Write(buf.get(), buf->size(), write_callback_.callback()));
1202
1203   CloseSpdySession(ERR_ABORTED, std::string());
1204
1205   EXPECT_EQ(ERR_CONNECTION_CLOSED, write_callback_.WaitForResult());
1206 }
1207
1208 // If the socket is Disconnected with a pending Write(), the callback
1209 // should not be called.
1210 TEST_P(SpdyProxyClientSocketTest, DisconnectWithWritePending) {
1211   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
1212   MockWrite writes[] = {
1213     CreateMockWrite(*conn, 0, SYNCHRONOUS),
1214     MockWrite(SYNCHRONOUS, 0, 2),  // EOF
1215   };
1216
1217   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
1218   MockRead reads[] = {
1219     CreateMockRead(*resp, 1, ASYNC),
1220     MockRead(ASYNC, 0, 3),  // EOF
1221   };
1222
1223   Initialize(reads, arraysize(reads), writes, arraysize(writes));
1224
1225   AssertConnectSucceeds();
1226
1227   EXPECT_TRUE(sock_->IsConnected());
1228
1229   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1));
1230   EXPECT_EQ(ERR_IO_PENDING,
1231             sock_->Write(buf.get(), buf->size(), write_callback_.callback()));
1232
1233   sock_->Disconnect();
1234
1235   EXPECT_FALSE(sock_->IsConnected());
1236   EXPECT_FALSE(write_callback_.have_result());
1237 }
1238
1239 // If the socket is Disconnected with a pending Read(), the callback
1240 // should not be called.
1241 TEST_P(SpdyProxyClientSocketTest, DisconnectWithReadPending) {
1242   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
1243   MockWrite writes[] = {
1244     CreateMockWrite(*conn, 0, SYNCHRONOUS),
1245   };
1246
1247   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
1248   MockRead reads[] = {
1249     CreateMockRead(*resp, 1, ASYNC),
1250     MockRead(ASYNC, 0, 2),  // EOF
1251   };
1252
1253   Initialize(reads, arraysize(reads), writes, arraysize(writes));
1254
1255   AssertConnectSucceeds();
1256
1257   EXPECT_TRUE(sock_->IsConnected());
1258
1259   scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1));
1260   ASSERT_EQ(ERR_IO_PENDING,
1261             sock_->Read(buf.get(), kLen1, read_callback_.callback()));
1262
1263   sock_->Disconnect();
1264
1265   EXPECT_FALSE(sock_->IsConnected());
1266   EXPECT_FALSE(read_callback_.have_result());
1267 }
1268
1269 // If the socket is Reset when both a read and write are pending,
1270 // both should be called back.
1271 TEST_P(SpdyProxyClientSocketTest, RstWithReadAndWritePending) {
1272   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
1273   MockWrite writes[] = {
1274     CreateMockWrite(*conn, 0, SYNCHRONOUS),
1275     MockWrite(ASYNC, ERR_ABORTED, 3),
1276   };
1277
1278   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
1279   scoped_ptr<SpdyFrame> rst(
1280       spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
1281   MockRead reads[] = {
1282     CreateMockRead(*resp, 1, ASYNC),
1283     CreateMockRead(*rst, 2, ASYNC),
1284     MockRead(ASYNC, 0, 4)  // EOF
1285   };
1286
1287   Initialize(reads, arraysize(reads), writes, arraysize(writes));
1288
1289   AssertConnectSucceeds();
1290
1291   EXPECT_TRUE(sock_->IsConnected());
1292
1293   scoped_refptr<IOBuffer> read_buf(new IOBuffer(kLen1));
1294   ASSERT_EQ(ERR_IO_PENDING,
1295             sock_->Read(read_buf.get(), kLen1, read_callback_.callback()));
1296
1297   scoped_refptr<IOBufferWithSize> write_buf(CreateBuffer(kMsg1, kLen1));
1298   EXPECT_EQ(
1299       ERR_IO_PENDING,
1300       sock_->Write(
1301           write_buf.get(), write_buf->size(), write_callback_.callback()));
1302
1303   Run(2);
1304
1305   EXPECT_TRUE(sock_.get());
1306   EXPECT_TRUE(read_callback_.have_result());
1307   EXPECT_TRUE(write_callback_.have_result());
1308 }
1309
1310 // Makes sure the proxy client socket's source gets the expected NetLog events
1311 // and only the expected NetLog events (No SpdySession events).
1312 TEST_P(SpdyProxyClientSocketTest, NetLog) {
1313   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
1314   MockWrite writes[] = {
1315     CreateMockWrite(*conn, 0, SYNCHRONOUS),
1316   };
1317
1318   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
1319   scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
1320   MockRead reads[] = {
1321     CreateMockRead(*resp, 1, ASYNC),
1322     CreateMockRead(*msg1, 2, ASYNC),
1323     MockRead(ASYNC, 0, 3),  // EOF
1324   };
1325
1326   Initialize(reads, arraysize(reads), writes, arraysize(writes));
1327
1328   AssertConnectSucceeds();
1329
1330   Run(1);  // SpdySession consumes the next read and sends it to
1331            // sock_ to be buffered.
1332   AssertSyncReadEquals(kMsg1, kLen1);
1333
1334   NetLog::Source sock_source = sock_->NetLog().source();
1335   sock_.reset();
1336
1337   CapturingNetLog::CapturedEntryList entry_list;
1338   net_log_.GetEntriesForSource(sock_source, &entry_list);
1339
1340   ASSERT_EQ(entry_list.size(), 10u);
1341   EXPECT_TRUE(LogContainsBeginEvent(entry_list, 0, NetLog::TYPE_SOCKET_ALIVE));
1342   EXPECT_TRUE(LogContainsEvent(entry_list, 1,
1343                   NetLog::TYPE_SPDY_PROXY_CLIENT_SESSION,
1344                   NetLog::PHASE_NONE));
1345   EXPECT_TRUE(LogContainsBeginEvent(entry_list, 2,
1346                   NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST));
1347   EXPECT_TRUE(LogContainsEvent(entry_list, 3,
1348                   NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1349                   NetLog::PHASE_NONE));
1350   EXPECT_TRUE(LogContainsEndEvent(entry_list, 4,
1351                   NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST));
1352   EXPECT_TRUE(LogContainsBeginEvent(entry_list, 5,
1353                   NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS));
1354   EXPECT_TRUE(LogContainsEvent(entry_list, 6,
1355                   NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1356                   NetLog::PHASE_NONE));
1357   EXPECT_TRUE(LogContainsEndEvent(entry_list, 7,
1358                   NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS));
1359   EXPECT_TRUE(LogContainsEvent(entry_list, 8,
1360                   NetLog::TYPE_SOCKET_BYTES_RECEIVED,
1361                   NetLog::PHASE_NONE));
1362   EXPECT_TRUE(LogContainsEndEvent(entry_list, 9, NetLog::TYPE_SOCKET_ALIVE));
1363 }
1364
1365 // CompletionCallback that causes the SpdyProxyClientSocket to be
1366 // deleted when Run is invoked.
1367 class DeleteSockCallback : public TestCompletionCallbackBase {
1368  public:
1369   explicit DeleteSockCallback(scoped_ptr<SpdyProxyClientSocket>* sock)
1370       : sock_(sock),
1371         callback_(base::Bind(&DeleteSockCallback::OnComplete,
1372                              base::Unretained(this))) {
1373   }
1374
1375   virtual ~DeleteSockCallback() {
1376   }
1377
1378   const CompletionCallback& callback() const { return callback_; }
1379
1380  private:
1381   void OnComplete(int result) {
1382     sock_->reset(NULL);
1383     SetResult(result);
1384   }
1385
1386   scoped_ptr<SpdyProxyClientSocket>* sock_;
1387   CompletionCallback callback_;
1388
1389   DISALLOW_COPY_AND_ASSIGN(DeleteSockCallback);
1390 };
1391
1392 // If the socket is Reset when both a read and write are pending, and the
1393 // read callback causes the socket to be deleted, the write callback should
1394 // not be called.
1395 TEST_P(SpdyProxyClientSocketTest, RstWithReadAndWritePendingDelete) {
1396   scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
1397   MockWrite writes[] = {
1398     CreateMockWrite(*conn, 0, SYNCHRONOUS),
1399     MockWrite(ASYNC, ERR_ABORTED, 3),
1400   };
1401
1402   scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
1403   scoped_ptr<SpdyFrame> rst(
1404       spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
1405   MockRead reads[] = {
1406     CreateMockRead(*resp, 1, ASYNC),
1407     CreateMockRead(*rst, 2, ASYNC),
1408     MockRead(ASYNC, 0, 4),  // EOF
1409   };
1410
1411   Initialize(reads, arraysize(reads), writes, arraysize(writes));
1412
1413   AssertConnectSucceeds();
1414
1415   EXPECT_TRUE(sock_->IsConnected());
1416
1417   DeleteSockCallback read_callback(&sock_);
1418
1419   scoped_refptr<IOBuffer> read_buf(new IOBuffer(kLen1));
1420   ASSERT_EQ(ERR_IO_PENDING,
1421             sock_->Read(read_buf.get(), kLen1, read_callback.callback()));
1422
1423   scoped_refptr<IOBufferWithSize> write_buf(CreateBuffer(kMsg1, kLen1));
1424   EXPECT_EQ(
1425       ERR_IO_PENDING,
1426       sock_->Write(
1427           write_buf.get(), write_buf->size(), write_callback_.callback()));
1428
1429   Run(1);
1430
1431   EXPECT_FALSE(sock_.get());
1432   EXPECT_TRUE(read_callback.have_result());
1433   EXPECT_FALSE(write_callback_.have_result());
1434 }
1435
1436 }  // namespace net