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