• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AddAuthToCache()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 
Run(int steps)108   void Run(int steps) {
109     data_->StopAfter(steps);
110     data_->Run();
111   }
112 
CloseSpdySession(net::Error error,const std::string & description)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 
SpdyProxyClientSocketTest()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 
TearDown()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 
Initialize(MockRead * reads,size_t reads_count,MockWrite * writes,size_t writes_count)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 
CreateBuffer(const char * data,int size)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 
AssertConnectSucceeds()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 
AssertConnectFails(int result)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 
AssertConnectionEstablished()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 
AssertSyncReadEquals(const char * data,int len)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 
AssertAsyncReadEquals(const char * data,int len)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 
AssertReadStarts(const char * data,int len)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 
AssertReadReturns(const char * data,int len)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 
AssertAsyncWriteSucceeds(const char * data,int len)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 
AssertWriteReturns(const char * data,int len,int rv)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 
AssertWriteLength(int len)294 void SpdyProxyClientSocketTest::AssertWriteLength(int len) {
295   EXPECT_EQ(len, write_callback_.WaitForResult());
296 }
297 
AssertAsyncWriteWithReadsSucceeds(const char * data,int len,int num_reads)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 
PopulateConnectRequestIR(SpdyHeaderBlock * block)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 
PopulateConnectReplyIR(SpdyHeaderBlock * block,const char * status)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*
ConstructConnectRequestFrame()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.
ConstructConnectAuthRequestFrame()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.
ConstructConnectReplyFrame()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.
ConstructConnectAuthReplyFrame()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.
ConstructConnectRedirectReplyFrame()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.
ConstructConnectErrorReplyFrame()372 SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() {
373   SpdyHeaderBlock block;
374   PopulateConnectReplyIR(&block, "500");
375   return spdy_util_.ConstructSpdyReply(kStreamId, block);
376 }
377 
ConstructBodyFrame(const char * data,int length)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 
TEST_P(SpdyProxyClientSocketTest,ConnectSendsCorrectRequest)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 
TEST_P(SpdyProxyClientSocketTest,ConnectWithAuthRequested)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 
TEST_P(SpdyProxyClientSocketTest,ConnectWithAuthCredentials)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 
TEST_P(SpdyProxyClientSocketTest,ConnectRedirects)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 
TEST_P(SpdyProxyClientSocketTest,ConnectFails)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 
TEST_P(SpdyProxyClientSocketTest,WasEverUsedReturnsCorrectValues)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 
TEST_P(SpdyProxyClientSocketTest,GetPeerAddressReturnsCorrectValues)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 
TEST_P(SpdyProxyClientSocketTest,WriteSendsDataInDataFrame)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 
TEST_P(SpdyProxyClientSocketTest,WriteSplitsLargeDataIntoMultipleFrames)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 
TEST_P(SpdyProxyClientSocketTest,ReadReadsDataInDataFrame)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 
TEST_P(SpdyProxyClientSocketTest,ReadDataFromBufferedFrames)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 
TEST_P(SpdyProxyClientSocketTest,ReadDataMultipleBufferedFrames)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 
TEST_P(SpdyProxyClientSocketTest,LargeReadWillMergeDataFromDifferentFrames)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 
TEST_P(SpdyProxyClientSocketTest,MultipleShortReadsThenMoreRead)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 
TEST_P(SpdyProxyClientSocketTest,ReadWillSplitDataFromLargeFrame)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 
TEST_P(SpdyProxyClientSocketTest,MultipleReadsFromSameLargeFrame)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 
TEST_P(SpdyProxyClientSocketTest,ReadAuthResponseBody)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 
TEST_P(SpdyProxyClientSocketTest,ReadErrorResponseBody)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 
TEST_P(SpdyProxyClientSocketTest,AsyncReadAroundWrite)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 
TEST_P(SpdyProxyClientSocketTest,AsyncWriteAroundReads)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
TEST_P(SpdyProxyClientSocketTest,ReadOnClosedSocketReturnsZero)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
TEST_P(SpdyProxyClientSocketTest,PendingReadOnCloseReturnsZero)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
TEST_P(SpdyProxyClientSocketTest,ReadOnDisconnectSocketReturnsNotConnected)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.
TEST_P(SpdyProxyClientSocketTest,ReadOnClosedSocketReturnsBufferedData)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
TEST_P(SpdyProxyClientSocketTest,WriteOnClosedStream)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
TEST_P(SpdyProxyClientSocketTest,WriteOnDisconnectedSocket)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.
TEST_P(SpdyProxyClientSocketTest,WritePendingOnClose)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.
TEST_P(SpdyProxyClientSocketTest,DisconnectWithWritePending)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.
TEST_P(SpdyProxyClientSocketTest,DisconnectWithReadPending)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.
TEST_P(SpdyProxyClientSocketTest,RstWithReadAndWritePending)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).
TEST_P(SpdyProxyClientSocketTest,NetLog)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:
DeleteSockCallback(scoped_ptr<SpdyProxyClientSocket> * sock)1314   explicit DeleteSockCallback(scoped_ptr<SpdyProxyClientSocket>* sock)
1315       : sock_(sock),
1316         callback_(base::Bind(&DeleteSockCallback::OnComplete,
1317                              base::Unretained(this))) {
1318   }
1319 
~DeleteSockCallback()1320   virtual ~DeleteSockCallback() {
1321   }
1322 
callback() const1323   const CompletionCallback& callback() const { return callback_; }
1324 
1325  private:
OnComplete(int result)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.
TEST_P(SpdyProxyClientSocketTest,RstWithReadAndWritePendingDelete)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
1385