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