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