• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
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 <utility>
8 
9 #include "base/functional/bind.h"
10 #include "base/functional/callback_helpers.h"
11 #include "base/memory/raw_ptr.h"
12 #include "base/run_loop.h"
13 #include "base/strings/string_piece.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "net/base/address_list.h"
16 #include "net/base/host_port_pair.h"
17 #include "net/base/load_timing_info.h"
18 #include "net/base/proxy_chain.h"
19 #include "net/base/proxy_server.h"
20 #include "net/base/test_completion_callback.h"
21 #include "net/base/winsock_init.h"
22 #include "net/dns/mock_host_resolver.h"
23 #include "net/dns/public/secure_dns_policy.h"
24 #include "net/http/http_proxy_connect_job.h"
25 #include "net/http/http_response_headers.h"
26 #include "net/http/http_response_info.h"
27 #include "net/log/net_log.h"
28 #include "net/log/net_log_event_type.h"
29 #include "net/log/net_log_source.h"
30 #include "net/log/test_net_log.h"
31 #include "net/log/test_net_log_util.h"
32 #include "net/socket/client_socket_factory.h"
33 #include "net/socket/connect_job_test_util.h"
34 #include "net/socket/next_proto.h"
35 #include "net/socket/socket_tag.h"
36 #include "net/socket/socket_test_util.h"
37 #include "net/socket/socks_connect_job.h"
38 #include "net/socket/ssl_client_socket.h"
39 #include "net/socket/ssl_connect_job.h"
40 #include "net/socket/stream_socket.h"
41 #include "net/socket/tcp_client_socket.h"
42 #include "net/socket/transport_connect_job.h"
43 #include "net/spdy/buffered_spdy_framer.h"
44 #include "net/spdy/spdy_http_utils.h"
45 #include "net/spdy/spdy_session_pool.h"
46 #include "net/spdy/spdy_test_util_common.h"
47 #include "net/test/cert_test_util.h"
48 #include "net/test/gtest_util.h"
49 #include "net/test/test_data_directory.h"
50 #include "net/test/test_with_task_environment.h"
51 #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
52 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
53 #include "testing/gmock/include/gmock/gmock.h"
54 #include "testing/gtest/include/gtest/gtest.h"
55 #include "testing/platform_test.h"
56 #include "url/gurl.h"
57 #include "url/scheme_host_port.h"
58 
59 using net::test::IsError;
60 using net::test::IsOk;
61 
62 //-----------------------------------------------------------------------------
63 
64 namespace net {
65 
66 namespace {
67 
68 static const char kRequestUrl[] = "https://www.google.com/";
69 static const char kOriginHost[] = "www.google.com";
70 static const int kOriginPort = 443;
71 static const char kOriginHostPort[] = "www.google.com:443";
72 static const char kProxyUrl[] = "https://myproxy:6121/";
73 static const char kProxyHost[] = "myproxy";
74 static const int kProxyPort = 6121;
75 static const char kUserAgent[] = "Mozilla/1.0";
76 
77 static const int kStreamId = 1;
78 
79 static const char kMsg1[] = "\0hello!\xff";
80 static const int kLen1 = 8;
81 static const char kMsg2[] = "\0a2345678\0";
82 static const int kLen2 = 10;
83 static const char kMsg3[] = "bye!";
84 static const int kLen3 = 4;
85 static const char kMsg33[] = "bye!bye!";
86 static const int kLen33 = kLen3 + kLen3;
87 static const char kMsg333[] = "bye!bye!bye!";
88 static const int kLen333 = kLen3 + kLen3 + kLen3;
89 
90 static const char kRedirectUrl[] = "https://example.com/";
91 
92 // Creates a SpdySession with a StreamSocket, instead of a ClientSocketHandle.
CreateSpdyProxySession(const url::SchemeHostPort & destination,HttpNetworkSession * http_session,const SpdySessionKey & key,const CommonConnectJobParams * common_connect_job_params)93 base::WeakPtr<SpdySession> CreateSpdyProxySession(
94     const url::SchemeHostPort& destination,
95     HttpNetworkSession* http_session,
96     const SpdySessionKey& key,
97     const CommonConnectJobParams* common_connect_job_params) {
98   EXPECT_FALSE(http_session->spdy_session_pool()->FindAvailableSession(
99       key, true /* enable_ip_based_pooling */, false /* is_websocket */,
100       NetLogWithSource()));
101 
102   auto transport_params = base::MakeRefCounted<TransportSocketParams>(
103       destination, NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
104       OnHostResolutionCallback(),
105       /*supported_alpns=*/base::flat_set<std::string>{"h2", "http/1.1"});
106 
107   SSLConfig ssl_config;
108   auto ssl_params = base::MakeRefCounted<SSLSocketParams>(
109       transport_params, /*socks_proxy_params=*/nullptr,
110       /*http_proxy_params=*/nullptr,
111       HostPortPair::FromSchemeHostPort(destination), ssl_config,
112       key.privacy_mode(), key.network_anonymization_key());
113   TestConnectJobDelegate connect_job_delegate;
114   SSLConnectJob connect_job(MEDIUM, SocketTag(), common_connect_job_params,
115                             ssl_params, &connect_job_delegate,
116                             nullptr /* net_log */);
117   connect_job_delegate.StartJobExpectingResult(&connect_job, OK,
118                                                false /* expect_sync_result */);
119 
120   base::WeakPtr<SpdySession> spdy_session =
121       http_session->spdy_session_pool()->CreateAvailableSessionFromSocket(
122           key, connect_job_delegate.ReleaseSocket(),
123           LoadTimingInfo::ConnectTiming(), NetLogWithSource());
124   // Failure is reported asynchronously.
125   EXPECT_TRUE(spdy_session);
126   EXPECT_TRUE(HasSpdySession(http_session->spdy_session_pool(), key));
127   return spdy_session;
128 }
129 
130 }  // namespace
131 
132 class SpdyProxyClientSocketTest : public PlatformTest,
133                                   public WithTaskEnvironment,
134                                   public ::testing::WithParamInterface<bool> {
135  public:
136   SpdyProxyClientSocketTest();
137 
138   SpdyProxyClientSocketTest(const SpdyProxyClientSocketTest&) = delete;
139   SpdyProxyClientSocketTest& operator=(const SpdyProxyClientSocketTest&) =
140       delete;
141 
142   ~SpdyProxyClientSocketTest() override;
143 
144   void TearDown() override;
145 
146  protected:
147   void Initialize(base::span<const MockRead> reads,
148                   base::span<const MockWrite> writes);
149   void PopulateConnectRequestIR(spdy::Http2HeaderBlock* syn_ir);
150   void PopulateConnectReplyIR(spdy::Http2HeaderBlock* block,
151                               const char* status);
152   spdy::SpdySerializedFrame ConstructConnectRequestFrame(
153       RequestPriority priority = LOWEST);
154   spdy::SpdySerializedFrame ConstructConnectAuthRequestFrame();
155   spdy::SpdySerializedFrame ConstructConnectReplyFrame();
156   spdy::SpdySerializedFrame ConstructConnectAuthReplyFrame();
157   spdy::SpdySerializedFrame ConstructConnectRedirectReplyFrame();
158   spdy::SpdySerializedFrame ConstructConnectErrorReplyFrame();
159   spdy::SpdySerializedFrame ConstructBodyFrame(const char* data,
160                                                int length,
161                                                bool fin = false);
162   scoped_refptr<IOBufferWithSize> CreateBuffer(const char* data, int size);
163   void AssertConnectSucceeds();
164   void AssertConnectFails(int result);
165   void AssertConnectionEstablished();
166   void AssertSyncReadEquals(const char* data, int len);
167   void AssertSyncReadEOF();
168   void AssertAsyncReadEquals(const char* data, int len, bool fin = false);
169   void AssertReadStarts(const char* data, int len);
170   void AssertReadReturns(const char* data, int len);
171   void AssertAsyncWriteSucceeds(const char* data, int len);
172   void AssertWriteReturns(const char* data, int len, int rv);
173   void AssertWriteLength(int len);
174 
AddAuthToCache()175   void AddAuthToCache() {
176     const std::u16string kFoo(u"foo");
177     const std::u16string kBar(u"bar");
178     session_->http_auth_cache()->Add(
179         url::SchemeHostPort{GURL(kProxyUrl)}, HttpAuth::AUTH_PROXY, "MyRealm1",
180         HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
181         "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
182   }
183 
ResumeAndRun()184   void ResumeAndRun() {
185     // Run until the pause, if the provider isn't paused yet.
186     data_->RunUntilPaused();
187     data_->Resume();
188     base::RunLoop().RunUntilIdle();
189   }
190 
CloseSpdySession(Error error,const std::string & description)191   void CloseSpdySession(Error error, const std::string& description) {
192     spdy_session_->CloseSessionOnError(error, description);
193   }
194 
195   // Whether to use net::Socket::ReadIfReady() instead of net::Socket::Read().
use_read_if_ready() const196   bool use_read_if_ready() const { return GetParam(); }
197 
198   NetLogWithSource net_log_with_source_{
199       NetLogWithSource::Make(NetLogSourceType::NONE)};
200   RecordingNetLogObserver net_log_observer_;
201   SpdyTestUtil spdy_util_;
202   std::unique_ptr<SpdyProxyClientSocket> sock_;
203   TestCompletionCallback read_callback_;
204   TestCompletionCallback write_callback_;
205   std::unique_ptr<SequencedSocketData> data_;
206 
207  private:
208   scoped_refptr<IOBuffer> read_buf_;
209   SpdySessionDependencies session_deps_;
210   std::unique_ptr<HttpNetworkSession> session_;
211   MockConnect connect_data_;
212   base::WeakPtr<SpdySession> spdy_session_;
213   std::string user_agent_;
214   GURL url_;
215   HostPortPair proxy_host_port_;
216   HostPortPair endpoint_host_port_pair_;
217   ProxyChain proxy_chain_;
218   SpdySessionKey endpoint_spdy_session_key_;
219   std::unique_ptr<CommonConnectJobParams> common_connect_job_params_;
220   SSLSocketDataProvider ssl_;
221 };
222 
SpdyProxyClientSocketTest()223 SpdyProxyClientSocketTest::SpdyProxyClientSocketTest()
224     : connect_data_(SYNCHRONOUS, OK),
225       user_agent_(kUserAgent),
226       url_(kRequestUrl),
227       proxy_host_port_(kProxyHost, kProxyPort),
228       endpoint_host_port_pair_(kOriginHost, kOriginPort),
229       proxy_chain_(ProxyServer::SCHEME_HTTPS, proxy_host_port_),
230       endpoint_spdy_session_key_(endpoint_host_port_pair_,
231                                  proxy_chain_,
232                                  PRIVACY_MODE_DISABLED,
233                                  SpdySessionKey::IsProxySession::kFalse,
234                                  SocketTag(),
235                                  NetworkAnonymizationKey(),
236                                  SecureDnsPolicy::kAllow),
237       ssl_(SYNCHRONOUS, OK) {
238   session_deps_.net_log = NetLog::Get();
239 }
240 
~SpdyProxyClientSocketTest()241 SpdyProxyClientSocketTest::~SpdyProxyClientSocketTest() {
242   if (data_) {
243     EXPECT_TRUE(data_->AllWriteDataConsumed());
244     EXPECT_TRUE(data_->AllReadDataConsumed());
245   }
246 }
247 
TearDown()248 void SpdyProxyClientSocketTest::TearDown() {
249   if (session_)
250     session_->spdy_session_pool()->CloseAllSessions();
251 
252   // Empty the current queue.
253   base::RunLoop().RunUntilIdle();
254   PlatformTest::TearDown();
255 }
256 
Initialize(base::span<const MockRead> reads,base::span<const MockWrite> writes)257 void SpdyProxyClientSocketTest::Initialize(base::span<const MockRead> reads,
258                                            base::span<const MockWrite> writes) {
259   data_ = std::make_unique<SequencedSocketData>(reads, writes);
260   data_->set_connect_data(connect_data_);
261   session_deps_.socket_factory->AddSocketDataProvider(data_.get());
262 
263   ssl_.ssl_info.cert =
264       ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
265   ASSERT_TRUE(ssl_.ssl_info.cert);
266   ssl_.next_proto = NextProto::kProtoHTTP2;
267   session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
268 
269   session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
270   common_connect_job_params_ = std::make_unique<CommonConnectJobParams>(
271       session_->CreateCommonConnectJobParams());
272 
273   // Creates the SPDY session and stream.
274   spdy_session_ = CreateSpdyProxySession(
275       url::SchemeHostPort(url_), session_.get(), endpoint_spdy_session_key_,
276       common_connect_job_params_.get());
277 
278   base::WeakPtr<SpdyStream> spdy_stream(
279       CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, spdy_session_, url_,
280                                 LOWEST, net_log_with_source_));
281   ASSERT_TRUE(spdy_stream.get() != nullptr);
282 
283   // Create the SpdyProxyClientSocket.
284   sock_ = std::make_unique<SpdyProxyClientSocket>(
285       spdy_stream, proxy_chain_, /*proxy_chain_index=*/0, user_agent_,
286       endpoint_host_port_pair_, net_log_with_source_,
287       base::MakeRefCounted<HttpAuthController>(
288           HttpAuth::AUTH_PROXY, GURL("https://" + proxy_host_port_.ToString()),
289           NetworkAnonymizationKey(), session_->http_auth_cache(),
290           session_->http_auth_handler_factory(), session_->host_resolver()),
291       // Testing with the proxy delegate is in HttpProxyConnectJobTest.
292       nullptr);
293 }
294 
CreateBuffer(const char * data,int size)295 scoped_refptr<IOBufferWithSize> SpdyProxyClientSocketTest::CreateBuffer(
296     const char* data, int size) {
297   scoped_refptr<IOBufferWithSize> buf =
298       base::MakeRefCounted<IOBufferWithSize>(size);
299   memcpy(buf->data(), data, size);
300   return buf;
301 }
302 
AssertConnectSucceeds()303 void SpdyProxyClientSocketTest::AssertConnectSucceeds() {
304   ASSERT_THAT(sock_->Connect(read_callback_.callback()),
305               IsError(ERR_IO_PENDING));
306   ASSERT_THAT(read_callback_.WaitForResult(), IsOk());
307 }
308 
AssertConnectFails(int result)309 void SpdyProxyClientSocketTest::AssertConnectFails(int result) {
310   ASSERT_THAT(sock_->Connect(read_callback_.callback()),
311               IsError(ERR_IO_PENDING));
312   ASSERT_EQ(result, read_callback_.WaitForResult());
313 }
314 
AssertConnectionEstablished()315 void SpdyProxyClientSocketTest::AssertConnectionEstablished() {
316   const HttpResponseInfo* response = sock_->GetConnectResponseInfo();
317   ASSERT_TRUE(response != nullptr);
318   ASSERT_EQ(200, response->headers->response_code());
319   // Although the underlying HTTP/2 connection uses TLS and negotiates ALPN, the
320   // tunnel itself is a TCP connection to the origin and should not report these
321   // values.
322   net::SSLInfo ssl_info;
323   EXPECT_FALSE(sock_->GetSSLInfo(&ssl_info));
324   EXPECT_EQ(sock_->GetNegotiatedProtocol(), NextProto::kProtoUnknown);
325 }
326 
AssertSyncReadEquals(const char * data,int len)327 void SpdyProxyClientSocketTest::AssertSyncReadEquals(const char* data,
328                                                      int len) {
329   auto buf = base::MakeRefCounted<IOBufferWithSize>(len);
330   if (use_read_if_ready()) {
331     ASSERT_EQ(len,
332               sock_->ReadIfReady(buf.get(), len, CompletionOnceCallback()));
333   } else {
334     ASSERT_EQ(len, sock_->Read(buf.get(), len, CompletionOnceCallback()));
335   }
336   ASSERT_EQ(std::string(data, len), std::string(buf->data(), len));
337   ASSERT_TRUE(sock_->IsConnected());
338 }
339 
AssertSyncReadEOF()340 void SpdyProxyClientSocketTest::AssertSyncReadEOF() {
341   if (use_read_if_ready()) {
342     ASSERT_EQ(0, sock_->ReadIfReady(nullptr, 1, read_callback_.callback()));
343   } else {
344     ASSERT_EQ(0, sock_->Read(nullptr, 1, read_callback_.callback()));
345   }
346 }
347 
AssertAsyncReadEquals(const char * data,int len,bool fin)348 void SpdyProxyClientSocketTest::AssertAsyncReadEquals(const char* data,
349                                                       int len,
350                                                       bool fin) {
351   // Issue the read, which will be completed asynchronously
352   auto buf = base::MakeRefCounted<IOBufferWithSize>(len);
353   if (use_read_if_ready()) {
354     ASSERT_EQ(ERR_IO_PENDING,
355               sock_->ReadIfReady(buf.get(), len, read_callback_.callback()));
356   } else {
357     ASSERT_EQ(ERR_IO_PENDING,
358               sock_->Read(buf.get(), len, read_callback_.callback()));
359   }
360   EXPECT_TRUE(sock_->IsConnected());
361 
362   ResumeAndRun();
363 
364   if (use_read_if_ready()) {
365     EXPECT_EQ(OK, read_callback_.WaitForResult());
366     ASSERT_EQ(len,
367               sock_->ReadIfReady(buf.get(), len, read_callback_.callback()));
368   } else {
369     EXPECT_EQ(len, read_callback_.WaitForResult());
370   }
371 
372   if (fin) {
373     EXPECT_FALSE(sock_->IsConnected());
374   } else {
375     EXPECT_TRUE(sock_->IsConnected());
376   }
377 
378   ASSERT_EQ(std::string(data, len), std::string(buf->data(), len));
379 }
380 
AssertReadStarts(const char * data,int len)381 void SpdyProxyClientSocketTest::AssertReadStarts(const char* data, int len) {
382   // Issue the read, which will be completed asynchronously.
383   read_buf_ = base::MakeRefCounted<IOBufferWithSize>(len);
384   if (use_read_if_ready()) {
385     ASSERT_EQ(ERR_IO_PENDING, sock_->ReadIfReady(read_buf_.get(), len,
386                                                  read_callback_.callback()));
387   } else {
388     ASSERT_EQ(ERR_IO_PENDING,
389               sock_->Read(read_buf_.get(), len, read_callback_.callback()));
390   }
391   EXPECT_TRUE(sock_->IsConnected());
392 }
393 
AssertReadReturns(const char * data,int len)394 void SpdyProxyClientSocketTest::AssertReadReturns(const char* data, int len) {
395   EXPECT_TRUE(sock_->IsConnected());
396 
397   // Now the read will return
398   if (use_read_if_ready()) {
399     EXPECT_EQ(OK, read_callback_.WaitForResult());
400     ASSERT_EQ(len, sock_->ReadIfReady(read_buf_.get(), len,
401                                       read_callback_.callback()));
402   } else {
403     EXPECT_EQ(len, read_callback_.WaitForResult());
404   }
405   ASSERT_EQ(std::string(data, len), std::string(read_buf_->data(), len));
406 }
407 
AssertAsyncWriteSucceeds(const char * data,int len)408 void SpdyProxyClientSocketTest::AssertAsyncWriteSucceeds(const char* data,
409                                                               int len) {
410   AssertWriteReturns(data, len, ERR_IO_PENDING);
411   AssertWriteLength(len);
412 }
413 
AssertWriteReturns(const char * data,int len,int rv)414 void SpdyProxyClientSocketTest::AssertWriteReturns(const char* data,
415                                                    int len,
416                                                    int rv) {
417   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(data, len));
418   EXPECT_EQ(rv, sock_->Write(buf.get(), buf->size(), write_callback_.callback(),
419                              TRAFFIC_ANNOTATION_FOR_TESTS));
420 }
421 
AssertWriteLength(int len)422 void SpdyProxyClientSocketTest::AssertWriteLength(int len) {
423   EXPECT_EQ(len, write_callback_.WaitForResult());
424 }
425 
PopulateConnectRequestIR(spdy::Http2HeaderBlock * block)426 void SpdyProxyClientSocketTest::PopulateConnectRequestIR(
427     spdy::Http2HeaderBlock* block) {
428   (*block)[spdy::kHttp2MethodHeader] = "CONNECT";
429   (*block)[spdy::kHttp2AuthorityHeader] = kOriginHostPort;
430   (*block)["user-agent"] = kUserAgent;
431 }
432 
PopulateConnectReplyIR(spdy::Http2HeaderBlock * block,const char * status)433 void SpdyProxyClientSocketTest::PopulateConnectReplyIR(
434     spdy::Http2HeaderBlock* block,
435     const char* status) {
436   (*block)[spdy::kHttp2StatusHeader] = status;
437 }
438 
439 // Constructs a standard SPDY HEADERS frame for a CONNECT request.
440 spdy::SpdySerializedFrame
ConstructConnectRequestFrame(RequestPriority priority)441 SpdyProxyClientSocketTest::ConstructConnectRequestFrame(
442     RequestPriority priority) {
443   spdy::Http2HeaderBlock block;
444   PopulateConnectRequestIR(&block);
445   return spdy_util_.ConstructSpdyHeaders(kStreamId, std::move(block), priority,
446                                          false);
447 }
448 
449 // Constructs a SPDY HEADERS frame for a CONNECT request which includes
450 // Proxy-Authorization headers.
451 spdy::SpdySerializedFrame
ConstructConnectAuthRequestFrame()452 SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() {
453   spdy::Http2HeaderBlock block;
454   PopulateConnectRequestIR(&block);
455   block["proxy-authorization"] = "Basic Zm9vOmJhcg==";
456   return spdy_util_.ConstructSpdyHeaders(kStreamId, std::move(block), LOWEST,
457                                          false);
458 }
459 
460 // Constructs a standard SPDY HEADERS frame to match the SPDY CONNECT.
461 spdy::SpdySerializedFrame
ConstructConnectReplyFrame()462 SpdyProxyClientSocketTest::ConstructConnectReplyFrame() {
463   spdy::Http2HeaderBlock block;
464   PopulateConnectReplyIR(&block, "200");
465   return spdy_util_.ConstructSpdyReply(kStreamId, std::move(block));
466 }
467 
468 // Constructs a standard SPDY HEADERS frame to match the SPDY CONNECT,
469 // including Proxy-Authenticate headers.
470 spdy::SpdySerializedFrame
ConstructConnectAuthReplyFrame()471 SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() {
472   spdy::Http2HeaderBlock block;
473   PopulateConnectReplyIR(&block, "407");
474   block["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
475   return spdy_util_.ConstructSpdyReply(kStreamId, std::move(block));
476 }
477 
478 // Constructs a SPDY HEADERS frame with an HTTP 302 redirect.
479 spdy::SpdySerializedFrame
ConstructConnectRedirectReplyFrame()480 SpdyProxyClientSocketTest::ConstructConnectRedirectReplyFrame() {
481   spdy::Http2HeaderBlock block;
482   PopulateConnectReplyIR(&block, "302");
483   block["location"] = kRedirectUrl;
484   block["set-cookie"] = "foo=bar";
485   return spdy_util_.ConstructSpdyReply(kStreamId, std::move(block));
486 }
487 
488 // Constructs a SPDY HEADERS frame with an HTTP 500 error.
489 spdy::SpdySerializedFrame
ConstructConnectErrorReplyFrame()490 SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() {
491   spdy::Http2HeaderBlock block;
492   PopulateConnectReplyIR(&block, "500");
493   return spdy_util_.ConstructSpdyReply(kStreamId, std::move(block));
494 }
495 
ConstructBodyFrame(const char * data,int length,bool fin)496 spdy::SpdySerializedFrame SpdyProxyClientSocketTest::ConstructBodyFrame(
497     const char* data,
498     int length,
499     bool fin) {
500   return spdy_util_.ConstructSpdyDataFrame(
501       kStreamId, base::StringPiece(data, length), fin);
502 }
503 
504 // ----------- Connect
505 
506 INSTANTIATE_TEST_SUITE_P(All,
507                          SpdyProxyClientSocketTest,
508                          ::testing::Bool());
509 
TEST_P(SpdyProxyClientSocketTest,ConnectSendsCorrectRequest)510 TEST_P(SpdyProxyClientSocketTest, ConnectSendsCorrectRequest) {
511   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
512   MockWrite writes[] = {
513       CreateMockWrite(conn, 0, SYNCHRONOUS),
514   };
515 
516   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
517   MockRead reads[] = {
518       CreateMockRead(resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
519   };
520 
521   Initialize(reads, writes);
522 
523   ASSERT_FALSE(sock_->IsConnected());
524 
525   AssertConnectSucceeds();
526 
527   AssertConnectionEstablished();
528 }
529 
TEST_P(SpdyProxyClientSocketTest,ConnectWithAuthRequested)530 TEST_P(SpdyProxyClientSocketTest, ConnectWithAuthRequested) {
531   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
532   MockWrite writes[] = {
533       CreateMockWrite(conn, 0, SYNCHRONOUS),
534   };
535 
536   spdy::SpdySerializedFrame resp(ConstructConnectAuthReplyFrame());
537   MockRead reads[] = {
538       CreateMockRead(resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
539   };
540 
541   Initialize(reads, writes);
542 
543   AssertConnectFails(ERR_PROXY_AUTH_REQUESTED);
544 
545   const HttpResponseInfo* response = sock_->GetConnectResponseInfo();
546   ASSERT_TRUE(response != nullptr);
547   ASSERT_EQ(407, response->headers->response_code());
548 }
549 
TEST_P(SpdyProxyClientSocketTest,ConnectWithAuthCredentials)550 TEST_P(SpdyProxyClientSocketTest, ConnectWithAuthCredentials) {
551   spdy::SpdySerializedFrame conn(ConstructConnectAuthRequestFrame());
552   MockWrite writes[] = {
553       CreateMockWrite(conn, 0, SYNCHRONOUS),
554   };
555 
556   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
557   MockRead reads[] = {
558       CreateMockRead(resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
559   };
560 
561   Initialize(reads, writes);
562   AddAuthToCache();
563 
564   AssertConnectSucceeds();
565 
566   AssertConnectionEstablished();
567 }
568 
TEST_P(SpdyProxyClientSocketTest,ConnectRedirects)569 TEST_P(SpdyProxyClientSocketTest, ConnectRedirects) {
570   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
571   spdy::SpdySerializedFrame rst(
572       spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
573   MockWrite writes[] = {
574       CreateMockWrite(conn, 0, SYNCHRONOUS),
575   };
576 
577   spdy::SpdySerializedFrame resp(ConstructConnectRedirectReplyFrame());
578   MockRead reads[] = {
579       CreateMockRead(resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
580   };
581 
582   Initialize(reads, writes);
583 
584   AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED);
585 
586   const HttpResponseInfo* response = sock_->GetConnectResponseInfo();
587   ASSERT_TRUE(response != nullptr);
588 
589   const HttpResponseHeaders* headers = response->headers.get();
590   ASSERT_EQ(302, headers->response_code());
591   ASSERT_TRUE(headers->HasHeader("set-cookie"));
592 
593   std::string location;
594   ASSERT_TRUE(headers->IsRedirect(&location));
595   ASSERT_EQ(location, kRedirectUrl);
596 
597   // Let the RST_STREAM write while |rst| is in-scope.
598   base::RunLoop().RunUntilIdle();
599 }
600 
TEST_P(SpdyProxyClientSocketTest,ConnectFails)601 TEST_P(SpdyProxyClientSocketTest, ConnectFails) {
602   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
603   MockWrite writes[] = {
604       CreateMockWrite(conn, 0, SYNCHRONOUS),
605   };
606 
607   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
608   MockRead reads[] = {
609     MockRead(ASYNC, 0, 1),  // EOF
610   };
611 
612   Initialize(reads, writes);
613 
614   ASSERT_FALSE(sock_->IsConnected());
615 
616   AssertConnectFails(ERR_CONNECTION_CLOSED);
617 
618   ASSERT_FALSE(sock_->IsConnected());
619 }
620 
TEST_P(SpdyProxyClientSocketTest,SetStreamPriority)621 TEST_P(SpdyProxyClientSocketTest, SetStreamPriority) {
622   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame(LOWEST));
623   MockWrite writes[] = {
624       CreateMockWrite(conn, 0, SYNCHRONOUS),
625   };
626 
627   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
628   MockRead reads[] = {
629       CreateMockRead(resp, 1, ASYNC),
630       MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
631   };
632 
633   Initialize(reads, writes);
634 
635   // Set the stream priority. Since a connection was already established, it's
636   // too late to adjust the HTTP2 stream's priority, and the request is ignored.
637   sock_->SetStreamPriority(HIGHEST);
638 
639   AssertConnectSucceeds();
640 }
641 
642 // ----------- WasEverUsed
643 
TEST_P(SpdyProxyClientSocketTest,WasEverUsedReturnsCorrectValues)644 TEST_P(SpdyProxyClientSocketTest, WasEverUsedReturnsCorrectValues) {
645   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
646   spdy::SpdySerializedFrame rst(
647       spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
648   MockWrite writes[] = {
649       CreateMockWrite(conn, 0, SYNCHRONOUS), CreateMockWrite(rst, 3),
650   };
651 
652   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
653   MockRead reads[] = {
654       CreateMockRead(resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
655   };
656 
657   Initialize(reads, writes);
658 
659   EXPECT_FALSE(sock_->WasEverUsed());
660   AssertConnectSucceeds();
661   EXPECT_TRUE(sock_->WasEverUsed());
662   sock_->Disconnect();
663   EXPECT_TRUE(sock_->WasEverUsed());
664 
665   // Let the RST_STREAM write while |rst| is in-scope.
666   base::RunLoop().RunUntilIdle();
667 }
668 
669 // ----------- GetPeerAddress
670 
TEST_P(SpdyProxyClientSocketTest,GetPeerAddressReturnsCorrectValues)671 TEST_P(SpdyProxyClientSocketTest, GetPeerAddressReturnsCorrectValues) {
672   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
673   MockWrite writes[] = {
674       CreateMockWrite(conn, 0, SYNCHRONOUS),
675   };
676 
677   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
678   MockRead reads[] = {
679       CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
680       MockRead(ASYNC, 0, 3),  // EOF
681   };
682 
683   Initialize(reads, writes);
684 
685   IPEndPoint addr;
686   EXPECT_THAT(sock_->GetPeerAddress(&addr), IsError(ERR_SOCKET_NOT_CONNECTED));
687 
688   AssertConnectSucceeds();
689   EXPECT_TRUE(sock_->IsConnected());
690   EXPECT_THAT(sock_->GetPeerAddress(&addr), IsOk());
691 
692   ResumeAndRun();
693 
694   EXPECT_FALSE(sock_->IsConnected());
695   EXPECT_THAT(sock_->GetPeerAddress(&addr), IsError(ERR_SOCKET_NOT_CONNECTED));
696 
697   sock_->Disconnect();
698 
699   EXPECT_THAT(sock_->GetPeerAddress(&addr), IsError(ERR_SOCKET_NOT_CONNECTED));
700 }
701 
702 // ----------- Write
703 
TEST_P(SpdyProxyClientSocketTest,WriteSendsDataInDataFrame)704 TEST_P(SpdyProxyClientSocketTest, WriteSendsDataInDataFrame) {
705   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
706   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
707   spdy::SpdySerializedFrame msg2(ConstructBodyFrame(kMsg2, kLen2));
708   MockWrite writes[] = {
709       CreateMockWrite(conn, 0, SYNCHRONOUS),
710       CreateMockWrite(msg1, 3, SYNCHRONOUS),
711       CreateMockWrite(msg2, 4, SYNCHRONOUS),
712   };
713 
714   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
715   MockRead reads[] = {
716       CreateMockRead(resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
717   };
718 
719   Initialize(reads, writes);
720 
721   AssertConnectSucceeds();
722 
723   AssertAsyncWriteSucceeds(kMsg1, kLen1);
724   AssertAsyncWriteSucceeds(kMsg2, kLen2);
725 }
726 
TEST_P(SpdyProxyClientSocketTest,WriteSplitsLargeDataIntoMultipleFrames)727 TEST_P(SpdyProxyClientSocketTest, WriteSplitsLargeDataIntoMultipleFrames) {
728   std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
729   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
730   spdy::SpdySerializedFrame chunk(
731       ConstructBodyFrame(chunk_data.data(), chunk_data.length()));
732   MockWrite writes[] = {CreateMockWrite(conn, 0, SYNCHRONOUS),
733                         CreateMockWrite(chunk, 3, SYNCHRONOUS),
734                         CreateMockWrite(chunk, 4, SYNCHRONOUS),
735                         CreateMockWrite(chunk, 5, SYNCHRONOUS)};
736 
737   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
738   MockRead reads[] = {
739       CreateMockRead(resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
740   };
741 
742   Initialize(reads, writes);
743 
744   AssertConnectSucceeds();
745 
746   std::string big_data(kMaxSpdyFrameChunkSize * 3, 'x');
747   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(big_data.data(),
748                                                    big_data.length()));
749 
750   EXPECT_EQ(ERR_IO_PENDING,
751             sock_->Write(buf.get(), buf->size(), write_callback_.callback(),
752                          TRAFFIC_ANNOTATION_FOR_TESTS));
753   EXPECT_EQ(buf->size(), write_callback_.WaitForResult());
754 }
755 
756 // ----------- Read
757 
TEST_P(SpdyProxyClientSocketTest,ReadReadsDataInDataFrame)758 TEST_P(SpdyProxyClientSocketTest, ReadReadsDataInDataFrame) {
759   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
760   MockWrite writes[] = {
761       CreateMockWrite(conn, 0, SYNCHRONOUS),
762   };
763 
764   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
765   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
766   MockRead reads[] = {
767       CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
768       CreateMockRead(msg1, 3, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4),
769   };
770 
771   Initialize(reads, writes);
772 
773   AssertConnectSucceeds();
774 
775   // SpdySession consumes the next read and sends it to sock_ to be buffered.
776   ResumeAndRun();
777   AssertSyncReadEquals(kMsg1, kLen1);
778 }
779 
TEST_P(SpdyProxyClientSocketTest,ReadDataFromBufferedFrames)780 TEST_P(SpdyProxyClientSocketTest, ReadDataFromBufferedFrames) {
781   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
782   MockWrite writes[] = {
783       CreateMockWrite(conn, 0, SYNCHRONOUS),
784   };
785 
786   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
787   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
788   spdy::SpdySerializedFrame msg2(ConstructBodyFrame(kMsg2, kLen2));
789   MockRead reads[] = {
790       CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
791       CreateMockRead(msg1, 3, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 4),
792       CreateMockRead(msg2, 5, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
793   };
794 
795   Initialize(reads, writes);
796 
797   AssertConnectSucceeds();
798 
799   // SpdySession consumes the next read and sends it to sock_ to be buffered.
800   ResumeAndRun();
801   AssertSyncReadEquals(kMsg1, kLen1);
802   // SpdySession consumes the next read and sends it to sock_ to be buffered.
803   ResumeAndRun();
804   AssertSyncReadEquals(kMsg2, kLen2);
805 }
806 
TEST_P(SpdyProxyClientSocketTest,ReadDataMultipleBufferedFrames)807 TEST_P(SpdyProxyClientSocketTest, ReadDataMultipleBufferedFrames) {
808   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
809   MockWrite writes[] = {
810       CreateMockWrite(conn, 0, SYNCHRONOUS),
811   };
812 
813   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
814   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
815   spdy::SpdySerializedFrame msg2(ConstructBodyFrame(kMsg2, kLen2));
816   MockRead reads[] = {
817       CreateMockRead(resp, 1, ASYNC),
818       MockRead(ASYNC, ERR_IO_PENDING, 2),
819       CreateMockRead(msg1, 3, ASYNC),
820       CreateMockRead(msg2, 4, ASYNC),
821       MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
822   };
823 
824   Initialize(reads, writes);
825 
826   AssertConnectSucceeds();
827 
828   // SpdySession consumes the next two reads and sends then to sock_ to be
829   // buffered.
830   ResumeAndRun();
831   AssertSyncReadEquals(kMsg1, kLen1);
832   AssertSyncReadEquals(kMsg2, kLen2);
833 }
834 
TEST_P(SpdyProxyClientSocketTest,LargeReadWillMergeDataFromDifferentFrames)835 TEST_P(SpdyProxyClientSocketTest, LargeReadWillMergeDataFromDifferentFrames) {
836   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
837   MockWrite writes[] = {
838       CreateMockWrite(conn, 0, SYNCHRONOUS),
839   };
840 
841   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
842   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
843   spdy::SpdySerializedFrame msg3(ConstructBodyFrame(kMsg3, kLen3));
844   MockRead reads[] = {
845       CreateMockRead(resp, 1, ASYNC),
846       MockRead(ASYNC, ERR_IO_PENDING, 2),
847       CreateMockRead(msg3, 3, ASYNC),
848       CreateMockRead(msg3, 4, ASYNC),
849       MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
850   };
851 
852   Initialize(reads, writes);
853 
854   AssertConnectSucceeds();
855 
856   // SpdySession consumes the next two reads and sends then to sock_ to be
857   // buffered.
858   ResumeAndRun();
859   // The payload from two data frames, each with kMsg3 will be combined
860   // together into a single read().
861   AssertSyncReadEquals(kMsg33, kLen33);
862 }
863 
TEST_P(SpdyProxyClientSocketTest,MultipleShortReadsThenMoreRead)864 TEST_P(SpdyProxyClientSocketTest, MultipleShortReadsThenMoreRead) {
865   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
866   MockWrite writes[] = {
867       CreateMockWrite(conn, 0, SYNCHRONOUS),
868   };
869 
870   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
871   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
872   spdy::SpdySerializedFrame msg3(ConstructBodyFrame(kMsg3, kLen3));
873   spdy::SpdySerializedFrame msg2(ConstructBodyFrame(kMsg2, kLen2));
874   MockRead reads[] = {
875       CreateMockRead(resp, 1, ASYNC),
876       MockRead(ASYNC, ERR_IO_PENDING, 2),
877       CreateMockRead(msg1, 3, ASYNC),
878       CreateMockRead(msg3, 4, ASYNC),
879       CreateMockRead(msg3, 5, ASYNC),
880       CreateMockRead(msg2, 6, ASYNC),
881       MockRead(SYNCHRONOUS, ERR_IO_PENDING, 7),
882   };
883 
884   Initialize(reads, writes);
885 
886   AssertConnectSucceeds();
887 
888   // SpdySession consumes the next four reads and sends then to sock_ to be
889   // buffered.
890   ResumeAndRun();
891   AssertSyncReadEquals(kMsg1, kLen1);
892   // The payload from two data frames, each with kMsg3 will be combined
893   // together into a single read().
894   AssertSyncReadEquals(kMsg33, kLen33);
895   AssertSyncReadEquals(kMsg2, kLen2);
896 }
897 
TEST_P(SpdyProxyClientSocketTest,ReadWillSplitDataFromLargeFrame)898 TEST_P(SpdyProxyClientSocketTest, ReadWillSplitDataFromLargeFrame) {
899   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
900   MockWrite writes[] = {
901       CreateMockWrite(conn, 0, SYNCHRONOUS),
902   };
903 
904   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
905   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
906   spdy::SpdySerializedFrame msg33(ConstructBodyFrame(kMsg33, kLen33));
907   spdy::SpdySerializedFrame msg2(ConstructBodyFrame(kMsg2, kLen2));
908   MockRead reads[] = {
909       CreateMockRead(resp, 1, ASYNC),
910       MockRead(ASYNC, ERR_IO_PENDING, 2),
911       CreateMockRead(msg1, 3, ASYNC),
912       CreateMockRead(msg33, 4, ASYNC),
913       MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
914   };
915 
916   Initialize(reads, writes);
917 
918   AssertConnectSucceeds();
919 
920   // SpdySession consumes the next two reads and sends then to sock_ to be
921   // buffered.
922   ResumeAndRun();
923   AssertSyncReadEquals(kMsg1, kLen1);
924   // The payload from the single large data frame will be read across
925   // two different reads.
926   AssertSyncReadEquals(kMsg3, kLen3);
927   AssertSyncReadEquals(kMsg3, kLen3);
928 }
929 
TEST_P(SpdyProxyClientSocketTest,MultipleReadsFromSameLargeFrame)930 TEST_P(SpdyProxyClientSocketTest, MultipleReadsFromSameLargeFrame) {
931   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
932   MockWrite writes[] = {
933       CreateMockWrite(conn, 0, SYNCHRONOUS),
934   };
935 
936   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
937   spdy::SpdySerializedFrame msg333(ConstructBodyFrame(kMsg333, kLen333));
938   MockRead reads[] = {
939       CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
940       CreateMockRead(msg333, 3, ASYNC),
941       MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4),
942   };
943 
944   Initialize(reads, writes);
945 
946   AssertConnectSucceeds();
947 
948   // SpdySession consumes the next read and sends it to sock_ to be buffered.
949   ResumeAndRun();
950   // The payload from the single large data frame will be read across
951   // two different reads.
952   AssertSyncReadEquals(kMsg33, kLen33);
953 
954   // Now attempt to do a read of more data than remains buffered
955   AssertSyncReadEquals(kMsg3, kLen3);
956 
957   ASSERT_TRUE(sock_->IsConnected());
958 }
959 
TEST_P(SpdyProxyClientSocketTest,ReadAuthResponseBody)960 TEST_P(SpdyProxyClientSocketTest, ReadAuthResponseBody) {
961   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
962   MockWrite writes[] = {
963       CreateMockWrite(conn, 0, SYNCHRONOUS),
964   };
965 
966   spdy::SpdySerializedFrame resp(ConstructConnectAuthReplyFrame());
967   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
968   spdy::SpdySerializedFrame msg2(ConstructBodyFrame(kMsg2, kLen2));
969   MockRead reads[] = {
970       CreateMockRead(resp, 1, ASYNC),
971       MockRead(ASYNC, ERR_IO_PENDING, 2),
972       CreateMockRead(msg1, 3, ASYNC),
973       CreateMockRead(msg2, 4, ASYNC),
974       MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
975   };
976 
977   Initialize(reads, writes);
978 
979   AssertConnectFails(ERR_PROXY_AUTH_REQUESTED);
980 
981   // SpdySession consumes the next two reads and sends then to sock_ to be
982   // buffered.
983   ResumeAndRun();
984   AssertSyncReadEquals(kMsg1, kLen1);
985   AssertSyncReadEquals(kMsg2, kLen2);
986 }
987 
TEST_P(SpdyProxyClientSocketTest,ReadErrorResponseBody)988 TEST_P(SpdyProxyClientSocketTest, ReadErrorResponseBody) {
989   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
990   MockWrite writes[] = {
991       CreateMockWrite(conn, 0, SYNCHRONOUS),
992   };
993 
994   spdy::SpdySerializedFrame resp(ConstructConnectErrorReplyFrame());
995   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
996   spdy::SpdySerializedFrame msg2(ConstructBodyFrame(kMsg2, kLen2));
997   MockRead reads[] = {
998       CreateMockRead(resp, 1, ASYNC), CreateMockRead(msg1, 2, SYNCHRONOUS),
999       CreateMockRead(msg2, 3, SYNCHRONOUS), MockRead(SYNCHRONOUS, 0, 4),  // EOF
1000   };
1001 
1002   Initialize(reads, writes);
1003 
1004   AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED);
1005 }
1006 
TEST_P(SpdyProxyClientSocketTest,SocketDestroyedWhenReadIsPending)1007 TEST_P(SpdyProxyClientSocketTest, SocketDestroyedWhenReadIsPending) {
1008   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1009   MockWrite writes[] = {CreateMockWrite(conn, 0, SYNCHRONOUS)};
1010 
1011   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1012   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
1013   MockRead reads[] = {
1014       CreateMockRead(resp, 1, ASYNC), CreateMockRead(msg1, 2, ASYNC),
1015       MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
1016   };
1017 
1018   Initialize(reads, writes);
1019 
1020   AssertConnectSucceeds();
1021 
1022   // Make Read()/ReadIfReady() pending.
1023   AssertReadStarts(kMsg1, kLen1);
1024 
1025   // Destroying socket.
1026   sock_ = nullptr;
1027 
1028   // Read data is not consumed.
1029   EXPECT_TRUE(data_->AllWriteDataConsumed());
1030   EXPECT_FALSE(data_->AllReadDataConsumed());
1031 
1032   // Reset |data_| so the test destructor doesn't check it.
1033   data_ = nullptr;
1034 }
1035 
1036 // ----------- Reads and Writes
1037 
TEST_P(SpdyProxyClientSocketTest,AsyncReadAroundWrite)1038 TEST_P(SpdyProxyClientSocketTest, AsyncReadAroundWrite) {
1039   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1040   spdy::SpdySerializedFrame msg2(ConstructBodyFrame(kMsg2, kLen2));
1041   MockWrite writes[] = {
1042       CreateMockWrite(conn, 0, SYNCHRONOUS),
1043       CreateMockWrite(msg2, 4, SYNCHRONOUS),
1044   };
1045 
1046   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1047   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
1048   spdy::SpdySerializedFrame msg3(ConstructBodyFrame(kMsg3, kLen3));
1049   MockRead reads[] = {
1050       CreateMockRead(resp, 1, ASYNC),
1051       MockRead(ASYNC, ERR_IO_PENDING, 2),
1052       CreateMockRead(msg1, 3, ASYNC),  // sync read
1053       MockRead(ASYNC, ERR_IO_PENDING, 5),
1054       CreateMockRead(msg3, 6, ASYNC),  // async read
1055       MockRead(SYNCHRONOUS, ERR_IO_PENDING, 7),
1056   };
1057 
1058   Initialize(reads, writes);
1059 
1060   AssertConnectSucceeds();
1061 
1062   ResumeAndRun();
1063   AssertSyncReadEquals(kMsg1, kLen1);
1064 
1065   AssertReadStarts(kMsg3, kLen3);
1066   // Read should block until after the write succeeds.
1067 
1068   AssertAsyncWriteSucceeds(kMsg2, kLen2);  // Advances past paused read.
1069 
1070   ASSERT_FALSE(read_callback_.have_result());
1071   ResumeAndRun();
1072   // Now the read will return.
1073   AssertReadReturns(kMsg3, kLen3);
1074 }
1075 
TEST_P(SpdyProxyClientSocketTest,AsyncWriteAroundReads)1076 TEST_P(SpdyProxyClientSocketTest, AsyncWriteAroundReads) {
1077   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1078   spdy::SpdySerializedFrame msg2(ConstructBodyFrame(kMsg2, kLen2));
1079   MockWrite writes[] = {
1080       CreateMockWrite(conn, 0, SYNCHRONOUS),
1081       MockWrite(ASYNC, ERR_IO_PENDING, 7), CreateMockWrite(msg2, 8, ASYNC),
1082   };
1083 
1084   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1085   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
1086   spdy::SpdySerializedFrame msg3(ConstructBodyFrame(kMsg3, kLen3));
1087   MockRead reads[] = {
1088       CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
1089       CreateMockRead(msg1, 3, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 4),
1090       CreateMockRead(msg3, 5, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
1091   };
1092 
1093   Initialize(reads, writes);
1094 
1095   AssertConnectSucceeds();
1096 
1097   ResumeAndRun();
1098   AssertSyncReadEquals(kMsg1, kLen1);
1099   // Write should block until the read completes
1100   AssertWriteReturns(kMsg2, kLen2, ERR_IO_PENDING);
1101 
1102   AssertAsyncReadEquals(kMsg3, kLen3);
1103 
1104   ASSERT_FALSE(write_callback_.have_result());
1105 
1106   // Now the write will complete
1107   ResumeAndRun();
1108   AssertWriteLength(kLen2);
1109 }
1110 
1111 // ----------- Reading/Writing on Closed socket
1112 
1113 // Reading from an already closed socket should return 0
TEST_P(SpdyProxyClientSocketTest,ReadOnClosedSocketReturnsZero)1114 TEST_P(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsZero) {
1115   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1116   MockWrite writes[] = {
1117       CreateMockWrite(conn, 0, SYNCHRONOUS),
1118   };
1119 
1120   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1121   MockRead reads[] = {
1122       CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
1123       MockRead(ASYNC, 0, 3),  // EOF
1124   };
1125 
1126   Initialize(reads, writes);
1127 
1128   AssertConnectSucceeds();
1129 
1130   ResumeAndRun();
1131 
1132   ASSERT_FALSE(sock_->IsConnected());
1133   AssertSyncReadEOF();
1134   AssertSyncReadEOF();
1135   AssertSyncReadEOF();
1136   ASSERT_FALSE(sock_->IsConnectedAndIdle());
1137 }
1138 
1139 // Read pending when socket is closed should return 0
TEST_P(SpdyProxyClientSocketTest,PendingReadOnCloseReturnsZero)1140 TEST_P(SpdyProxyClientSocketTest, PendingReadOnCloseReturnsZero) {
1141   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1142   MockWrite writes[] = {
1143       CreateMockWrite(conn, 0, SYNCHRONOUS),
1144   };
1145 
1146   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1147   MockRead reads[] = {
1148       CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
1149       MockRead(ASYNC, 0, 3),  // EOF
1150   };
1151 
1152   Initialize(reads, writes);
1153 
1154   AssertConnectSucceeds();
1155 
1156   AssertReadStarts(kMsg1, kLen1);
1157 
1158   ResumeAndRun();
1159 
1160   ASSERT_EQ(0, read_callback_.WaitForResult());
1161 }
1162 
1163 // Reading from a disconnected socket is an error
TEST_P(SpdyProxyClientSocketTest,ReadOnDisconnectSocketReturnsNotConnected)1164 TEST_P(SpdyProxyClientSocketTest, ReadOnDisconnectSocketReturnsNotConnected) {
1165   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1166   spdy::SpdySerializedFrame rst(
1167       spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
1168   MockWrite writes[] = {
1169       CreateMockWrite(conn, 0, SYNCHRONOUS), CreateMockWrite(rst, 3),
1170   };
1171 
1172   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1173   MockRead reads[] = {
1174       CreateMockRead(resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
1175   };
1176 
1177   Initialize(reads, writes);
1178 
1179   AssertConnectSucceeds();
1180 
1181   sock_->Disconnect();
1182 
1183   if (use_read_if_ready()) {
1184     ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED,
1185               sock_->ReadIfReady(nullptr, 1, CompletionOnceCallback()));
1186   } else {
1187     ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED,
1188               sock_->Read(nullptr, 1, CompletionOnceCallback()));
1189   }
1190 
1191   // Let the RST_STREAM write while |rst| is in-scope.
1192   base::RunLoop().RunUntilIdle();
1193 }
1194 
1195 // Reading buffered data from an already closed socket should return
1196 // buffered data, then 0.
TEST_P(SpdyProxyClientSocketTest,ReadOnClosedSocketReturnsBufferedData)1197 TEST_P(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsBufferedData) {
1198   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1199   MockWrite writes[] = {
1200       CreateMockWrite(conn, 0, SYNCHRONOUS),
1201   };
1202 
1203   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1204   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
1205   MockRead reads[] = {
1206       CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
1207       CreateMockRead(msg1, 3, ASYNC), MockRead(ASYNC, 0, 4),  // EOF
1208   };
1209 
1210   Initialize(reads, writes);
1211 
1212   AssertConnectSucceeds();
1213 
1214   ResumeAndRun();
1215 
1216   ASSERT_FALSE(sock_->IsConnected());
1217   auto buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
1218   ASSERT_EQ(kLen1, sock_->Read(buf.get(), kLen1, CompletionOnceCallback()));
1219   ASSERT_EQ(std::string(kMsg1, kLen1), std::string(buf->data(), kLen1));
1220 
1221   ASSERT_EQ(0, sock_->Read(nullptr, 1, CompletionOnceCallback()));
1222   ASSERT_EQ(0, sock_->Read(nullptr, 1, CompletionOnceCallback()));
1223   sock_->Disconnect();
1224   ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED,
1225             sock_->Read(nullptr, 1, CompletionOnceCallback()));
1226 }
1227 
1228 // Calling Write() on a closed socket is an error
TEST_P(SpdyProxyClientSocketTest,WriteOnClosedStream)1229 TEST_P(SpdyProxyClientSocketTest, WriteOnClosedStream) {
1230   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1231   MockWrite writes[] = {
1232       CreateMockWrite(conn, 0, SYNCHRONOUS),
1233   };
1234 
1235   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1236   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
1237   MockRead reads[] = {
1238       CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
1239       MockRead(ASYNC, 0, 3),  // EOF
1240   };
1241 
1242   Initialize(reads, writes);
1243 
1244   AssertConnectSucceeds();
1245 
1246   // Read EOF which will close the stream.
1247   ResumeAndRun();
1248   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1));
1249   EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED,
1250             sock_->Write(buf.get(), buf->size(), CompletionOnceCallback(),
1251                          TRAFFIC_ANNOTATION_FOR_TESTS));
1252 }
1253 
1254 // Calling Write() on a disconnected socket is an error.
TEST_P(SpdyProxyClientSocketTest,WriteOnDisconnectedSocket)1255 TEST_P(SpdyProxyClientSocketTest, WriteOnDisconnectedSocket) {
1256   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1257   spdy::SpdySerializedFrame rst(
1258       spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
1259   MockWrite writes[] = {
1260       CreateMockWrite(conn, 0, SYNCHRONOUS), CreateMockWrite(rst, 3),
1261   };
1262 
1263   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1264   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
1265   MockRead reads[] = {
1266       CreateMockRead(resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
1267   };
1268 
1269   Initialize(reads, writes);
1270 
1271   AssertConnectSucceeds();
1272 
1273   sock_->Disconnect();
1274 
1275   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1));
1276   EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED,
1277             sock_->Write(buf.get(), buf->size(), CompletionOnceCallback(),
1278                          TRAFFIC_ANNOTATION_FOR_TESTS));
1279 
1280   // Let the RST_STREAM write while |rst| is in-scope.
1281   base::RunLoop().RunUntilIdle();
1282 }
1283 
1284 // If the socket is closed with a pending Write(), the callback
1285 // should be called with ERR_CONNECTION_CLOSED.
TEST_P(SpdyProxyClientSocketTest,WritePendingOnClose)1286 TEST_P(SpdyProxyClientSocketTest, WritePendingOnClose) {
1287   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1288   MockWrite writes[] = {
1289       CreateMockWrite(conn, 0, SYNCHRONOUS),
1290       MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 3),
1291   };
1292 
1293   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1294   MockRead reads[] = {
1295       CreateMockRead(resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
1296   };
1297 
1298   Initialize(reads, writes);
1299 
1300   AssertConnectSucceeds();
1301 
1302   EXPECT_TRUE(sock_->IsConnected());
1303 
1304   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1));
1305   EXPECT_EQ(ERR_IO_PENDING,
1306             sock_->Write(buf.get(), buf->size(), write_callback_.callback(),
1307                          TRAFFIC_ANNOTATION_FOR_TESTS));
1308   // Make sure the write actually starts.
1309   base::RunLoop().RunUntilIdle();
1310 
1311   CloseSpdySession(ERR_ABORTED, std::string());
1312 
1313   EXPECT_THAT(write_callback_.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
1314 }
1315 
1316 // If the socket is Disconnected with a pending Write(), the callback
1317 // should not be called.
TEST_P(SpdyProxyClientSocketTest,DisconnectWithWritePending)1318 TEST_P(SpdyProxyClientSocketTest, DisconnectWithWritePending) {
1319   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1320   spdy::SpdySerializedFrame rst(
1321       spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
1322   MockWrite writes[] = {
1323       CreateMockWrite(conn, 0, SYNCHRONOUS), CreateMockWrite(rst, 3),
1324   };
1325 
1326   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1327   MockRead reads[] = {
1328       CreateMockRead(resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
1329   };
1330 
1331   Initialize(reads, writes);
1332 
1333   AssertConnectSucceeds();
1334 
1335   EXPECT_TRUE(sock_->IsConnected());
1336 
1337   scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1));
1338   EXPECT_EQ(ERR_IO_PENDING,
1339             sock_->Write(buf.get(), buf->size(), write_callback_.callback(),
1340                          TRAFFIC_ANNOTATION_FOR_TESTS));
1341 
1342   sock_->Disconnect();
1343 
1344   EXPECT_FALSE(sock_->IsConnected());
1345   EXPECT_FALSE(write_callback_.have_result());
1346 
1347   // Let the RST_STREAM write while |rst| is in-scope.
1348   base::RunLoop().RunUntilIdle();
1349 }
1350 
1351 // If the socket is Disconnected with a pending Read(), the callback
1352 // should not be called.
TEST_P(SpdyProxyClientSocketTest,DisconnectWithReadPending)1353 TEST_P(SpdyProxyClientSocketTest, DisconnectWithReadPending) {
1354   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1355   spdy::SpdySerializedFrame rst(
1356       spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
1357   MockWrite writes[] = {
1358       CreateMockWrite(conn, 0, SYNCHRONOUS), CreateMockWrite(rst, 3),
1359   };
1360 
1361   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1362   MockRead reads[] = {
1363       CreateMockRead(resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
1364   };
1365 
1366   Initialize(reads, writes);
1367 
1368   AssertConnectSucceeds();
1369 
1370   EXPECT_TRUE(sock_->IsConnected());
1371 
1372   auto buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
1373   ASSERT_EQ(ERR_IO_PENDING,
1374             sock_->Read(buf.get(), kLen1, read_callback_.callback()));
1375 
1376   sock_->Disconnect();
1377 
1378   EXPECT_FALSE(sock_->IsConnected());
1379   EXPECT_FALSE(read_callback_.have_result());
1380 
1381   // Let the RST_STREAM write while |rst| is in-scope.
1382   base::RunLoop().RunUntilIdle();
1383 }
1384 
1385 // If the socket is Reset when both a read and write are pending,
1386 // both should be called back.
TEST_P(SpdyProxyClientSocketTest,RstWithReadAndWritePending)1387 TEST_P(SpdyProxyClientSocketTest, RstWithReadAndWritePending) {
1388   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1389   MockWrite writes[] = {
1390       CreateMockWrite(conn, 0, SYNCHRONOUS),
1391   };
1392 
1393   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1394   spdy::SpdySerializedFrame rst(
1395       spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
1396   MockRead reads[] = {
1397       CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
1398       CreateMockRead(rst, 3, ASYNC), MockRead(ASYNC, 0, 4)  // EOF
1399   };
1400 
1401   Initialize(reads, writes);
1402 
1403   AssertConnectSucceeds();
1404 
1405   EXPECT_TRUE(sock_->IsConnected());
1406 
1407   auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
1408   ASSERT_EQ(ERR_IO_PENDING,
1409             sock_->Read(read_buf.get(), kLen1, read_callback_.callback()));
1410 
1411   scoped_refptr<IOBufferWithSize> write_buf(CreateBuffer(kMsg1, kLen1));
1412   EXPECT_EQ(ERR_IO_PENDING, sock_->Write(write_buf.get(), write_buf->size(),
1413                                          write_callback_.callback(),
1414                                          TRAFFIC_ANNOTATION_FOR_TESTS));
1415 
1416   ResumeAndRun();
1417 
1418   EXPECT_TRUE(sock_.get());
1419   EXPECT_TRUE(read_callback_.have_result());
1420   EXPECT_TRUE(write_callback_.have_result());
1421 
1422   // Let the RST_STREAM write while |rst| is in-scope.
1423   base::RunLoop().RunUntilIdle();
1424 }
1425 
1426 // Makes sure the proxy client socket's source gets the expected NetLog events
1427 // and only the expected NetLog events (No SpdySession events).
TEST_P(SpdyProxyClientSocketTest,NetLog)1428 TEST_P(SpdyProxyClientSocketTest, NetLog) {
1429   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1430   spdy::SpdySerializedFrame rst(
1431       spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
1432   MockWrite writes[] = {
1433       CreateMockWrite(conn, 0, SYNCHRONOUS), CreateMockWrite(rst, 5),
1434   };
1435 
1436   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1437   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
1438   MockRead reads[] = {
1439       CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
1440       CreateMockRead(msg1, 3, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4),
1441   };
1442 
1443   Initialize(reads, writes);
1444 
1445   AssertConnectSucceeds();
1446 
1447   // SpdySession consumes the next read and sends it to sock_ to be buffered.
1448   ResumeAndRun();
1449   AssertSyncReadEquals(kMsg1, kLen1);
1450 
1451   NetLogSource sock_source = sock_->NetLog().source();
1452   sock_.reset();
1453 
1454   auto entry_list = net_log_observer_.GetEntriesForSource(sock_source);
1455 
1456   ASSERT_EQ(entry_list.size(), 10u);
1457   EXPECT_TRUE(
1458       LogContainsBeginEvent(entry_list, 0, NetLogEventType::SOCKET_ALIVE));
1459   EXPECT_TRUE(LogContainsEvent(entry_list, 1,
1460                                NetLogEventType::HTTP2_PROXY_CLIENT_SESSION,
1461                                NetLogEventPhase::NONE));
1462   EXPECT_TRUE(LogContainsBeginEvent(
1463       entry_list, 2, NetLogEventType::HTTP_TRANSACTION_TUNNEL_SEND_REQUEST));
1464   EXPECT_TRUE(LogContainsEvent(
1465       entry_list, 3, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1466       NetLogEventPhase::NONE));
1467   EXPECT_TRUE(LogContainsEndEvent(
1468       entry_list, 4, NetLogEventType::HTTP_TRANSACTION_TUNNEL_SEND_REQUEST));
1469   EXPECT_TRUE(LogContainsBeginEvent(
1470       entry_list, 5, NetLogEventType::HTTP_TRANSACTION_TUNNEL_READ_HEADERS));
1471   EXPECT_TRUE(LogContainsEvent(
1472       entry_list, 6,
1473       NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1474       NetLogEventPhase::NONE));
1475   EXPECT_TRUE(LogContainsEndEvent(
1476       entry_list, 7, NetLogEventType::HTTP_TRANSACTION_TUNNEL_READ_HEADERS));
1477   EXPECT_TRUE(LogContainsEvent(entry_list, 8,
1478                                NetLogEventType::SOCKET_BYTES_RECEIVED,
1479                                NetLogEventPhase::NONE));
1480   EXPECT_TRUE(
1481       LogContainsEndEvent(entry_list, 9, NetLogEventType::SOCKET_ALIVE));
1482 
1483   // Let the RST_STREAM write while |rst| is in-scope.
1484   base::RunLoop().RunUntilIdle();
1485 }
1486 
1487 // A helper class that will delete |sock| when the callback is invoked.
1488 class DeleteSockCallback : public TestCompletionCallbackBase {
1489  public:
DeleteSockCallback(std::unique_ptr<SpdyProxyClientSocket> * sock)1490   explicit DeleteSockCallback(std::unique_ptr<SpdyProxyClientSocket>* sock)
1491       : sock_(sock) {}
1492 
1493   DeleteSockCallback(const DeleteSockCallback&) = delete;
1494   DeleteSockCallback& operator=(const DeleteSockCallback&) = delete;
1495 
1496   ~DeleteSockCallback() override = default;
1497 
callback()1498   CompletionOnceCallback callback() {
1499     return base::BindOnce(&DeleteSockCallback::OnComplete,
1500                           base::Unretained(this));
1501   }
1502 
1503  private:
OnComplete(int result)1504   void OnComplete(int result) {
1505     sock_->reset(nullptr);
1506     SetResult(result);
1507   }
1508 
1509   raw_ptr<std::unique_ptr<SpdyProxyClientSocket>> sock_;
1510 };
1511 
1512 // If the socket is Reset when both a read and write are pending, and the
1513 // read callback causes the socket to be deleted, the write callback should
1514 // not be called.
TEST_P(SpdyProxyClientSocketTest,RstWithReadAndWritePendingDelete)1515 TEST_P(SpdyProxyClientSocketTest, RstWithReadAndWritePendingDelete) {
1516   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1517   MockWrite writes[] = {
1518       CreateMockWrite(conn, 0, SYNCHRONOUS),
1519   };
1520 
1521   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1522   spdy::SpdySerializedFrame rst(
1523       spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
1524   MockRead reads[] = {
1525       CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
1526       CreateMockRead(rst, 3, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4),
1527   };
1528 
1529   Initialize(reads, writes);
1530 
1531   AssertConnectSucceeds();
1532 
1533   EXPECT_TRUE(sock_->IsConnected());
1534 
1535   DeleteSockCallback read_callback(&sock_);
1536 
1537   auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
1538   ASSERT_EQ(ERR_IO_PENDING,
1539             sock_->Read(read_buf.get(), kLen1, read_callback.callback()));
1540 
1541   scoped_refptr<IOBufferWithSize> write_buf(CreateBuffer(kMsg1, kLen1));
1542   EXPECT_EQ(ERR_IO_PENDING, sock_->Write(write_buf.get(), write_buf->size(),
1543                                          write_callback_.callback(),
1544                                          TRAFFIC_ANNOTATION_FOR_TESTS));
1545 
1546   ResumeAndRun();
1547 
1548   EXPECT_FALSE(sock_.get());
1549   EXPECT_TRUE(read_callback.have_result());
1550   EXPECT_FALSE(write_callback_.have_result());
1551 
1552   // Let the RST_STREAM write while |rst| is in-scope.
1553   base::RunLoop().RunUntilIdle();
1554 }
1555 
1556 // ----------- Canceling a ReadIfReady
TEST_P(SpdyProxyClientSocketTest,CancelReadIfReady)1557 TEST_P(SpdyProxyClientSocketTest, CancelReadIfReady) {
1558   // Not relevant if not ReadIfReady().
1559   if (!use_read_if_ready())
1560     return;
1561 
1562   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1563   MockWrite writes[] = {CreateMockWrite(conn, 0, SYNCHRONOUS)};
1564 
1565   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1566   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
1567   spdy::SpdySerializedFrame msg3(ConstructBodyFrame(kMsg3, kLen3));
1568   MockRead reads[] = {
1569       CreateMockRead(resp, 1, ASYNC), CreateMockRead(msg1, 2, ASYNC),
1570       CreateMockRead(msg3, 3, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4),
1571   };
1572 
1573   Initialize(reads, writes);
1574 
1575   AssertConnectSucceeds();
1576 
1577   AssertReadStarts(kMsg1, kLen1);
1578   EXPECT_EQ(OK, sock_->CancelReadIfReady());
1579 
1580   // Perform ReadIfReady again should succeed after cancelation.
1581   AssertReadStarts(kMsg1, kLen1);
1582   AssertReadReturns(kMsg1, kLen1);
1583   AssertReadStarts(kMsg3, kLen3);
1584   AssertReadReturns(kMsg3, kLen3);
1585 
1586   // Canceling ReadIfReady() when none is in progress is an no-op.
1587   EXPECT_EQ(OK, sock_->CancelReadIfReady());
1588 }
1589 
1590 // ----------- Handling END_STREAM from the peer
1591 
TEST_P(SpdyProxyClientSocketTest,HandleEndStreamAsEOF)1592 TEST_P(SpdyProxyClientSocketTest, HandleEndStreamAsEOF) {
1593   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1594   spdy::SpdySerializedFrame end_stream(
1595       ConstructBodyFrame(/*data=*/nullptr, /*length=*/0, /*fin=*/true));
1596   MockWrite writes[] = {
1597       CreateMockWrite(conn, 0, SYNCHRONOUS),
1598       CreateMockWrite(end_stream, 7, SYNCHRONOUS),
1599   };
1600 
1601   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1602   spdy::SpdySerializedFrame msg1(ConstructBodyFrame(kMsg1, kLen1));
1603   spdy::SpdySerializedFrame msg2(
1604       ConstructBodyFrame(kMsg2, kLen2, /*fin=*/true));
1605   MockRead reads[] = {
1606       CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
1607       CreateMockRead(msg1, 3, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 4),
1608       CreateMockRead(msg2, 5, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
1609   };
1610 
1611   Initialize(reads, writes);
1612 
1613   AssertConnectSucceeds();
1614 
1615   AssertAsyncReadEquals(kMsg1, kLen1);
1616   AssertAsyncReadEquals(kMsg2, kLen2, /*fin=*/true);
1617 }
1618 
TEST_P(SpdyProxyClientSocketTest,SendEndStreamAfterWrite)1619 TEST_P(SpdyProxyClientSocketTest, SendEndStreamAfterWrite) {
1620   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1621   spdy::SpdySerializedFrame write_msg(ConstructBodyFrame(kMsg1, kLen1));
1622   spdy::SpdySerializedFrame end_stream(
1623       ConstructBodyFrame(/*data=*/nullptr, /*length=*/0, /*fin=*/true));
1624   MockWrite writes[] = {
1625       CreateMockWrite(conn, 0, SYNCHRONOUS),
1626       CreateMockWrite(write_msg, 4, ASYNC),
1627       CreateMockWrite(end_stream, 6, ASYNC),
1628   };
1629 
1630   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1631   spdy::SpdySerializedFrame read_msg(
1632       ConstructBodyFrame(kMsg2, kLen2, /*fin=*/true));
1633   MockRead reads[] = {
1634       CreateMockRead(resp, 1, ASYNC),     MockRead(ASYNC, ERR_IO_PENDING, 2),
1635       CreateMockRead(read_msg, 3, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 5),
1636       MockRead(SYNCHRONOUS, 0, 7),
1637   };
1638 
1639   Initialize(reads, writes);
1640 
1641   AssertConnectSucceeds();
1642 
1643   AssertWriteReturns(kMsg1, kLen1, ERR_IO_PENDING);
1644   AssertAsyncReadEquals(kMsg2, kLen2, /*fin=*/false);
1645   ResumeAndRun();
1646   AssertWriteLength(kLen1);
1647   AssertSyncReadEOF();
1648 }
1649 
1650 // Regression test for https://crbug.com/1320256
TEST_P(SpdyProxyClientSocketTest,WriteAfterStreamEndSent)1651 TEST_P(SpdyProxyClientSocketTest, WriteAfterStreamEndSent) {
1652   spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame());
1653   MockWrite writes[] = {
1654       CreateMockWrite(conn, 0, SYNCHRONOUS),
1655       // The following mock write blocks SpdyStream::SendData() in
1656       // SpdyProxyClientSocket::MaybeSendEndStream().
1657       MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 5),
1658   };
1659 
1660   spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame());
1661   spdy::SpdySerializedFrame read_msg(
1662       ConstructBodyFrame(kMsg1, kLen1, /*fin=*/true));
1663   MockRead reads[] = {
1664       CreateMockRead(resp, 1, ASYNC),
1665       MockRead(ASYNC, ERR_IO_PENDING, 2),
1666       CreateMockRead(read_msg, 3, ASYNC),
1667       MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4),
1668   };
1669 
1670   Initialize(reads, writes);
1671 
1672   AssertConnectSucceeds();
1673 
1674   AssertAsyncReadEquals(kMsg1, kLen1);
1675   AssertWriteReturns(kMsg2, kLen2, ERR_CONNECTION_CLOSED);
1676 }
1677 
1678 }  // namespace net
1679