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