1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/spdy/spdy_proxy_client_socket.h"
8 #include "base/bind_helpers.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "net/base/address_list.h"
11 #include "net/base/test_completion_callback.h"
12 #include "net/base/winsock_init.h"
13 #include "net/dns/mock_host_resolver.h"
14 #include "net/http/http_response_headers.h"
15 #include "net/http/http_response_info.h"
16 #include "net/log/capturing_net_log.h"
17 #include "net/log/net_log.h"
18 #include "net/log/net_log_unittest.h"
19 #include "net/socket/client_socket_factory.h"
20 #include "net/socket/next_proto.h"
21 #include "net/socket/socket_test_util.h"
22 #include "net/socket/tcp_client_socket.h"
23 #include "net/spdy/buffered_spdy_framer.h"
24 #include "net/spdy/spdy_http_utils.h"
25 #include "net/spdy/spdy_protocol.h"
26 #include "net/spdy/spdy_session_pool.h"
27 #include "net/spdy/spdy_test_util_common.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "testing/platform_test.h"
31 //-----------------------------------------------------------------------------
35 static const char kRequestUrl
[] = "https://www.google.com/";
36 static const char kOriginHost
[] = "www.google.com";
37 static const int kOriginPort
= 443;
38 static const char kOriginHostPort
[] = "www.google.com:443";
39 static const char kProxyUrl
[] = "https://myproxy:6121/";
40 static const char kProxyHost
[] = "myproxy";
41 static const int kProxyPort
= 6121;
42 static const char kUserAgent
[] = "Mozilla/1.0";
44 static const int kStreamId
= 1;
46 static const char kMsg1
[] = "\0hello!\xff";
47 static const int kLen1
= 8;
48 static const char kMsg2
[] = "\0a2345678\0";
49 static const int kLen2
= 10;
50 static const char kMsg3
[] = "bye!";
51 static const int kLen3
= 4;
52 static const char kMsg33
[] = "bye!bye!";
53 static const int kLen33
= kLen3
+ kLen3
;
54 static const char kMsg333
[] = "bye!bye!bye!";
55 static const int kLen333
= kLen3
+ kLen3
+ kLen3
;
57 static const char kRedirectUrl
[] = "https://example.com/";
59 } // anonymous namespace
63 class SpdyProxyClientSocketTest
64 : public PlatformTest
,
65 public testing::WithParamInterface
<NextProto
> {
67 SpdyProxyClientSocketTest();
69 void TearDown() override
;
72 void Initialize(MockRead
* reads
, size_t reads_count
, MockWrite
* writes
,
74 void PopulateConnectRequestIR(SpdyHeaderBlock
* syn_ir
);
75 void PopulateConnectReplyIR(SpdyHeaderBlock
* block
, const char* status
);
76 SpdyFrame
* ConstructConnectRequestFrame();
77 SpdyFrame
* ConstructConnectAuthRequestFrame();
78 SpdyFrame
* ConstructConnectReplyFrame();
79 SpdyFrame
* ConstructConnectAuthReplyFrame();
80 SpdyFrame
* ConstructConnectRedirectReplyFrame();
81 SpdyFrame
* ConstructConnectErrorReplyFrame();
82 SpdyFrame
* ConstructBodyFrame(const char* data
, int length
);
83 scoped_refptr
<IOBufferWithSize
> CreateBuffer(const char* data
, int size
);
84 void AssertConnectSucceeds();
85 void AssertConnectFails(int result
);
86 void AssertConnectionEstablished();
87 void AssertSyncReadEquals(const char* data
, int len
);
88 void AssertAsyncReadEquals(const char* data
, int len
);
89 void AssertReadStarts(const char* data
, int len
);
90 void AssertReadReturns(const char* data
, int len
);
91 void AssertAsyncWriteSucceeds(const char* data
, int len
);
92 void AssertWriteReturns(const char* data
, int len
, int rv
);
93 void AssertWriteLength(int len
);
94 void AssertAsyncWriteWithReadsSucceeds(const char* data
, int len
,
97 void AddAuthToCache() {
98 const base::string16
kFoo(base::ASCIIToUTF16("foo"));
99 const base::string16
kBar(base::ASCIIToUTF16("bar"));
100 session_
->http_auth_cache()->Add(GURL(kProxyUrl
),
102 HttpAuth::AUTH_SCHEME_BASIC
,
103 "Basic realm=MyRealm1",
104 AuthCredentials(kFoo
, kBar
),
108 void Run(int steps
) {
109 data_
->StopAfter(steps
);
113 void CloseSpdySession(net::Error error
, const std::string
& description
) {
114 spdy_session_
->CloseSessionOnError(error
, description
);
117 SpdyTestUtil spdy_util_
;
118 scoped_ptr
<SpdyProxyClientSocket
> sock_
;
119 TestCompletionCallback read_callback_
;
120 TestCompletionCallback write_callback_
;
121 scoped_ptr
<DeterministicSocketData
> data_
;
122 CapturingBoundNetLog net_log_
;
125 scoped_refptr
<HttpNetworkSession
> session_
;
126 scoped_refptr
<IOBuffer
> read_buf_
;
127 SpdySessionDependencies session_deps_
;
128 MockConnect connect_data_
;
129 base::WeakPtr
<SpdySession
> spdy_session_
;
130 BufferedSpdyFramer framer_
;
132 std::string user_agent_
;
134 HostPortPair proxy_host_port_
;
135 HostPortPair endpoint_host_port_pair_
;
137 SpdySessionKey endpoint_spdy_session_key_
;
139 DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocketTest
);
142 INSTANTIATE_TEST_CASE_P(NextProto
,
143 SpdyProxyClientSocketTest
,
144 testing::Values(kProtoSPDY31
,
148 SpdyProxyClientSocketTest::SpdyProxyClientSocketTest()
149 : spdy_util_(GetParam()),
152 session_deps_(GetParam()),
153 connect_data_(SYNCHRONOUS
, OK
),
154 framer_(spdy_util_
.spdy_version(), false),
155 user_agent_(kUserAgent
),
157 proxy_host_port_(kProxyHost
, kProxyPort
),
158 endpoint_host_port_pair_(kOriginHost
, kOriginPort
),
159 proxy_(ProxyServer::SCHEME_HTTPS
, proxy_host_port_
),
160 endpoint_spdy_session_key_(endpoint_host_port_pair_
,
162 PRIVACY_MODE_DISABLED
) {
163 session_deps_
.net_log
= net_log_
.bound().net_log();
166 void SpdyProxyClientSocketTest::TearDown() {
167 if (session_
.get() != NULL
)
168 session_
->spdy_session_pool()->CloseAllSessions();
170 // Empty the current queue.
171 base::MessageLoop::current()->RunUntilIdle();
172 PlatformTest::TearDown();
175 void SpdyProxyClientSocketTest::Initialize(MockRead
* reads
,
178 size_t writes_count
) {
179 data_
.reset(new DeterministicSocketData(reads
, reads_count
,
180 writes
, writes_count
));
181 data_
->set_connect_data(connect_data_
);
184 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
186 session_deps_
.host_resolver
->set_synchronous_mode(true);
188 session_
= SpdySessionDependencies::SpdyCreateSessionDeterministic(
191 // Creates the SPDY session and stream.
193 CreateInsecureSpdySession(
194 session_
, endpoint_spdy_session_key_
, BoundNetLog());
195 base::WeakPtr
<SpdyStream
> spdy_stream(
196 CreateStreamSynchronously(
197 SPDY_BIDIRECTIONAL_STREAM
, spdy_session_
, url_
, LOWEST
,
199 ASSERT_TRUE(spdy_stream
.get() != NULL
);
201 // Create the SpdyProxyClientSocket.
202 sock_
.reset(new SpdyProxyClientSocket(
203 spdy_stream
, user_agent_
, endpoint_host_port_pair_
, proxy_host_port_
,
204 net_log_
.bound(), session_
->http_auth_cache(),
205 session_
->http_auth_handler_factory()));
208 scoped_refptr
<IOBufferWithSize
> SpdyProxyClientSocketTest::CreateBuffer(
209 const char* data
, int size
) {
210 scoped_refptr
<IOBufferWithSize
> buf(new IOBufferWithSize(size
));
211 memcpy(buf
->data(), data
, size
);
215 void SpdyProxyClientSocketTest::AssertConnectSucceeds() {
216 ASSERT_EQ(ERR_IO_PENDING
, sock_
->Connect(read_callback_
.callback()));
218 ASSERT_EQ(OK
, read_callback_
.WaitForResult());
221 void SpdyProxyClientSocketTest::AssertConnectFails(int result
) {
222 ASSERT_EQ(ERR_IO_PENDING
, sock_
->Connect(read_callback_
.callback()));
224 ASSERT_EQ(result
, read_callback_
.WaitForResult());
227 void SpdyProxyClientSocketTest::AssertConnectionEstablished() {
228 const HttpResponseInfo
* response
= sock_
->GetConnectResponseInfo();
229 ASSERT_TRUE(response
!= NULL
);
230 ASSERT_EQ(200, response
->headers
->response_code());
233 void SpdyProxyClientSocketTest::AssertSyncReadEquals(const char* data
,
235 scoped_refptr
<IOBuffer
> buf(new IOBuffer(len
));
236 ASSERT_EQ(len
, sock_
->Read(buf
.get(), len
, CompletionCallback()));
237 ASSERT_EQ(std::string(data
, len
), std::string(buf
->data(), len
));
238 ASSERT_TRUE(sock_
->IsConnected());
241 void SpdyProxyClientSocketTest::AssertAsyncReadEquals(const char* data
,
244 // Issue the read, which will be completed asynchronously
245 scoped_refptr
<IOBuffer
> buf(new IOBuffer(len
));
246 ASSERT_EQ(ERR_IO_PENDING
,
247 sock_
->Read(buf
.get(), len
, read_callback_
.callback()));
248 EXPECT_TRUE(sock_
->IsConnected());
251 EXPECT_TRUE(sock_
->IsConnected());
253 // Now the read will return
254 EXPECT_EQ(len
, read_callback_
.WaitForResult());
255 ASSERT_EQ(std::string(data
, len
), std::string(buf
->data(), len
));
258 void SpdyProxyClientSocketTest::AssertReadStarts(const char* data
,
261 // Issue the read, which will be completed asynchronously
262 read_buf_
= new IOBuffer(len
);
263 ASSERT_EQ(ERR_IO_PENDING
,
264 sock_
->Read(read_buf_
.get(), len
, read_callback_
.callback()));
265 EXPECT_TRUE(sock_
->IsConnected());
268 void SpdyProxyClientSocketTest::AssertReadReturns(const char* data
,
270 EXPECT_TRUE(sock_
->IsConnected());
272 // Now the read will return
273 EXPECT_EQ(len
, read_callback_
.WaitForResult());
274 ASSERT_EQ(std::string(data
, len
), std::string(read_buf_
->data(), len
));
277 void SpdyProxyClientSocketTest::AssertAsyncWriteSucceeds(const char* data
,
279 AssertWriteReturns(data
, len
, ERR_IO_PENDING
);
281 AssertWriteLength(len
);
284 void SpdyProxyClientSocketTest::AssertWriteReturns(const char* data
,
287 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(data
, len
));
289 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
292 void SpdyProxyClientSocketTest::AssertWriteLength(int len
) {
293 EXPECT_EQ(len
, write_callback_
.WaitForResult());
296 void SpdyProxyClientSocketTest::AssertAsyncWriteWithReadsSucceeds(
297 const char* data
, int len
, int num_reads
) {
298 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(data
, len
));
300 EXPECT_EQ(ERR_IO_PENDING
,
301 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
303 for (int i
= 0; i
< num_reads
; i
++) {
305 AssertSyncReadEquals(kMsg2
, kLen2
);
308 write_callback_
.WaitForResult();
311 void SpdyProxyClientSocketTest::PopulateConnectRequestIR(
312 SpdyHeaderBlock
* block
) {
313 (*block
)[spdy_util_
.GetMethodKey()] = "CONNECT";
314 (*block
)[spdy_util_
.GetPathKey()] = kOriginHostPort
;
315 (*block
)[spdy_util_
.GetHostKey()] = kOriginHost
;
316 (*block
)["user-agent"] = kUserAgent
;
317 spdy_util_
.MaybeAddVersionHeader(block
);
320 void SpdyProxyClientSocketTest::PopulateConnectReplyIR(SpdyHeaderBlock
* block
,
321 const char* status
) {
322 (*block
)[spdy_util_
.GetStatusKey()] = status
;
323 spdy_util_
.MaybeAddVersionHeader(block
);
326 // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
328 SpdyProxyClientSocketTest::ConstructConnectRequestFrame() {
329 SpdyHeaderBlock block
;
330 PopulateConnectRequestIR(&block
);
331 return spdy_util_
.ConstructSpdySyn(kStreamId
, block
, LOWEST
, false, false);
334 // Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes
335 // Proxy-Authorization headers.
336 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() {
337 SpdyHeaderBlock block
;
338 PopulateConnectRequestIR(&block
);
339 block
["proxy-authorization"] = "Basic Zm9vOmJhcg==";
340 return spdy_util_
.ConstructSpdySyn(kStreamId
, block
, LOWEST
, false, false);
343 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT.
344 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() {
345 SpdyHeaderBlock block
;
346 PopulateConnectReplyIR(&block
, "200");
347 SpdySynReplyIR
reply_ir(kStreamId
);
348 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
351 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT,
352 // including Proxy-Authenticate headers.
353 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() {
354 SpdyHeaderBlock block
;
355 PopulateConnectReplyIR(&block
, "407");
356 block
["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
357 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
360 // Constructs a SPDY SYN_REPLY frame with an HTTP 302 redirect.
361 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectRedirectReplyFrame() {
362 SpdyHeaderBlock block
;
363 PopulateConnectReplyIR(&block
, "302");
364 block
["location"] = kRedirectUrl
;
365 block
["set-cookie"] = "foo=bar";
366 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
369 // Constructs a SPDY SYN_REPLY frame with an HTTP 500 error.
370 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() {
371 SpdyHeaderBlock block
;
372 PopulateConnectReplyIR(&block
, "500");
373 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
376 SpdyFrame
* SpdyProxyClientSocketTest::ConstructBodyFrame(
379 return framer_
.CreateDataFrame(kStreamId
, data
, length
, DATA_FLAG_NONE
);
382 // ----------- Connect
384 TEST_P(SpdyProxyClientSocketTest
, ConnectSendsCorrectRequest
) {
385 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
386 MockWrite writes
[] = {
387 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
390 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
392 CreateMockRead(*resp
, 1, ASYNC
),
393 MockRead(ASYNC
, 0, 2), // EOF
396 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
398 ASSERT_FALSE(sock_
->IsConnected());
400 AssertConnectSucceeds();
402 AssertConnectionEstablished();
405 TEST_P(SpdyProxyClientSocketTest
, ConnectWithAuthRequested
) {
406 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
407 MockWrite writes
[] = {
408 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
411 scoped_ptr
<SpdyFrame
> resp(ConstructConnectAuthReplyFrame());
413 CreateMockRead(*resp
, 1, ASYNC
),
414 MockRead(ASYNC
, 0, 2), // EOF
417 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
419 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED
);
421 const HttpResponseInfo
* response
= sock_
->GetConnectResponseInfo();
422 ASSERT_TRUE(response
!= NULL
);
423 ASSERT_EQ(407, response
->headers
->response_code());
426 TEST_P(SpdyProxyClientSocketTest
, ConnectWithAuthCredentials
) {
427 scoped_ptr
<SpdyFrame
> conn(ConstructConnectAuthRequestFrame());
428 MockWrite writes
[] = {
429 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
432 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
434 CreateMockRead(*resp
, 1, ASYNC
),
435 MockRead(ASYNC
, 0, 2), // EOF
438 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
441 AssertConnectSucceeds();
443 AssertConnectionEstablished();
446 TEST_P(SpdyProxyClientSocketTest
, ConnectRedirects
) {
447 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
448 scoped_ptr
<SpdyFrame
> rst(
449 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
450 MockWrite writes
[] = {
451 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
454 scoped_ptr
<SpdyFrame
> resp(ConstructConnectRedirectReplyFrame());
456 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
459 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
461 AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE
);
463 const HttpResponseInfo
* response
= sock_
->GetConnectResponseInfo();
464 ASSERT_TRUE(response
!= NULL
);
466 const HttpResponseHeaders
* headers
= response
->headers
.get();
467 ASSERT_EQ(302, headers
->response_code());
468 ASSERT_FALSE(headers
->HasHeader("set-cookie"));
469 ASSERT_TRUE(headers
->HasHeaderValue("content-length", "0"));
471 std::string location
;
472 ASSERT_TRUE(headers
->IsRedirect(&location
));
473 ASSERT_EQ(location
, kRedirectUrl
);
475 // Let the RST_STREAM write while |rst| is in-scope.
476 base::MessageLoop::current()->RunUntilIdle();
479 TEST_P(SpdyProxyClientSocketTest
, ConnectFails
) {
480 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
481 MockWrite writes
[] = {
482 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
485 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
487 MockRead(ASYNC
, 0, 1), // EOF
490 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
492 ASSERT_FALSE(sock_
->IsConnected());
494 AssertConnectFails(ERR_CONNECTION_CLOSED
);
496 ASSERT_FALSE(sock_
->IsConnected());
499 // ----------- WasEverUsed
501 TEST_P(SpdyProxyClientSocketTest
, WasEverUsedReturnsCorrectValues
) {
502 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
503 scoped_ptr
<SpdyFrame
> rst(
504 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
505 MockWrite writes
[] = {
506 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
509 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
511 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
514 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
516 EXPECT_FALSE(sock_
->WasEverUsed());
517 AssertConnectSucceeds();
518 EXPECT_TRUE(sock_
->WasEverUsed());
520 EXPECT_TRUE(sock_
->WasEverUsed());
522 // Let the RST_STREAM write while |rst| is in-scope.
523 base::MessageLoop::current()->RunUntilIdle();
526 // ----------- GetPeerAddress
528 TEST_P(SpdyProxyClientSocketTest
, GetPeerAddressReturnsCorrectValues
) {
529 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
530 MockWrite writes
[] = {
531 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
534 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
536 CreateMockRead(*resp
, 1, ASYNC
),
537 MockRead(ASYNC
, 0, 2), // EOF
540 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
542 net::IPEndPoint addr
;
543 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
545 AssertConnectSucceeds();
546 EXPECT_TRUE(sock_
->IsConnected());
547 EXPECT_EQ(OK
, sock_
->GetPeerAddress(&addr
));
551 EXPECT_FALSE(sock_
->IsConnected());
552 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
556 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
561 TEST_P(SpdyProxyClientSocketTest
, WriteSendsDataInDataFrame
) {
562 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
563 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
564 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
565 MockWrite writes
[] = {
566 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
567 CreateMockWrite(*msg1
, 2, SYNCHRONOUS
),
568 CreateMockWrite(*msg2
, 3, SYNCHRONOUS
),
571 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
573 CreateMockRead(*resp
, 1, ASYNC
),
574 MockRead(ASYNC
, 0, 4), // EOF
577 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
579 AssertConnectSucceeds();
581 AssertAsyncWriteSucceeds(kMsg1
, kLen1
);
582 AssertAsyncWriteSucceeds(kMsg2
, kLen2
);
585 TEST_P(SpdyProxyClientSocketTest
, WriteSplitsLargeDataIntoMultipleFrames
) {
586 std::string
chunk_data(kMaxSpdyFrameChunkSize
, 'x');
587 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
588 scoped_ptr
<SpdyFrame
> chunk(ConstructBodyFrame(chunk_data
.data(),
589 chunk_data
.length()));
590 MockWrite writes
[] = {
591 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
592 CreateMockWrite(*chunk
, 2, SYNCHRONOUS
),
593 CreateMockWrite(*chunk
, 3, SYNCHRONOUS
),
594 CreateMockWrite(*chunk
, 4, SYNCHRONOUS
)
597 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
599 CreateMockRead(*resp
, 1, ASYNC
),
600 MockRead(ASYNC
, 0, 5), // EOF
603 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
605 AssertConnectSucceeds();
607 std::string
big_data(kMaxSpdyFrameChunkSize
* 3, 'x');
608 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(big_data
.data(),
611 EXPECT_EQ(ERR_IO_PENDING
,
612 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
615 EXPECT_EQ(buf
->size(), write_callback_
.WaitForResult());
620 TEST_P(SpdyProxyClientSocketTest
, ReadReadsDataInDataFrame
) {
621 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
622 MockWrite writes
[] = {
623 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
626 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
627 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
629 CreateMockRead(*resp
, 1, ASYNC
),
630 CreateMockRead(*msg1
, 2, ASYNC
),
631 MockRead(ASYNC
, 0, 3), // EOF
634 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
636 AssertConnectSucceeds();
638 Run(1); // SpdySession consumes the next read and sends it to
639 // sock_ to be buffered.
640 AssertSyncReadEquals(kMsg1
, kLen1
);
643 TEST_P(SpdyProxyClientSocketTest
, ReadDataFromBufferedFrames
) {
644 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
645 MockWrite writes
[] = {
646 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
649 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
650 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
651 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
653 CreateMockRead(*resp
, 1, ASYNC
),
654 CreateMockRead(*msg1
, 2, ASYNC
),
655 CreateMockRead(*msg2
, 3, ASYNC
),
656 MockRead(ASYNC
, 0, 4), // EOF
659 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
661 AssertConnectSucceeds();
663 Run(1); // SpdySession consumes the next read and sends it to
664 // sock_ to be buffered.
665 AssertSyncReadEquals(kMsg1
, kLen1
);
666 Run(1); // SpdySession consumes the next read and sends it to
667 // sock_ to be buffered.
668 AssertSyncReadEquals(kMsg2
, kLen2
);
671 TEST_P(SpdyProxyClientSocketTest
, ReadDataMultipleBufferedFrames
) {
672 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
673 MockWrite writes
[] = {
674 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
677 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
678 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
679 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
681 CreateMockRead(*resp
, 1, ASYNC
),
682 CreateMockRead(*msg1
, 2, ASYNC
),
683 CreateMockRead(*msg2
, 3, ASYNC
),
684 MockRead(ASYNC
, 0, 4), // EOF
687 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
689 AssertConnectSucceeds();
691 Run(2); // SpdySession consumes the next two reads and sends then to
692 // sock_ to be buffered.
693 AssertSyncReadEquals(kMsg1
, kLen1
);
694 AssertSyncReadEquals(kMsg2
, kLen2
);
697 TEST_P(SpdyProxyClientSocketTest
,
698 LargeReadWillMergeDataFromDifferentFrames
) {
699 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
700 MockWrite writes
[] = {
701 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
704 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
705 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
706 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
708 CreateMockRead(*resp
, 1, ASYNC
),
709 CreateMockRead(*msg3
, 2, ASYNC
),
710 CreateMockRead(*msg3
, 3, ASYNC
),
711 MockRead(ASYNC
, 0, 4), // EOF
714 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
716 AssertConnectSucceeds();
718 Run(2); // SpdySession consumes the next two reads and sends then to
719 // sock_ to be buffered.
720 // The payload from two data frames, each with kMsg3 will be combined
721 // together into a single read().
722 AssertSyncReadEquals(kMsg33
, kLen33
);
725 TEST_P(SpdyProxyClientSocketTest
, MultipleShortReadsThenMoreRead
) {
726 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
727 MockWrite writes
[] = {
728 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
731 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
732 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
733 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
734 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
736 CreateMockRead(*resp
, 1, ASYNC
),
737 CreateMockRead(*msg1
, 2, ASYNC
),
738 CreateMockRead(*msg3
, 3, ASYNC
),
739 CreateMockRead(*msg3
, 4, ASYNC
),
740 CreateMockRead(*msg2
, 5, ASYNC
),
741 MockRead(ASYNC
, 0, 6), // EOF
744 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
746 AssertConnectSucceeds();
748 Run(4); // SpdySession consumes the next four reads and sends then to
749 // sock_ to be buffered.
750 AssertSyncReadEquals(kMsg1
, kLen1
);
751 // The payload from two data frames, each with kMsg3 will be combined
752 // together into a single read().
753 AssertSyncReadEquals(kMsg33
, kLen33
);
754 AssertSyncReadEquals(kMsg2
, kLen2
);
757 TEST_P(SpdyProxyClientSocketTest
, ReadWillSplitDataFromLargeFrame
) {
758 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
759 MockWrite writes
[] = {
760 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
763 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
764 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
765 scoped_ptr
<SpdyFrame
> msg33(ConstructBodyFrame(kMsg33
, kLen33
));
766 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
768 CreateMockRead(*resp
, 1, ASYNC
),
769 CreateMockRead(*msg1
, 2, ASYNC
),
770 CreateMockRead(*msg33
, 3, ASYNC
),
771 MockRead(ASYNC
, 0, 4), // EOF
774 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
776 AssertConnectSucceeds();
778 Run(2); // SpdySession consumes the next two reads and sends then to
779 // sock_ to be buffered.
780 AssertSyncReadEquals(kMsg1
, kLen1
);
781 // The payload from the single large data frame will be read across
782 // two different reads.
783 AssertSyncReadEquals(kMsg3
, kLen3
);
784 AssertSyncReadEquals(kMsg3
, kLen3
);
787 TEST_P(SpdyProxyClientSocketTest
, MultipleReadsFromSameLargeFrame
) {
788 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
789 MockWrite writes
[] = {
790 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
793 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
794 scoped_ptr
<SpdyFrame
> msg333(ConstructBodyFrame(kMsg333
, kLen333
));
796 CreateMockRead(*resp
, 1, ASYNC
),
797 CreateMockRead(*msg333
, 2, ASYNC
),
798 MockRead(ASYNC
, 0, 3), // EOF
801 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
803 AssertConnectSucceeds();
805 Run(1); // SpdySession consumes the next read and sends it to
806 // sock_ to be buffered.
807 // The payload from the single large data frame will be read across
808 // two different reads.
809 AssertSyncReadEquals(kMsg33
, kLen33
);
811 // Now attempt to do a read of more data than remains buffered
812 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen33
));
813 ASSERT_EQ(kLen3
, sock_
->Read(buf
.get(), kLen33
, read_callback_
.callback()));
814 ASSERT_EQ(std::string(kMsg3
, kLen3
), std::string(buf
->data(), kLen3
));
815 ASSERT_TRUE(sock_
->IsConnected());
818 TEST_P(SpdyProxyClientSocketTest
, ReadAuthResponseBody
) {
819 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
820 MockWrite writes
[] = {
821 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
824 scoped_ptr
<SpdyFrame
> resp(ConstructConnectAuthReplyFrame());
825 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
826 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
828 CreateMockRead(*resp
, 1, ASYNC
),
829 CreateMockRead(*msg1
, 2, ASYNC
),
830 CreateMockRead(*msg2
, 3, ASYNC
),
831 MockRead(ASYNC
, 0, 4), // EOF
834 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
836 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED
);
838 Run(2); // SpdySession consumes the next two reads and sends then to
839 // sock_ to be buffered.
840 AssertSyncReadEquals(kMsg1
, kLen1
);
841 AssertSyncReadEquals(kMsg2
, kLen2
);
844 TEST_P(SpdyProxyClientSocketTest
, ReadErrorResponseBody
) {
845 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
846 MockWrite writes
[] = {
847 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
850 scoped_ptr
<SpdyFrame
> resp(ConstructConnectErrorReplyFrame());
851 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
852 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
854 CreateMockRead(*resp
, 1, ASYNC
),
855 CreateMockRead(*msg1
, 2, ASYNC
),
856 CreateMockRead(*msg2
, 3, ASYNC
),
857 MockRead(ASYNC
, 0, 4), // EOF
860 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
862 AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED
);
865 // ----------- Reads and Writes
867 TEST_P(SpdyProxyClientSocketTest
, AsyncReadAroundWrite
) {
868 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
869 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
870 MockWrite writes
[] = {
871 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
872 CreateMockWrite(*msg2
, 3, SYNCHRONOUS
),
875 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
876 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
877 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
879 CreateMockRead(*resp
, 1, ASYNC
),
880 CreateMockRead(*msg1
, 2, ASYNC
), // sync read
881 CreateMockRead(*msg3
, 4, ASYNC
), // async read
882 MockRead(ASYNC
, 0, 5), // EOF
885 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
887 AssertConnectSucceeds();
890 AssertSyncReadEquals(kMsg1
, kLen1
);
892 AssertReadStarts(kMsg3
, kLen3
);
893 // Read should block until after the write succeeds
895 AssertAsyncWriteSucceeds(kMsg2
, kLen2
); // Runs 1 step
897 ASSERT_FALSE(read_callback_
.have_result());
899 // Now the read will return
900 AssertReadReturns(kMsg3
, kLen3
);
903 TEST_P(SpdyProxyClientSocketTest
, AsyncWriteAroundReads
) {
904 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
905 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
906 MockWrite writes
[] = {
907 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
908 CreateMockWrite(*msg2
, 4, ASYNC
),
911 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
912 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
913 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
915 CreateMockRead(*resp
, 1, ASYNC
),
916 CreateMockRead(*msg1
, 2, ASYNC
),
917 CreateMockRead(*msg3
, 3, ASYNC
),
918 MockRead(ASYNC
, 0, 5), // EOF
921 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
923 AssertConnectSucceeds();
926 AssertSyncReadEquals(kMsg1
, kLen1
);
927 // Write should block until the read completes
928 AssertWriteReturns(kMsg2
, kLen2
, ERR_IO_PENDING
);
930 AssertAsyncReadEquals(kMsg3
, kLen3
);
932 ASSERT_FALSE(write_callback_
.have_result());
934 // Now the write will complete
936 AssertWriteLength(kLen2
);
939 // ----------- Reading/Writing on Closed socket
941 // Reading from an already closed socket should return 0
942 TEST_P(SpdyProxyClientSocketTest
, ReadOnClosedSocketReturnsZero
) {
943 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
944 MockWrite writes
[] = {
945 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
948 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
950 CreateMockRead(*resp
, 1, ASYNC
),
951 MockRead(ASYNC
, 0, 2), // EOF
954 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
956 AssertConnectSucceeds();
960 ASSERT_FALSE(sock_
->IsConnected());
961 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
962 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
963 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
964 ASSERT_FALSE(sock_
->IsConnectedAndIdle());
967 // Read pending when socket is closed should return 0
968 TEST_P(SpdyProxyClientSocketTest
, PendingReadOnCloseReturnsZero
) {
969 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
970 MockWrite writes
[] = {
971 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
974 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
976 CreateMockRead(*resp
, 1, ASYNC
),
977 MockRead(ASYNC
, 0, 2), // EOF
980 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
982 AssertConnectSucceeds();
984 AssertReadStarts(kMsg1
, kLen1
);
988 ASSERT_EQ(0, read_callback_
.WaitForResult());
991 // Reading from a disconnected socket is an error
992 TEST_P(SpdyProxyClientSocketTest
,
993 ReadOnDisconnectSocketReturnsNotConnected
) {
994 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
995 scoped_ptr
<SpdyFrame
> rst(
996 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
997 MockWrite writes
[] = {
998 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1001 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1002 MockRead reads
[] = {
1003 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1006 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1008 AssertConnectSucceeds();
1010 sock_
->Disconnect();
1012 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1013 sock_
->Read(NULL
, 1, CompletionCallback()));
1015 // Let the RST_STREAM write while |rst| is in-scope.
1016 base::MessageLoop::current()->RunUntilIdle();
1019 // Reading buffered data from an already closed socket should return
1020 // buffered data, then 0.
1021 TEST_P(SpdyProxyClientSocketTest
, ReadOnClosedSocketReturnsBufferedData
) {
1022 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1023 MockWrite writes
[] = {
1024 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1027 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1028 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1029 MockRead reads
[] = {
1030 CreateMockRead(*resp
, 1, ASYNC
),
1031 CreateMockRead(*msg1
, 2, ASYNC
),
1032 MockRead(ASYNC
, 0, 3), // EOF
1035 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1037 AssertConnectSucceeds();
1041 ASSERT_FALSE(sock_
->IsConnected());
1042 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen1
));
1043 ASSERT_EQ(kLen1
, sock_
->Read(buf
.get(), kLen1
, CompletionCallback()));
1044 ASSERT_EQ(std::string(kMsg1
, kLen1
), std::string(buf
->data(), kLen1
));
1046 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
1047 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
1048 sock_
->Disconnect();
1049 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1050 sock_
->Read(NULL
, 1, CompletionCallback()));
1053 // Calling Write() on a closed socket is an error
1054 TEST_P(SpdyProxyClientSocketTest
, WriteOnClosedStream
) {
1055 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1056 MockWrite writes
[] = {
1057 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1060 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1061 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1062 MockRead reads
[] = {
1063 CreateMockRead(*resp
, 1, ASYNC
),
1064 MockRead(ASYNC
, 0, 2), // EOF
1067 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1069 AssertConnectSucceeds();
1071 Run(1); // Read EOF which will close the stream
1072 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1073 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1074 sock_
->Write(buf
.get(), buf
->size(), CompletionCallback()));
1077 // Calling Write() on a disconnected socket is an error
1078 TEST_P(SpdyProxyClientSocketTest
, WriteOnDisconnectedSocket
) {
1079 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1080 scoped_ptr
<SpdyFrame
> rst(
1081 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1082 MockWrite writes
[] = {
1083 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1086 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1087 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1088 MockRead reads
[] = {
1089 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1092 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1094 AssertConnectSucceeds();
1096 sock_
->Disconnect();
1098 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1099 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1100 sock_
->Write(buf
.get(), buf
->size(), CompletionCallback()));
1102 // Let the RST_STREAM write while |rst| is in-scope.
1103 base::MessageLoop::current()->RunUntilIdle();
1106 // If the socket is closed with a pending Write(), the callback
1107 // should be called with ERR_CONNECTION_CLOSED.
1108 TEST_P(SpdyProxyClientSocketTest
, WritePendingOnClose
) {
1109 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1110 MockWrite writes
[] = {
1111 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1112 MockWrite(ASYNC
, ERR_ABORTED
, 2),
1115 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1116 MockRead reads
[] = {
1117 CreateMockRead(*resp
, 1, ASYNC
),
1118 MockRead(ASYNC
, 0, 3), // EOF
1121 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1123 AssertConnectSucceeds();
1125 EXPECT_TRUE(sock_
->IsConnected());
1127 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1128 EXPECT_EQ(ERR_IO_PENDING
,
1129 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
1131 CloseSpdySession(ERR_ABORTED
, std::string());
1133 EXPECT_EQ(ERR_CONNECTION_CLOSED
, write_callback_
.WaitForResult());
1136 // If the socket is Disconnected with a pending Write(), the callback
1137 // should not be called.
1138 TEST_P(SpdyProxyClientSocketTest
, DisconnectWithWritePending
) {
1139 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1140 scoped_ptr
<SpdyFrame
> rst(
1141 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1142 MockWrite writes
[] = {
1143 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1144 MockWrite(SYNCHRONOUS
, 0, 3), // EOF
1147 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1148 MockRead reads
[] = {
1149 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 4), // EOF
1152 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1154 AssertConnectSucceeds();
1156 EXPECT_TRUE(sock_
->IsConnected());
1158 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1159 EXPECT_EQ(ERR_IO_PENDING
,
1160 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
1162 sock_
->Disconnect();
1164 EXPECT_FALSE(sock_
->IsConnected());
1165 EXPECT_FALSE(write_callback_
.have_result());
1167 // Let the RST_STREAM write while |rst| is in-scope.
1168 base::MessageLoop::current()->RunUntilIdle();
1171 // If the socket is Disconnected with a pending Read(), the callback
1172 // should not be called.
1173 TEST_P(SpdyProxyClientSocketTest
, DisconnectWithReadPending
) {
1174 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1175 scoped_ptr
<SpdyFrame
> rst(
1176 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1177 MockWrite writes
[] = {
1178 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1181 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1182 MockRead reads
[] = {
1183 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1186 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1188 AssertConnectSucceeds();
1190 EXPECT_TRUE(sock_
->IsConnected());
1192 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen1
));
1193 ASSERT_EQ(ERR_IO_PENDING
,
1194 sock_
->Read(buf
.get(), kLen1
, read_callback_
.callback()));
1196 sock_
->Disconnect();
1198 EXPECT_FALSE(sock_
->IsConnected());
1199 EXPECT_FALSE(read_callback_
.have_result());
1201 // Let the RST_STREAM write while |rst| is in-scope.
1202 base::MessageLoop::current()->RunUntilIdle();
1205 // If the socket is Reset when both a read and write are pending,
1206 // both should be called back.
1207 TEST_P(SpdyProxyClientSocketTest
, RstWithReadAndWritePending
) {
1208 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1209 MockWrite writes
[] = {
1210 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1211 MockWrite(ASYNC
, ERR_ABORTED
, 3),
1214 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1215 scoped_ptr
<SpdyFrame
> rst(
1216 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1217 MockRead reads
[] = {
1218 CreateMockRead(*resp
, 1, ASYNC
),
1219 CreateMockRead(*rst
, 2, ASYNC
),
1220 MockRead(ASYNC
, 0, 4) // EOF
1223 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1225 AssertConnectSucceeds();
1227 EXPECT_TRUE(sock_
->IsConnected());
1229 scoped_refptr
<IOBuffer
> read_buf(new IOBuffer(kLen1
));
1230 ASSERT_EQ(ERR_IO_PENDING
,
1231 sock_
->Read(read_buf
.get(), kLen1
, read_callback_
.callback()));
1233 scoped_refptr
<IOBufferWithSize
> write_buf(CreateBuffer(kMsg1
, kLen1
));
1237 write_buf
.get(), write_buf
->size(), write_callback_
.callback()));
1241 EXPECT_TRUE(sock_
.get());
1242 EXPECT_TRUE(read_callback_
.have_result());
1243 EXPECT_TRUE(write_callback_
.have_result());
1245 // Let the RST_STREAM write while |rst| is in-scope.
1246 base::MessageLoop::current()->RunUntilIdle();
1249 // Makes sure the proxy client socket's source gets the expected NetLog events
1250 // and only the expected NetLog events (No SpdySession events).
1251 TEST_P(SpdyProxyClientSocketTest
, NetLog
) {
1252 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1253 scoped_ptr
<SpdyFrame
> rst(
1254 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1255 MockWrite writes
[] = {
1256 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 3),
1259 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1260 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1261 MockRead reads
[] = {
1262 CreateMockRead(*resp
, 1, ASYNC
), CreateMockRead(*msg1
, 2, ASYNC
),
1263 MockRead(ASYNC
, 0, 4), // EOF
1266 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1268 AssertConnectSucceeds();
1270 Run(1); // SpdySession consumes the next read and sends it to
1271 // sock_ to be buffered.
1272 AssertSyncReadEquals(kMsg1
, kLen1
);
1274 NetLog::Source sock_source
= sock_
->NetLog().source();
1277 CapturingNetLog::CapturedEntryList entry_list
;
1278 net_log_
.GetEntriesForSource(sock_source
, &entry_list
);
1280 ASSERT_EQ(entry_list
.size(), 10u);
1281 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 0, NetLog::TYPE_SOCKET_ALIVE
));
1282 EXPECT_TRUE(LogContainsEvent(entry_list
, 1,
1283 NetLog::TYPE_HTTP2_PROXY_CLIENT_SESSION
,
1284 NetLog::PHASE_NONE
));
1285 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 2,
1286 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST
));
1287 EXPECT_TRUE(LogContainsEvent(entry_list
, 3,
1288 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
1289 NetLog::PHASE_NONE
));
1290 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 4,
1291 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST
));
1292 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 5,
1293 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS
));
1294 EXPECT_TRUE(LogContainsEvent(entry_list
, 6,
1295 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
1296 NetLog::PHASE_NONE
));
1297 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 7,
1298 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS
));
1299 EXPECT_TRUE(LogContainsEvent(entry_list
, 8,
1300 NetLog::TYPE_SOCKET_BYTES_RECEIVED
,
1301 NetLog::PHASE_NONE
));
1302 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 9, NetLog::TYPE_SOCKET_ALIVE
));
1304 // Let the RST_STREAM write while |rst| is in-scope.
1305 base::MessageLoop::current()->RunUntilIdle();
1308 // CompletionCallback that causes the SpdyProxyClientSocket to be
1309 // deleted when Run is invoked.
1310 class DeleteSockCallback
: public TestCompletionCallbackBase
{
1312 explicit DeleteSockCallback(scoped_ptr
<SpdyProxyClientSocket
>* sock
)
1314 callback_(base::Bind(&DeleteSockCallback::OnComplete
,
1315 base::Unretained(this))) {
1318 ~DeleteSockCallback() override
{}
1320 const CompletionCallback
& callback() const { return callback_
; }
1323 void OnComplete(int result
) {
1328 scoped_ptr
<SpdyProxyClientSocket
>* sock_
;
1329 CompletionCallback callback_
;
1331 DISALLOW_COPY_AND_ASSIGN(DeleteSockCallback
);
1334 // If the socket is Reset when both a read and write are pending, and the
1335 // read callback causes the socket to be deleted, the write callback should
1337 TEST_P(SpdyProxyClientSocketTest
, RstWithReadAndWritePendingDelete
) {
1338 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1339 MockWrite writes
[] = {
1340 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1341 MockWrite(ASYNC
, ERR_ABORTED
, 3),
1344 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1345 scoped_ptr
<SpdyFrame
> rst(
1346 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1347 MockRead reads
[] = {
1348 CreateMockRead(*resp
, 1, ASYNC
),
1349 CreateMockRead(*rst
, 2, ASYNC
),
1350 MockRead(ASYNC
, 0, 4), // EOF
1353 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1355 AssertConnectSucceeds();
1357 EXPECT_TRUE(sock_
->IsConnected());
1359 DeleteSockCallback
read_callback(&sock_
);
1361 scoped_refptr
<IOBuffer
> read_buf(new IOBuffer(kLen1
));
1362 ASSERT_EQ(ERR_IO_PENDING
,
1363 sock_
->Read(read_buf
.get(), kLen1
, read_callback
.callback()));
1365 scoped_refptr
<IOBufferWithSize
> write_buf(CreateBuffer(kMsg1
, kLen1
));
1369 write_buf
.get(), write_buf
->size(), write_callback_
.callback()));
1373 EXPECT_FALSE(sock_
.get());
1374 EXPECT_TRUE(read_callback
.have_result());
1375 EXPECT_FALSE(write_callback_
.have_result());
1377 // Let the RST_STREAM write while |rst| is in-scope.
1378 base::MessageLoop::current()->RunUntilIdle();