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/capturing_net_log.h"
12 #include "net/base/net_log.h"
13 #include "net/base/net_log_unittest.h"
14 #include "net/base/test_completion_callback.h"
15 #include "net/base/winsock_init.h"
16 #include "net/dns/mock_host_resolver.h"
17 #include "net/http/http_response_headers.h"
18 #include "net/http/http_response_info.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(
144 SpdyProxyClientSocketTest
,
145 testing::Values(kProtoSPDY31
, kProtoSPDY4_14
, kProtoSPDY4_15
));
147 SpdyProxyClientSocketTest::SpdyProxyClientSocketTest()
148 : spdy_util_(GetParam()),
151 session_deps_(GetParam()),
152 connect_data_(SYNCHRONOUS
, OK
),
153 framer_(spdy_util_
.spdy_version(), false),
154 user_agent_(kUserAgent
),
156 proxy_host_port_(kProxyHost
, kProxyPort
),
157 endpoint_host_port_pair_(kOriginHost
, kOriginPort
),
158 proxy_(ProxyServer::SCHEME_HTTPS
, proxy_host_port_
),
159 endpoint_spdy_session_key_(endpoint_host_port_pair_
,
161 PRIVACY_MODE_DISABLED
) {
162 session_deps_
.net_log
= net_log_
.bound().net_log();
165 void SpdyProxyClientSocketTest::TearDown() {
166 if (session_
.get() != NULL
)
167 session_
->spdy_session_pool()->CloseAllSessions();
169 // Empty the current queue.
170 base::MessageLoop::current()->RunUntilIdle();
171 PlatformTest::TearDown();
174 void SpdyProxyClientSocketTest::Initialize(MockRead
* reads
,
177 size_t writes_count
) {
178 data_
.reset(new DeterministicSocketData(reads
, reads_count
,
179 writes
, writes_count
));
180 data_
->set_connect_data(connect_data_
);
183 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
185 session_deps_
.host_resolver
->set_synchronous_mode(true);
187 session_
= SpdySessionDependencies::SpdyCreateSessionDeterministic(
190 // Creates the SPDY session and stream.
192 CreateInsecureSpdySession(
193 session_
, endpoint_spdy_session_key_
, BoundNetLog());
194 base::WeakPtr
<SpdyStream
> spdy_stream(
195 CreateStreamSynchronously(
196 SPDY_BIDIRECTIONAL_STREAM
, spdy_session_
, url_
, LOWEST
,
198 ASSERT_TRUE(spdy_stream
.get() != NULL
);
200 // Create the SpdyProxyClientSocket.
202 new SpdyProxyClientSocket(spdy_stream
, user_agent_
,
203 endpoint_host_port_pair_
, url_
,
204 proxy_host_port_
, net_log_
.bound(),
205 session_
->http_auth_cache(),
206 session_
->http_auth_handler_factory()));
209 scoped_refptr
<IOBufferWithSize
> SpdyProxyClientSocketTest::CreateBuffer(
210 const char* data
, int size
) {
211 scoped_refptr
<IOBufferWithSize
> buf(new IOBufferWithSize(size
));
212 memcpy(buf
->data(), data
, size
);
216 void SpdyProxyClientSocketTest::AssertConnectSucceeds() {
217 ASSERT_EQ(ERR_IO_PENDING
, sock_
->Connect(read_callback_
.callback()));
219 ASSERT_EQ(OK
, read_callback_
.WaitForResult());
222 void SpdyProxyClientSocketTest::AssertConnectFails(int result
) {
223 ASSERT_EQ(ERR_IO_PENDING
, sock_
->Connect(read_callback_
.callback()));
225 ASSERT_EQ(result
, read_callback_
.WaitForResult());
228 void SpdyProxyClientSocketTest::AssertConnectionEstablished() {
229 const HttpResponseInfo
* response
= sock_
->GetConnectResponseInfo();
230 ASSERT_TRUE(response
!= NULL
);
231 ASSERT_EQ(200, response
->headers
->response_code());
234 void SpdyProxyClientSocketTest::AssertSyncReadEquals(const char* data
,
236 scoped_refptr
<IOBuffer
> buf(new IOBuffer(len
));
237 ASSERT_EQ(len
, sock_
->Read(buf
.get(), len
, CompletionCallback()));
238 ASSERT_EQ(std::string(data
, len
), std::string(buf
->data(), len
));
239 ASSERT_TRUE(sock_
->IsConnected());
242 void SpdyProxyClientSocketTest::AssertAsyncReadEquals(const char* data
,
245 // Issue the read, which will be completed asynchronously
246 scoped_refptr
<IOBuffer
> buf(new IOBuffer(len
));
247 ASSERT_EQ(ERR_IO_PENDING
,
248 sock_
->Read(buf
.get(), len
, read_callback_
.callback()));
249 EXPECT_TRUE(sock_
->IsConnected());
252 EXPECT_TRUE(sock_
->IsConnected());
254 // Now the read will return
255 EXPECT_EQ(len
, read_callback_
.WaitForResult());
256 ASSERT_EQ(std::string(data
, len
), std::string(buf
->data(), len
));
259 void SpdyProxyClientSocketTest::AssertReadStarts(const char* data
,
262 // Issue the read, which will be completed asynchronously
263 read_buf_
= new IOBuffer(len
);
264 ASSERT_EQ(ERR_IO_PENDING
,
265 sock_
->Read(read_buf_
.get(), len
, read_callback_
.callback()));
266 EXPECT_TRUE(sock_
->IsConnected());
269 void SpdyProxyClientSocketTest::AssertReadReturns(const char* data
,
271 EXPECT_TRUE(sock_
->IsConnected());
273 // Now the read will return
274 EXPECT_EQ(len
, read_callback_
.WaitForResult());
275 ASSERT_EQ(std::string(data
, len
), std::string(read_buf_
->data(), len
));
278 void SpdyProxyClientSocketTest::AssertAsyncWriteSucceeds(const char* data
,
280 AssertWriteReturns(data
, len
, ERR_IO_PENDING
);
282 AssertWriteLength(len
);
285 void SpdyProxyClientSocketTest::AssertWriteReturns(const char* data
,
288 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(data
, len
));
290 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
293 void SpdyProxyClientSocketTest::AssertWriteLength(int len
) {
294 EXPECT_EQ(len
, write_callback_
.WaitForResult());
297 void SpdyProxyClientSocketTest::AssertAsyncWriteWithReadsSucceeds(
298 const char* data
, int len
, int num_reads
) {
299 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(data
, len
));
301 EXPECT_EQ(ERR_IO_PENDING
,
302 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
304 for (int i
= 0; i
< num_reads
; i
++) {
306 AssertSyncReadEquals(kMsg2
, kLen2
);
309 write_callback_
.WaitForResult();
312 void SpdyProxyClientSocketTest::PopulateConnectRequestIR(
313 SpdyHeaderBlock
* block
) {
314 (*block
)[spdy_util_
.GetMethodKey()] = "CONNECT";
315 (*block
)[spdy_util_
.GetPathKey()] = kOriginHostPort
;
316 (*block
)[spdy_util_
.GetHostKey()] = kOriginHost
;
317 (*block
)["user-agent"] = kUserAgent
;
318 spdy_util_
.MaybeAddVersionHeader(block
);
321 void SpdyProxyClientSocketTest::PopulateConnectReplyIR(SpdyHeaderBlock
* block
,
322 const char* status
) {
323 (*block
)[spdy_util_
.GetStatusKey()] = status
;
324 spdy_util_
.MaybeAddVersionHeader(block
);
327 // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
329 SpdyProxyClientSocketTest::ConstructConnectRequestFrame() {
330 SpdyHeaderBlock block
;
331 PopulateConnectRequestIR(&block
);
332 return spdy_util_
.ConstructSpdySyn(kStreamId
, block
, LOWEST
, false, false);
335 // Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes
336 // Proxy-Authorization headers.
337 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() {
338 SpdyHeaderBlock block
;
339 PopulateConnectRequestIR(&block
);
340 block
["proxy-authorization"] = "Basic Zm9vOmJhcg==";
341 return spdy_util_
.ConstructSpdySyn(kStreamId
, block
, LOWEST
, false, false);
344 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT.
345 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() {
346 SpdyHeaderBlock block
;
347 PopulateConnectReplyIR(&block
, "200");
348 SpdySynReplyIR
reply_ir(kStreamId
);
349 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
352 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT,
353 // including Proxy-Authenticate headers.
354 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() {
355 SpdyHeaderBlock block
;
356 PopulateConnectReplyIR(&block
, "407");
357 block
["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
358 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
361 // Constructs a SPDY SYN_REPLY frame with an HTTP 302 redirect.
362 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectRedirectReplyFrame() {
363 SpdyHeaderBlock block
;
364 PopulateConnectReplyIR(&block
, "302");
365 block
["location"] = kRedirectUrl
;
366 block
["set-cookie"] = "foo=bar";
367 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
370 // Constructs a SPDY SYN_REPLY frame with an HTTP 500 error.
371 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() {
372 SpdyHeaderBlock block
;
373 PopulateConnectReplyIR(&block
, "500");
374 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
377 SpdyFrame
* SpdyProxyClientSocketTest::ConstructBodyFrame(
380 return framer_
.CreateDataFrame(kStreamId
, data
, length
, DATA_FLAG_NONE
);
383 // ----------- Connect
385 TEST_P(SpdyProxyClientSocketTest
, ConnectSendsCorrectRequest
) {
386 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
387 MockWrite writes
[] = {
388 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
391 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
393 CreateMockRead(*resp
, 1, ASYNC
),
394 MockRead(ASYNC
, 0, 2), // EOF
397 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
399 ASSERT_FALSE(sock_
->IsConnected());
401 AssertConnectSucceeds();
403 AssertConnectionEstablished();
406 TEST_P(SpdyProxyClientSocketTest
, ConnectWithAuthRequested
) {
407 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
408 MockWrite writes
[] = {
409 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
412 scoped_ptr
<SpdyFrame
> resp(ConstructConnectAuthReplyFrame());
414 CreateMockRead(*resp
, 1, ASYNC
),
415 MockRead(ASYNC
, 0, 2), // EOF
418 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
420 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED
);
422 const HttpResponseInfo
* response
= sock_
->GetConnectResponseInfo();
423 ASSERT_TRUE(response
!= NULL
);
424 ASSERT_EQ(407, response
->headers
->response_code());
427 TEST_P(SpdyProxyClientSocketTest
, ConnectWithAuthCredentials
) {
428 scoped_ptr
<SpdyFrame
> conn(ConstructConnectAuthRequestFrame());
429 MockWrite writes
[] = {
430 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
433 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
435 CreateMockRead(*resp
, 1, ASYNC
),
436 MockRead(ASYNC
, 0, 2), // EOF
439 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
442 AssertConnectSucceeds();
444 AssertConnectionEstablished();
447 TEST_P(SpdyProxyClientSocketTest
, ConnectRedirects
) {
448 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
449 scoped_ptr
<SpdyFrame
> rst(
450 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
451 MockWrite writes
[] = {
452 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
455 scoped_ptr
<SpdyFrame
> resp(ConstructConnectRedirectReplyFrame());
457 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
460 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
462 AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE
);
464 const HttpResponseInfo
* response
= sock_
->GetConnectResponseInfo();
465 ASSERT_TRUE(response
!= NULL
);
467 const HttpResponseHeaders
* headers
= response
->headers
.get();
468 ASSERT_EQ(302, headers
->response_code());
469 ASSERT_FALSE(headers
->HasHeader("set-cookie"));
470 ASSERT_TRUE(headers
->HasHeaderValue("content-length", "0"));
472 std::string location
;
473 ASSERT_TRUE(headers
->IsRedirect(&location
));
474 ASSERT_EQ(location
, kRedirectUrl
);
476 // Let the RST_STREAM write while |rst| is in-scope.
477 base::MessageLoop::current()->RunUntilIdle();
480 TEST_P(SpdyProxyClientSocketTest
, ConnectFails
) {
481 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
482 MockWrite writes
[] = {
483 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
486 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
488 MockRead(ASYNC
, 0, 1), // EOF
491 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
493 ASSERT_FALSE(sock_
->IsConnected());
495 AssertConnectFails(ERR_CONNECTION_CLOSED
);
497 ASSERT_FALSE(sock_
->IsConnected());
500 // ----------- WasEverUsed
502 TEST_P(SpdyProxyClientSocketTest
, WasEverUsedReturnsCorrectValues
) {
503 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
504 scoped_ptr
<SpdyFrame
> rst(
505 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
506 MockWrite writes
[] = {
507 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
510 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
512 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
515 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
517 EXPECT_FALSE(sock_
->WasEverUsed());
518 AssertConnectSucceeds();
519 EXPECT_TRUE(sock_
->WasEverUsed());
521 EXPECT_TRUE(sock_
->WasEverUsed());
523 // Let the RST_STREAM write while |rst| is in-scope.
524 base::MessageLoop::current()->RunUntilIdle();
527 // ----------- GetPeerAddress
529 TEST_P(SpdyProxyClientSocketTest
, GetPeerAddressReturnsCorrectValues
) {
530 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
531 MockWrite writes
[] = {
532 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
535 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
537 CreateMockRead(*resp
, 1, ASYNC
),
538 MockRead(ASYNC
, 0, 2), // EOF
541 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
543 net::IPEndPoint addr
;
544 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
546 AssertConnectSucceeds();
547 EXPECT_TRUE(sock_
->IsConnected());
548 EXPECT_EQ(OK
, sock_
->GetPeerAddress(&addr
));
552 EXPECT_FALSE(sock_
->IsConnected());
553 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
557 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
562 TEST_P(SpdyProxyClientSocketTest
, WriteSendsDataInDataFrame
) {
563 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
564 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
565 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
566 MockWrite writes
[] = {
567 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
568 CreateMockWrite(*msg1
, 2, SYNCHRONOUS
),
569 CreateMockWrite(*msg2
, 3, SYNCHRONOUS
),
572 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
574 CreateMockRead(*resp
, 1, ASYNC
),
575 MockRead(ASYNC
, 0, 4), // EOF
578 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
580 AssertConnectSucceeds();
582 AssertAsyncWriteSucceeds(kMsg1
, kLen1
);
583 AssertAsyncWriteSucceeds(kMsg2
, kLen2
);
586 TEST_P(SpdyProxyClientSocketTest
, WriteSplitsLargeDataIntoMultipleFrames
) {
587 std::string
chunk_data(kMaxSpdyFrameChunkSize
, 'x');
588 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
589 scoped_ptr
<SpdyFrame
> chunk(ConstructBodyFrame(chunk_data
.data(),
590 chunk_data
.length()));
591 MockWrite writes
[] = {
592 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
593 CreateMockWrite(*chunk
, 2, SYNCHRONOUS
),
594 CreateMockWrite(*chunk
, 3, SYNCHRONOUS
),
595 CreateMockWrite(*chunk
, 4, SYNCHRONOUS
)
598 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
600 CreateMockRead(*resp
, 1, ASYNC
),
601 MockRead(ASYNC
, 0, 5), // EOF
604 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
606 AssertConnectSucceeds();
608 std::string
big_data(kMaxSpdyFrameChunkSize
* 3, 'x');
609 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(big_data
.data(),
612 EXPECT_EQ(ERR_IO_PENDING
,
613 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
616 EXPECT_EQ(buf
->size(), write_callback_
.WaitForResult());
621 TEST_P(SpdyProxyClientSocketTest
, ReadReadsDataInDataFrame
) {
622 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
623 MockWrite writes
[] = {
624 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
627 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
628 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
630 CreateMockRead(*resp
, 1, ASYNC
),
631 CreateMockRead(*msg1
, 2, ASYNC
),
632 MockRead(ASYNC
, 0, 3), // EOF
635 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
637 AssertConnectSucceeds();
639 Run(1); // SpdySession consumes the next read and sends it to
640 // sock_ to be buffered.
641 AssertSyncReadEquals(kMsg1
, kLen1
);
644 TEST_P(SpdyProxyClientSocketTest
, ReadDataFromBufferedFrames
) {
645 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
646 MockWrite writes
[] = {
647 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
650 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
651 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
652 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
654 CreateMockRead(*resp
, 1, ASYNC
),
655 CreateMockRead(*msg1
, 2, ASYNC
),
656 CreateMockRead(*msg2
, 3, ASYNC
),
657 MockRead(ASYNC
, 0, 4), // EOF
660 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
662 AssertConnectSucceeds();
664 Run(1); // SpdySession consumes the next read and sends it to
665 // sock_ to be buffered.
666 AssertSyncReadEquals(kMsg1
, kLen1
);
667 Run(1); // SpdySession consumes the next read and sends it to
668 // sock_ to be buffered.
669 AssertSyncReadEquals(kMsg2
, kLen2
);
672 TEST_P(SpdyProxyClientSocketTest
, ReadDataMultipleBufferedFrames
) {
673 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
674 MockWrite writes
[] = {
675 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
678 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
679 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
680 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
682 CreateMockRead(*resp
, 1, ASYNC
),
683 CreateMockRead(*msg1
, 2, ASYNC
),
684 CreateMockRead(*msg2
, 3, ASYNC
),
685 MockRead(ASYNC
, 0, 4), // EOF
688 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
690 AssertConnectSucceeds();
692 Run(2); // SpdySession consumes the next two reads and sends then to
693 // sock_ to be buffered.
694 AssertSyncReadEquals(kMsg1
, kLen1
);
695 AssertSyncReadEquals(kMsg2
, kLen2
);
698 TEST_P(SpdyProxyClientSocketTest
,
699 LargeReadWillMergeDataFromDifferentFrames
) {
700 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
701 MockWrite writes
[] = {
702 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
705 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
706 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
707 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
709 CreateMockRead(*resp
, 1, ASYNC
),
710 CreateMockRead(*msg3
, 2, ASYNC
),
711 CreateMockRead(*msg3
, 3, ASYNC
),
712 MockRead(ASYNC
, 0, 4), // EOF
715 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
717 AssertConnectSucceeds();
719 Run(2); // SpdySession consumes the next two reads and sends then to
720 // sock_ to be buffered.
721 // The payload from two data frames, each with kMsg3 will be combined
722 // together into a single read().
723 AssertSyncReadEquals(kMsg33
, kLen33
);
726 TEST_P(SpdyProxyClientSocketTest
, MultipleShortReadsThenMoreRead
) {
727 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
728 MockWrite writes
[] = {
729 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
732 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
733 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
734 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
735 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
737 CreateMockRead(*resp
, 1, ASYNC
),
738 CreateMockRead(*msg1
, 2, ASYNC
),
739 CreateMockRead(*msg3
, 3, ASYNC
),
740 CreateMockRead(*msg3
, 4, ASYNC
),
741 CreateMockRead(*msg2
, 5, ASYNC
),
742 MockRead(ASYNC
, 0, 6), // EOF
745 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
747 AssertConnectSucceeds();
749 Run(4); // SpdySession consumes the next four reads and sends then to
750 // sock_ to be buffered.
751 AssertSyncReadEquals(kMsg1
, kLen1
);
752 // The payload from two data frames, each with kMsg3 will be combined
753 // together into a single read().
754 AssertSyncReadEquals(kMsg33
, kLen33
);
755 AssertSyncReadEquals(kMsg2
, kLen2
);
758 TEST_P(SpdyProxyClientSocketTest
, ReadWillSplitDataFromLargeFrame
) {
759 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
760 MockWrite writes
[] = {
761 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
764 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
765 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
766 scoped_ptr
<SpdyFrame
> msg33(ConstructBodyFrame(kMsg33
, kLen33
));
767 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
769 CreateMockRead(*resp
, 1, ASYNC
),
770 CreateMockRead(*msg1
, 2, ASYNC
),
771 CreateMockRead(*msg33
, 3, ASYNC
),
772 MockRead(ASYNC
, 0, 4), // EOF
775 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
777 AssertConnectSucceeds();
779 Run(2); // SpdySession consumes the next two reads and sends then to
780 // sock_ to be buffered.
781 AssertSyncReadEquals(kMsg1
, kLen1
);
782 // The payload from the single large data frame will be read across
783 // two different reads.
784 AssertSyncReadEquals(kMsg3
, kLen3
);
785 AssertSyncReadEquals(kMsg3
, kLen3
);
788 TEST_P(SpdyProxyClientSocketTest
, MultipleReadsFromSameLargeFrame
) {
789 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
790 MockWrite writes
[] = {
791 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
794 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
795 scoped_ptr
<SpdyFrame
> msg333(ConstructBodyFrame(kMsg333
, kLen333
));
797 CreateMockRead(*resp
, 1, ASYNC
),
798 CreateMockRead(*msg333
, 2, ASYNC
),
799 MockRead(ASYNC
, 0, 3), // EOF
802 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
804 AssertConnectSucceeds();
806 Run(1); // SpdySession consumes the next read and sends it to
807 // sock_ to be buffered.
808 // The payload from the single large data frame will be read across
809 // two different reads.
810 AssertSyncReadEquals(kMsg33
, kLen33
);
812 // Now attempt to do a read of more data than remains buffered
813 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen33
));
814 ASSERT_EQ(kLen3
, sock_
->Read(buf
.get(), kLen33
, read_callback_
.callback()));
815 ASSERT_EQ(std::string(kMsg3
, kLen3
), std::string(buf
->data(), kLen3
));
816 ASSERT_TRUE(sock_
->IsConnected());
819 TEST_P(SpdyProxyClientSocketTest
, ReadAuthResponseBody
) {
820 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
821 MockWrite writes
[] = {
822 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
825 scoped_ptr
<SpdyFrame
> resp(ConstructConnectAuthReplyFrame());
826 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
827 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
829 CreateMockRead(*resp
, 1, ASYNC
),
830 CreateMockRead(*msg1
, 2, ASYNC
),
831 CreateMockRead(*msg2
, 3, ASYNC
),
832 MockRead(ASYNC
, 0, 4), // EOF
835 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
837 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED
);
839 Run(2); // SpdySession consumes the next two reads and sends then to
840 // sock_ to be buffered.
841 AssertSyncReadEquals(kMsg1
, kLen1
);
842 AssertSyncReadEquals(kMsg2
, kLen2
);
845 TEST_P(SpdyProxyClientSocketTest
, ReadErrorResponseBody
) {
846 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
847 MockWrite writes
[] = {
848 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
851 scoped_ptr
<SpdyFrame
> resp(ConstructConnectErrorReplyFrame());
852 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
853 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
855 CreateMockRead(*resp
, 1, ASYNC
),
856 CreateMockRead(*msg1
, 2, ASYNC
),
857 CreateMockRead(*msg2
, 3, ASYNC
),
858 MockRead(ASYNC
, 0, 4), // EOF
861 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
863 AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED
);
866 // ----------- Reads and Writes
868 TEST_P(SpdyProxyClientSocketTest
, AsyncReadAroundWrite
) {
869 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
870 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
871 MockWrite writes
[] = {
872 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
873 CreateMockWrite(*msg2
, 3, SYNCHRONOUS
),
876 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
877 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
878 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
880 CreateMockRead(*resp
, 1, ASYNC
),
881 CreateMockRead(*msg1
, 2, ASYNC
), // sync read
882 CreateMockRead(*msg3
, 4, ASYNC
), // async read
883 MockRead(ASYNC
, 0, 5), // EOF
886 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
888 AssertConnectSucceeds();
891 AssertSyncReadEquals(kMsg1
, kLen1
);
893 AssertReadStarts(kMsg3
, kLen3
);
894 // Read should block until after the write succeeds
896 AssertAsyncWriteSucceeds(kMsg2
, kLen2
); // Runs 1 step
898 ASSERT_FALSE(read_callback_
.have_result());
900 // Now the read will return
901 AssertReadReturns(kMsg3
, kLen3
);
904 TEST_P(SpdyProxyClientSocketTest
, AsyncWriteAroundReads
) {
905 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
906 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
907 MockWrite writes
[] = {
908 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
909 CreateMockWrite(*msg2
, 4, ASYNC
),
912 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
913 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
914 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
916 CreateMockRead(*resp
, 1, ASYNC
),
917 CreateMockRead(*msg1
, 2, ASYNC
),
918 CreateMockRead(*msg3
, 3, ASYNC
),
919 MockRead(ASYNC
, 0, 5), // EOF
922 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
924 AssertConnectSucceeds();
927 AssertSyncReadEquals(kMsg1
, kLen1
);
928 // Write should block until the read completes
929 AssertWriteReturns(kMsg2
, kLen2
, ERR_IO_PENDING
);
931 AssertAsyncReadEquals(kMsg3
, kLen3
);
933 ASSERT_FALSE(write_callback_
.have_result());
935 // Now the write will complete
937 AssertWriteLength(kLen2
);
940 // ----------- Reading/Writing on Closed socket
942 // Reading from an already closed socket should return 0
943 TEST_P(SpdyProxyClientSocketTest
, ReadOnClosedSocketReturnsZero
) {
944 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
945 MockWrite writes
[] = {
946 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
949 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
951 CreateMockRead(*resp
, 1, ASYNC
),
952 MockRead(ASYNC
, 0, 2), // EOF
955 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
957 AssertConnectSucceeds();
961 ASSERT_FALSE(sock_
->IsConnected());
962 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
963 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
964 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
965 ASSERT_FALSE(sock_
->IsConnectedAndIdle());
968 // Read pending when socket is closed should return 0
969 TEST_P(SpdyProxyClientSocketTest
, PendingReadOnCloseReturnsZero
) {
970 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
971 MockWrite writes
[] = {
972 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
975 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
977 CreateMockRead(*resp
, 1, ASYNC
),
978 MockRead(ASYNC
, 0, 2), // EOF
981 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
983 AssertConnectSucceeds();
985 AssertReadStarts(kMsg1
, kLen1
);
989 ASSERT_EQ(0, read_callback_
.WaitForResult());
992 // Reading from a disconnected socket is an error
993 TEST_P(SpdyProxyClientSocketTest
,
994 ReadOnDisconnectSocketReturnsNotConnected
) {
995 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
996 scoped_ptr
<SpdyFrame
> rst(
997 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
998 MockWrite writes
[] = {
999 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1002 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1003 MockRead reads
[] = {
1004 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1007 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1009 AssertConnectSucceeds();
1011 sock_
->Disconnect();
1013 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1014 sock_
->Read(NULL
, 1, CompletionCallback()));
1016 // Let the RST_STREAM write while |rst| is in-scope.
1017 base::MessageLoop::current()->RunUntilIdle();
1020 // Reading buffered data from an already closed socket should return
1021 // buffered data, then 0.
1022 TEST_P(SpdyProxyClientSocketTest
, ReadOnClosedSocketReturnsBufferedData
) {
1023 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1024 MockWrite writes
[] = {
1025 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1028 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1029 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1030 MockRead reads
[] = {
1031 CreateMockRead(*resp
, 1, ASYNC
),
1032 CreateMockRead(*msg1
, 2, ASYNC
),
1033 MockRead(ASYNC
, 0, 3), // EOF
1036 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1038 AssertConnectSucceeds();
1042 ASSERT_FALSE(sock_
->IsConnected());
1043 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen1
));
1044 ASSERT_EQ(kLen1
, sock_
->Read(buf
.get(), kLen1
, CompletionCallback()));
1045 ASSERT_EQ(std::string(kMsg1
, kLen1
), std::string(buf
->data(), kLen1
));
1047 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
1048 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
1049 sock_
->Disconnect();
1050 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1051 sock_
->Read(NULL
, 1, CompletionCallback()));
1054 // Calling Write() on a closed socket is an error
1055 TEST_P(SpdyProxyClientSocketTest
, WriteOnClosedStream
) {
1056 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1057 MockWrite writes
[] = {
1058 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1061 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1062 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1063 MockRead reads
[] = {
1064 CreateMockRead(*resp
, 1, ASYNC
),
1065 MockRead(ASYNC
, 0, 2), // EOF
1068 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1070 AssertConnectSucceeds();
1072 Run(1); // Read EOF which will close the stream
1073 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1074 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1075 sock_
->Write(buf
.get(), buf
->size(), CompletionCallback()));
1078 // Calling Write() on a disconnected socket is an error
1079 TEST_P(SpdyProxyClientSocketTest
, WriteOnDisconnectedSocket
) {
1080 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1081 scoped_ptr
<SpdyFrame
> rst(
1082 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1083 MockWrite writes
[] = {
1084 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1087 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1088 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1089 MockRead reads
[] = {
1090 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1093 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1095 AssertConnectSucceeds();
1097 sock_
->Disconnect();
1099 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1100 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1101 sock_
->Write(buf
.get(), buf
->size(), CompletionCallback()));
1103 // Let the RST_STREAM write while |rst| is in-scope.
1104 base::MessageLoop::current()->RunUntilIdle();
1107 // If the socket is closed with a pending Write(), the callback
1108 // should be called with ERR_CONNECTION_CLOSED.
1109 TEST_P(SpdyProxyClientSocketTest
, WritePendingOnClose
) {
1110 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1111 MockWrite writes
[] = {
1112 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1113 MockWrite(ASYNC
, ERR_ABORTED
, 2),
1116 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1117 MockRead reads
[] = {
1118 CreateMockRead(*resp
, 1, ASYNC
),
1119 MockRead(ASYNC
, 0, 3), // EOF
1122 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1124 AssertConnectSucceeds();
1126 EXPECT_TRUE(sock_
->IsConnected());
1128 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1129 EXPECT_EQ(ERR_IO_PENDING
,
1130 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
1132 CloseSpdySession(ERR_ABORTED
, std::string());
1134 EXPECT_EQ(ERR_CONNECTION_CLOSED
, write_callback_
.WaitForResult());
1137 // If the socket is Disconnected with a pending Write(), the callback
1138 // should not be called.
1139 TEST_P(SpdyProxyClientSocketTest
, DisconnectWithWritePending
) {
1140 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1141 scoped_ptr
<SpdyFrame
> rst(
1142 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1143 MockWrite writes
[] = {
1144 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1145 MockWrite(SYNCHRONOUS
, 0, 3), // EOF
1148 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1149 MockRead reads
[] = {
1150 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 4), // EOF
1153 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1155 AssertConnectSucceeds();
1157 EXPECT_TRUE(sock_
->IsConnected());
1159 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1160 EXPECT_EQ(ERR_IO_PENDING
,
1161 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
1163 sock_
->Disconnect();
1165 EXPECT_FALSE(sock_
->IsConnected());
1166 EXPECT_FALSE(write_callback_
.have_result());
1168 // Let the RST_STREAM write while |rst| is in-scope.
1169 base::MessageLoop::current()->RunUntilIdle();
1172 // If the socket is Disconnected with a pending Read(), the callback
1173 // should not be called.
1174 TEST_P(SpdyProxyClientSocketTest
, DisconnectWithReadPending
) {
1175 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1176 scoped_ptr
<SpdyFrame
> rst(
1177 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1178 MockWrite writes
[] = {
1179 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1182 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1183 MockRead reads
[] = {
1184 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1187 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1189 AssertConnectSucceeds();
1191 EXPECT_TRUE(sock_
->IsConnected());
1193 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen1
));
1194 ASSERT_EQ(ERR_IO_PENDING
,
1195 sock_
->Read(buf
.get(), kLen1
, read_callback_
.callback()));
1197 sock_
->Disconnect();
1199 EXPECT_FALSE(sock_
->IsConnected());
1200 EXPECT_FALSE(read_callback_
.have_result());
1202 // Let the RST_STREAM write while |rst| is in-scope.
1203 base::MessageLoop::current()->RunUntilIdle();
1206 // If the socket is Reset when both a read and write are pending,
1207 // both should be called back.
1208 TEST_P(SpdyProxyClientSocketTest
, RstWithReadAndWritePending
) {
1209 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1210 MockWrite writes
[] = {
1211 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1212 MockWrite(ASYNC
, ERR_ABORTED
, 3),
1215 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1216 scoped_ptr
<SpdyFrame
> rst(
1217 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1218 MockRead reads
[] = {
1219 CreateMockRead(*resp
, 1, ASYNC
),
1220 CreateMockRead(*rst
, 2, ASYNC
),
1221 MockRead(ASYNC
, 0, 4) // EOF
1224 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1226 AssertConnectSucceeds();
1228 EXPECT_TRUE(sock_
->IsConnected());
1230 scoped_refptr
<IOBuffer
> read_buf(new IOBuffer(kLen1
));
1231 ASSERT_EQ(ERR_IO_PENDING
,
1232 sock_
->Read(read_buf
.get(), kLen1
, read_callback_
.callback()));
1234 scoped_refptr
<IOBufferWithSize
> write_buf(CreateBuffer(kMsg1
, kLen1
));
1238 write_buf
.get(), write_buf
->size(), write_callback_
.callback()));
1242 EXPECT_TRUE(sock_
.get());
1243 EXPECT_TRUE(read_callback_
.have_result());
1244 EXPECT_TRUE(write_callback_
.have_result());
1246 // Let the RST_STREAM write while |rst| is in-scope.
1247 base::MessageLoop::current()->RunUntilIdle();
1250 // Makes sure the proxy client socket's source gets the expected NetLog events
1251 // and only the expected NetLog events (No SpdySession events).
1252 TEST_P(SpdyProxyClientSocketTest
, NetLog
) {
1253 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1254 scoped_ptr
<SpdyFrame
> rst(
1255 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1256 MockWrite writes
[] = {
1257 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 3),
1260 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1261 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1262 MockRead reads
[] = {
1263 CreateMockRead(*resp
, 1, ASYNC
), CreateMockRead(*msg1
, 2, ASYNC
),
1264 MockRead(ASYNC
, 0, 4), // EOF
1267 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1269 AssertConnectSucceeds();
1271 Run(1); // SpdySession consumes the next read and sends it to
1272 // sock_ to be buffered.
1273 AssertSyncReadEquals(kMsg1
, kLen1
);
1275 NetLog::Source sock_source
= sock_
->NetLog().source();
1278 CapturingNetLog::CapturedEntryList entry_list
;
1279 net_log_
.GetEntriesForSource(sock_source
, &entry_list
);
1281 ASSERT_EQ(entry_list
.size(), 10u);
1282 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 0, NetLog::TYPE_SOCKET_ALIVE
));
1283 EXPECT_TRUE(LogContainsEvent(entry_list
, 1,
1284 NetLog::TYPE_HTTP2_PROXY_CLIENT_SESSION
,
1285 NetLog::PHASE_NONE
));
1286 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 2,
1287 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST
));
1288 EXPECT_TRUE(LogContainsEvent(entry_list
, 3,
1289 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
1290 NetLog::PHASE_NONE
));
1291 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 4,
1292 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST
));
1293 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 5,
1294 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS
));
1295 EXPECT_TRUE(LogContainsEvent(entry_list
, 6,
1296 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
1297 NetLog::PHASE_NONE
));
1298 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 7,
1299 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS
));
1300 EXPECT_TRUE(LogContainsEvent(entry_list
, 8,
1301 NetLog::TYPE_SOCKET_BYTES_RECEIVED
,
1302 NetLog::PHASE_NONE
));
1303 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 9, NetLog::TYPE_SOCKET_ALIVE
));
1305 // Let the RST_STREAM write while |rst| is in-scope.
1306 base::MessageLoop::current()->RunUntilIdle();
1309 // CompletionCallback that causes the SpdyProxyClientSocket to be
1310 // deleted when Run is invoked.
1311 class DeleteSockCallback
: public TestCompletionCallbackBase
{
1313 explicit DeleteSockCallback(scoped_ptr
<SpdyProxyClientSocket
>* sock
)
1315 callback_(base::Bind(&DeleteSockCallback::OnComplete
,
1316 base::Unretained(this))) {
1319 ~DeleteSockCallback() override
{}
1321 const CompletionCallback
& callback() const { return callback_
; }
1324 void OnComplete(int result
) {
1329 scoped_ptr
<SpdyProxyClientSocket
>* sock_
;
1330 CompletionCallback callback_
;
1332 DISALLOW_COPY_AND_ASSIGN(DeleteSockCallback
);
1335 // If the socket is Reset when both a read and write are pending, and the
1336 // read callback causes the socket to be deleted, the write callback should
1338 TEST_P(SpdyProxyClientSocketTest
, RstWithReadAndWritePendingDelete
) {
1339 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1340 MockWrite writes
[] = {
1341 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1342 MockWrite(ASYNC
, ERR_ABORTED
, 3),
1345 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1346 scoped_ptr
<SpdyFrame
> rst(
1347 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1348 MockRead reads
[] = {
1349 CreateMockRead(*resp
, 1, ASYNC
),
1350 CreateMockRead(*rst
, 2, ASYNC
),
1351 MockRead(ASYNC
, 0, 4), // EOF
1354 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1356 AssertConnectSucceeds();
1358 EXPECT_TRUE(sock_
->IsConnected());
1360 DeleteSockCallback
read_callback(&sock_
);
1362 scoped_refptr
<IOBuffer
> read_buf(new IOBuffer(kLen1
));
1363 ASSERT_EQ(ERR_IO_PENDING
,
1364 sock_
->Read(read_buf
.get(), kLen1
, read_callback
.callback()));
1366 scoped_refptr
<IOBufferWithSize
> write_buf(CreateBuffer(kMsg1
, kLen1
));
1370 write_buf
.get(), write_buf
->size(), write_callback_
.callback()));
1374 EXPECT_FALSE(sock_
.get());
1375 EXPECT_TRUE(read_callback
.have_result());
1376 EXPECT_FALSE(write_callback_
.have_result());
1378 // Let the RST_STREAM write while |rst| is in-scope.
1379 base::MessageLoop::current()->RunUntilIdle();