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