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