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/net_log.h"
17 #include "net/log/test_net_log.h"
18 #include "net/log/test_net_log_entry.h"
19 #include "net/log/test_net_log_util.h"
20 #include "net/socket/client_socket_factory.h"
21 #include "net/socket/next_proto.h"
22 #include "net/socket/socket_test_util.h"
23 #include "net/socket/tcp_client_socket.h"
24 #include "net/spdy/buffered_spdy_framer.h"
25 #include "net/spdy/spdy_http_utils.h"
26 #include "net/spdy/spdy_protocol.h"
27 #include "net/spdy/spdy_session_pool.h"
28 #include "net/spdy/spdy_test_util_common.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "testing/platform_test.h"
32 //-----------------------------------------------------------------------------
36 static const char kRequestUrl
[] = "https://www.google.com/";
37 static const char kOriginHost
[] = "www.google.com";
38 static const int kOriginPort
= 443;
39 static const char kOriginHostPort
[] = "www.google.com:443";
40 static const char kProxyUrl
[] = "https://myproxy:6121/";
41 static const char kProxyHost
[] = "myproxy";
42 static const int kProxyPort
= 6121;
43 static const char kUserAgent
[] = "Mozilla/1.0";
45 static const int kStreamId
= 1;
47 static const char kMsg1
[] = "\0hello!\xff";
48 static const int kLen1
= 8;
49 static const char kMsg2
[] = "\0a2345678\0";
50 static const int kLen2
= 10;
51 static const char kMsg3
[] = "bye!";
52 static const int kLen3
= 4;
53 static const char kMsg33
[] = "bye!bye!";
54 static const int kLen33
= kLen3
+ kLen3
;
55 static const char kMsg333
[] = "bye!bye!bye!";
56 static const int kLen333
= kLen3
+ kLen3
+ kLen3
;
58 static const char kRedirectUrl
[] = "https://example.com/";
60 } // anonymous namespace
64 class SpdyProxyClientSocketTest
65 : public PlatformTest
,
66 public testing::WithParamInterface
<NextProto
> {
68 SpdyProxyClientSocketTest();
70 void TearDown() override
;
73 void Initialize(MockRead
* reads
, size_t reads_count
, MockWrite
* writes
,
75 void PopulateConnectRequestIR(SpdyHeaderBlock
* syn_ir
);
76 void PopulateConnectReplyIR(SpdyHeaderBlock
* block
, const char* status
);
77 SpdyFrame
* ConstructConnectRequestFrame();
78 SpdyFrame
* ConstructConnectAuthRequestFrame();
79 SpdyFrame
* ConstructConnectReplyFrame();
80 SpdyFrame
* ConstructConnectAuthReplyFrame();
81 SpdyFrame
* ConstructConnectRedirectReplyFrame();
82 SpdyFrame
* ConstructConnectErrorReplyFrame();
83 SpdyFrame
* ConstructBodyFrame(const char* data
, int length
);
84 scoped_refptr
<IOBufferWithSize
> CreateBuffer(const char* data
, int size
);
85 void AssertConnectSucceeds();
86 void AssertConnectFails(int result
);
87 void AssertConnectionEstablished();
88 void AssertSyncReadEquals(const char* data
, int len
);
89 void AssertAsyncReadEquals(const char* data
, int len
);
90 void AssertReadStarts(const char* data
, int len
);
91 void AssertReadReturns(const char* data
, int len
);
92 void AssertAsyncWriteSucceeds(const char* data
, int len
);
93 void AssertWriteReturns(const char* data
, int len
, int rv
);
94 void AssertWriteLength(int len
);
95 void AssertAsyncWriteWithReadsSucceeds(const char* data
, int len
,
98 void AddAuthToCache() {
99 const base::string16
kFoo(base::ASCIIToUTF16("foo"));
100 const base::string16
kBar(base::ASCIIToUTF16("bar"));
101 session_
->http_auth_cache()->Add(GURL(kProxyUrl
),
103 HttpAuth::AUTH_SCHEME_BASIC
,
104 "Basic realm=MyRealm1",
105 AuthCredentials(kFoo
, kBar
),
109 void Run(int steps
) {
110 data_
->StopAfter(steps
);
114 void CloseSpdySession(Error error
, const std::string
& description
) {
115 spdy_session_
->CloseSessionOnError(error
, description
);
118 SpdyTestUtil spdy_util_
;
119 scoped_ptr
<SpdyProxyClientSocket
> sock_
;
120 TestCompletionCallback read_callback_
;
121 TestCompletionCallback write_callback_
;
122 scoped_ptr
<DeterministicSocketData
> data_
;
123 BoundTestNetLog net_log_
;
126 scoped_refptr
<HttpNetworkSession
> session_
;
127 scoped_refptr
<IOBuffer
> read_buf_
;
128 SpdySessionDependencies session_deps_
;
129 MockConnect connect_data_
;
130 base::WeakPtr
<SpdySession
> spdy_session_
;
131 BufferedSpdyFramer framer_
;
133 std::string user_agent_
;
135 HostPortPair proxy_host_port_
;
136 HostPortPair endpoint_host_port_pair_
;
138 SpdySessionKey endpoint_spdy_session_key_
;
140 DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocketTest
);
143 INSTANTIATE_TEST_CASE_P(NextProto
,
144 SpdyProxyClientSocketTest
,
145 testing::Values(kProtoSPDY31
,
149 SpdyProxyClientSocketTest::SpdyProxyClientSocketTest()
150 : spdy_util_(GetParam()),
153 session_deps_(GetParam()),
154 connect_data_(SYNCHRONOUS
, OK
),
155 framer_(spdy_util_
.spdy_version(), false),
156 user_agent_(kUserAgent
),
158 proxy_host_port_(kProxyHost
, kProxyPort
),
159 endpoint_host_port_pair_(kOriginHost
, kOriginPort
),
160 proxy_(ProxyServer::SCHEME_HTTPS
, proxy_host_port_
),
161 endpoint_spdy_session_key_(endpoint_host_port_pair_
,
163 PRIVACY_MODE_DISABLED
) {
164 session_deps_
.net_log
= net_log_
.bound().net_log();
167 void SpdyProxyClientSocketTest::TearDown() {
168 if (session_
.get() != NULL
)
169 session_
->spdy_session_pool()->CloseAllSessions();
171 // Empty the current queue.
172 base::MessageLoop::current()->RunUntilIdle();
173 PlatformTest::TearDown();
176 void SpdyProxyClientSocketTest::Initialize(MockRead
* reads
,
179 size_t writes_count
) {
180 data_
.reset(new DeterministicSocketData(reads
, reads_count
,
181 writes
, writes_count
));
182 data_
->set_connect_data(connect_data_
);
185 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
187 session_deps_
.host_resolver
->set_synchronous_mode(true);
189 session_
= SpdySessionDependencies::SpdyCreateSessionDeterministic(
192 // Creates the SPDY session and stream.
194 CreateInsecureSpdySession(
195 session_
, endpoint_spdy_session_key_
, BoundNetLog());
196 base::WeakPtr
<SpdyStream
> spdy_stream(
197 CreateStreamSynchronously(
198 SPDY_BIDIRECTIONAL_STREAM
, spdy_session_
, url_
, LOWEST
,
200 ASSERT_TRUE(spdy_stream
.get() != NULL
);
202 // Create the SpdyProxyClientSocket.
203 sock_
.reset(new SpdyProxyClientSocket(
204 spdy_stream
, user_agent_
, endpoint_host_port_pair_
, proxy_host_port_
,
205 net_log_
.bound(), 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 if (spdy_util_
.spdy_version() == HTTP2
) {
316 (*block
)[spdy_util_
.GetHostKey()] = kOriginHostPort
;
318 (*block
)[spdy_util_
.GetPathKey()] = kOriginHostPort
;
319 (*block
)[spdy_util_
.GetHostKey()] = kOriginHost
;
321 (*block
)["user-agent"] = kUserAgent
;
322 spdy_util_
.MaybeAddVersionHeader(block
);
325 void SpdyProxyClientSocketTest::PopulateConnectReplyIR(SpdyHeaderBlock
* block
,
326 const char* status
) {
327 (*block
)[spdy_util_
.GetStatusKey()] = status
;
328 spdy_util_
.MaybeAddVersionHeader(block
);
331 // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
333 SpdyProxyClientSocketTest::ConstructConnectRequestFrame() {
334 SpdyHeaderBlock block
;
335 PopulateConnectRequestIR(&block
);
336 return spdy_util_
.ConstructSpdySyn(kStreamId
, block
, LOWEST
, false, false);
339 // Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes
340 // Proxy-Authorization headers.
341 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() {
342 SpdyHeaderBlock block
;
343 PopulateConnectRequestIR(&block
);
344 block
["proxy-authorization"] = "Basic Zm9vOmJhcg==";
345 return spdy_util_
.ConstructSpdySyn(kStreamId
, block
, LOWEST
, false, false);
348 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT.
349 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() {
350 SpdyHeaderBlock block
;
351 PopulateConnectReplyIR(&block
, "200");
352 SpdySynReplyIR
reply_ir(kStreamId
);
353 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
356 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT,
357 // including Proxy-Authenticate headers.
358 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() {
359 SpdyHeaderBlock block
;
360 PopulateConnectReplyIR(&block
, "407");
361 block
["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
362 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
365 // Constructs a SPDY SYN_REPLY frame with an HTTP 302 redirect.
366 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectRedirectReplyFrame() {
367 SpdyHeaderBlock block
;
368 PopulateConnectReplyIR(&block
, "302");
369 block
["location"] = kRedirectUrl
;
370 block
["set-cookie"] = "foo=bar";
371 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
374 // Constructs a SPDY SYN_REPLY frame with an HTTP 500 error.
375 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() {
376 SpdyHeaderBlock block
;
377 PopulateConnectReplyIR(&block
, "500");
378 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
381 SpdyFrame
* SpdyProxyClientSocketTest::ConstructBodyFrame(
384 return framer_
.CreateDataFrame(kStreamId
, data
, length
, DATA_FLAG_NONE
);
387 // ----------- Connect
389 TEST_P(SpdyProxyClientSocketTest
, ConnectSendsCorrectRequest
) {
390 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
391 MockWrite writes
[] = {
392 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
395 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
397 CreateMockRead(*resp
, 1, ASYNC
),
398 MockRead(ASYNC
, 0, 2), // EOF
401 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
403 ASSERT_FALSE(sock_
->IsConnected());
405 AssertConnectSucceeds();
407 AssertConnectionEstablished();
410 TEST_P(SpdyProxyClientSocketTest
, ConnectWithAuthRequested
) {
411 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
412 MockWrite writes
[] = {
413 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
416 scoped_ptr
<SpdyFrame
> resp(ConstructConnectAuthReplyFrame());
418 CreateMockRead(*resp
, 1, ASYNC
),
419 MockRead(ASYNC
, 0, 2), // EOF
422 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
424 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED
);
426 const HttpResponseInfo
* response
= sock_
->GetConnectResponseInfo();
427 ASSERT_TRUE(response
!= NULL
);
428 ASSERT_EQ(407, response
->headers
->response_code());
431 TEST_P(SpdyProxyClientSocketTest
, ConnectWithAuthCredentials
) {
432 scoped_ptr
<SpdyFrame
> conn(ConstructConnectAuthRequestFrame());
433 MockWrite writes
[] = {
434 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
437 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
439 CreateMockRead(*resp
, 1, ASYNC
),
440 MockRead(ASYNC
, 0, 2), // EOF
443 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
446 AssertConnectSucceeds();
448 AssertConnectionEstablished();
451 TEST_P(SpdyProxyClientSocketTest
, ConnectRedirects
) {
452 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
453 scoped_ptr
<SpdyFrame
> rst(
454 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
455 MockWrite writes
[] = {
456 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
459 scoped_ptr
<SpdyFrame
> resp(ConstructConnectRedirectReplyFrame());
461 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
464 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
466 AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE
);
468 const HttpResponseInfo
* response
= sock_
->GetConnectResponseInfo();
469 ASSERT_TRUE(response
!= NULL
);
471 const HttpResponseHeaders
* headers
= response
->headers
.get();
472 ASSERT_EQ(302, headers
->response_code());
473 ASSERT_FALSE(headers
->HasHeader("set-cookie"));
474 ASSERT_TRUE(headers
->HasHeaderValue("content-length", "0"));
476 std::string location
;
477 ASSERT_TRUE(headers
->IsRedirect(&location
));
478 ASSERT_EQ(location
, kRedirectUrl
);
480 // Let the RST_STREAM write while |rst| is in-scope.
481 base::MessageLoop::current()->RunUntilIdle();
484 TEST_P(SpdyProxyClientSocketTest
, ConnectFails
) {
485 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
486 MockWrite writes
[] = {
487 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
490 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
492 MockRead(ASYNC
, 0, 1), // EOF
495 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
497 ASSERT_FALSE(sock_
->IsConnected());
499 AssertConnectFails(ERR_CONNECTION_CLOSED
);
501 ASSERT_FALSE(sock_
->IsConnected());
504 // ----------- WasEverUsed
506 TEST_P(SpdyProxyClientSocketTest
, WasEverUsedReturnsCorrectValues
) {
507 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
508 scoped_ptr
<SpdyFrame
> rst(
509 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
510 MockWrite writes
[] = {
511 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
514 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
516 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
519 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
521 EXPECT_FALSE(sock_
->WasEverUsed());
522 AssertConnectSucceeds();
523 EXPECT_TRUE(sock_
->WasEverUsed());
525 EXPECT_TRUE(sock_
->WasEverUsed());
527 // Let the RST_STREAM write while |rst| is in-scope.
528 base::MessageLoop::current()->RunUntilIdle();
531 // ----------- GetPeerAddress
533 TEST_P(SpdyProxyClientSocketTest
, GetPeerAddressReturnsCorrectValues
) {
534 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
535 MockWrite writes
[] = {
536 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
539 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
541 CreateMockRead(*resp
, 1, ASYNC
),
542 MockRead(ASYNC
, 0, 2), // EOF
545 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
548 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
550 AssertConnectSucceeds();
551 EXPECT_TRUE(sock_
->IsConnected());
552 EXPECT_EQ(OK
, sock_
->GetPeerAddress(&addr
));
556 EXPECT_FALSE(sock_
->IsConnected());
557 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
561 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
566 TEST_P(SpdyProxyClientSocketTest
, WriteSendsDataInDataFrame
) {
567 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
568 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
569 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
570 MockWrite writes
[] = {
571 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
572 CreateMockWrite(*msg1
, 2, SYNCHRONOUS
),
573 CreateMockWrite(*msg2
, 3, SYNCHRONOUS
),
576 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
578 CreateMockRead(*resp
, 1, ASYNC
),
579 MockRead(ASYNC
, 0, 4), // EOF
582 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
584 AssertConnectSucceeds();
586 AssertAsyncWriteSucceeds(kMsg1
, kLen1
);
587 AssertAsyncWriteSucceeds(kMsg2
, kLen2
);
590 TEST_P(SpdyProxyClientSocketTest
, WriteSplitsLargeDataIntoMultipleFrames
) {
591 std::string
chunk_data(kMaxSpdyFrameChunkSize
, 'x');
592 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
593 scoped_ptr
<SpdyFrame
> chunk(ConstructBodyFrame(chunk_data
.data(),
594 chunk_data
.length()));
595 MockWrite writes
[] = {
596 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
597 CreateMockWrite(*chunk
, 2, SYNCHRONOUS
),
598 CreateMockWrite(*chunk
, 3, SYNCHRONOUS
),
599 CreateMockWrite(*chunk
, 4, SYNCHRONOUS
)
602 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
604 CreateMockRead(*resp
, 1, ASYNC
),
605 MockRead(ASYNC
, 0, 5), // EOF
608 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
610 AssertConnectSucceeds();
612 std::string
big_data(kMaxSpdyFrameChunkSize
* 3, 'x');
613 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(big_data
.data(),
616 EXPECT_EQ(ERR_IO_PENDING
,
617 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
620 EXPECT_EQ(buf
->size(), write_callback_
.WaitForResult());
625 TEST_P(SpdyProxyClientSocketTest
, ReadReadsDataInDataFrame
) {
626 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
627 MockWrite writes
[] = {
628 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
631 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
632 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
634 CreateMockRead(*resp
, 1, ASYNC
),
635 CreateMockRead(*msg1
, 2, ASYNC
),
636 MockRead(ASYNC
, 0, 3), // EOF
639 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
641 AssertConnectSucceeds();
643 Run(1); // SpdySession consumes the next read and sends it to
644 // sock_ to be buffered.
645 AssertSyncReadEquals(kMsg1
, kLen1
);
648 TEST_P(SpdyProxyClientSocketTest
, ReadDataFromBufferedFrames
) {
649 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
650 MockWrite writes
[] = {
651 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
654 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
655 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
656 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
658 CreateMockRead(*resp
, 1, ASYNC
),
659 CreateMockRead(*msg1
, 2, ASYNC
),
660 CreateMockRead(*msg2
, 3, ASYNC
),
661 MockRead(ASYNC
, 0, 4), // EOF
664 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
666 AssertConnectSucceeds();
668 Run(1); // SpdySession consumes the next read and sends it to
669 // sock_ to be buffered.
670 AssertSyncReadEquals(kMsg1
, kLen1
);
671 Run(1); // SpdySession consumes the next read and sends it to
672 // sock_ to be buffered.
673 AssertSyncReadEquals(kMsg2
, kLen2
);
676 TEST_P(SpdyProxyClientSocketTest
, ReadDataMultipleBufferedFrames
) {
677 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
678 MockWrite writes
[] = {
679 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
682 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
683 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
684 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
686 CreateMockRead(*resp
, 1, ASYNC
),
687 CreateMockRead(*msg1
, 2, ASYNC
),
688 CreateMockRead(*msg2
, 3, ASYNC
),
689 MockRead(ASYNC
, 0, 4), // EOF
692 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
694 AssertConnectSucceeds();
696 Run(2); // SpdySession consumes the next two reads and sends then to
697 // sock_ to be buffered.
698 AssertSyncReadEquals(kMsg1
, kLen1
);
699 AssertSyncReadEquals(kMsg2
, kLen2
);
702 TEST_P(SpdyProxyClientSocketTest
,
703 LargeReadWillMergeDataFromDifferentFrames
) {
704 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
705 MockWrite writes
[] = {
706 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
709 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
710 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
711 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
713 CreateMockRead(*resp
, 1, ASYNC
),
714 CreateMockRead(*msg3
, 2, ASYNC
),
715 CreateMockRead(*msg3
, 3, ASYNC
),
716 MockRead(ASYNC
, 0, 4), // EOF
719 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
721 AssertConnectSucceeds();
723 Run(2); // SpdySession consumes the next two reads and sends then to
724 // sock_ to be buffered.
725 // The payload from two data frames, each with kMsg3 will be combined
726 // together into a single read().
727 AssertSyncReadEquals(kMsg33
, kLen33
);
730 TEST_P(SpdyProxyClientSocketTest
, MultipleShortReadsThenMoreRead
) {
731 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
732 MockWrite writes
[] = {
733 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
736 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
737 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
738 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
739 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
741 CreateMockRead(*resp
, 1, ASYNC
),
742 CreateMockRead(*msg1
, 2, ASYNC
),
743 CreateMockRead(*msg3
, 3, ASYNC
),
744 CreateMockRead(*msg3
, 4, ASYNC
),
745 CreateMockRead(*msg2
, 5, ASYNC
),
746 MockRead(ASYNC
, 0, 6), // EOF
749 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
751 AssertConnectSucceeds();
753 Run(4); // SpdySession consumes the next four reads and sends then to
754 // sock_ to be buffered.
755 AssertSyncReadEquals(kMsg1
, kLen1
);
756 // The payload from two data frames, each with kMsg3 will be combined
757 // together into a single read().
758 AssertSyncReadEquals(kMsg33
, kLen33
);
759 AssertSyncReadEquals(kMsg2
, kLen2
);
762 TEST_P(SpdyProxyClientSocketTest
, ReadWillSplitDataFromLargeFrame
) {
763 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
764 MockWrite writes
[] = {
765 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
768 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
769 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
770 scoped_ptr
<SpdyFrame
> msg33(ConstructBodyFrame(kMsg33
, kLen33
));
771 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
773 CreateMockRead(*resp
, 1, ASYNC
),
774 CreateMockRead(*msg1
, 2, ASYNC
),
775 CreateMockRead(*msg33
, 3, ASYNC
),
776 MockRead(ASYNC
, 0, 4), // EOF
779 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
781 AssertConnectSucceeds();
783 Run(2); // SpdySession consumes the next two reads and sends then to
784 // sock_ to be buffered.
785 AssertSyncReadEquals(kMsg1
, kLen1
);
786 // The payload from the single large data frame will be read across
787 // two different reads.
788 AssertSyncReadEquals(kMsg3
, kLen3
);
789 AssertSyncReadEquals(kMsg3
, kLen3
);
792 TEST_P(SpdyProxyClientSocketTest
, MultipleReadsFromSameLargeFrame
) {
793 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
794 MockWrite writes
[] = {
795 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
798 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
799 scoped_ptr
<SpdyFrame
> msg333(ConstructBodyFrame(kMsg333
, kLen333
));
801 CreateMockRead(*resp
, 1, ASYNC
),
802 CreateMockRead(*msg333
, 2, ASYNC
),
803 MockRead(ASYNC
, 0, 3), // EOF
806 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
808 AssertConnectSucceeds();
810 Run(1); // SpdySession consumes the next read and sends it to
811 // sock_ to be buffered.
812 // The payload from the single large data frame will be read across
813 // two different reads.
814 AssertSyncReadEquals(kMsg33
, kLen33
);
816 // Now attempt to do a read of more data than remains buffered
817 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen33
));
818 ASSERT_EQ(kLen3
, sock_
->Read(buf
.get(), kLen33
, read_callback_
.callback()));
819 ASSERT_EQ(std::string(kMsg3
, kLen3
), std::string(buf
->data(), kLen3
));
820 ASSERT_TRUE(sock_
->IsConnected());
823 TEST_P(SpdyProxyClientSocketTest
, ReadAuthResponseBody
) {
824 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
825 MockWrite writes
[] = {
826 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
829 scoped_ptr
<SpdyFrame
> resp(ConstructConnectAuthReplyFrame());
830 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
831 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
833 CreateMockRead(*resp
, 1, ASYNC
),
834 CreateMockRead(*msg1
, 2, ASYNC
),
835 CreateMockRead(*msg2
, 3, ASYNC
),
836 MockRead(ASYNC
, 0, 4), // EOF
839 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
841 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED
);
843 Run(2); // SpdySession consumes the next two reads and sends then to
844 // sock_ to be buffered.
845 AssertSyncReadEquals(kMsg1
, kLen1
);
846 AssertSyncReadEquals(kMsg2
, kLen2
);
849 TEST_P(SpdyProxyClientSocketTest
, ReadErrorResponseBody
) {
850 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
851 MockWrite writes
[] = {
852 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
855 scoped_ptr
<SpdyFrame
> resp(ConstructConnectErrorReplyFrame());
856 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
857 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
859 CreateMockRead(*resp
, 1, ASYNC
),
860 CreateMockRead(*msg1
, 2, ASYNC
),
861 CreateMockRead(*msg2
, 3, ASYNC
),
862 MockRead(ASYNC
, 0, 4), // EOF
865 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
867 AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED
);
870 // ----------- Reads and Writes
872 TEST_P(SpdyProxyClientSocketTest
, AsyncReadAroundWrite
) {
873 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
874 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
875 MockWrite writes
[] = {
876 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
877 CreateMockWrite(*msg2
, 3, SYNCHRONOUS
),
880 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
881 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
882 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
884 CreateMockRead(*resp
, 1, ASYNC
),
885 CreateMockRead(*msg1
, 2, ASYNC
), // sync read
886 CreateMockRead(*msg3
, 4, ASYNC
), // async read
887 MockRead(ASYNC
, 0, 5), // EOF
890 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
892 AssertConnectSucceeds();
895 AssertSyncReadEquals(kMsg1
, kLen1
);
897 AssertReadStarts(kMsg3
, kLen3
);
898 // Read should block until after the write succeeds
900 AssertAsyncWriteSucceeds(kMsg2
, kLen2
); // Runs 1 step
902 ASSERT_FALSE(read_callback_
.have_result());
904 // Now the read will return
905 AssertReadReturns(kMsg3
, kLen3
);
908 TEST_P(SpdyProxyClientSocketTest
, AsyncWriteAroundReads
) {
909 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
910 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
911 MockWrite writes
[] = {
912 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
913 CreateMockWrite(*msg2
, 4, ASYNC
),
916 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
917 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
918 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
920 CreateMockRead(*resp
, 1, ASYNC
),
921 CreateMockRead(*msg1
, 2, ASYNC
),
922 CreateMockRead(*msg3
, 3, ASYNC
),
923 MockRead(ASYNC
, 0, 5), // EOF
926 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
928 AssertConnectSucceeds();
931 AssertSyncReadEquals(kMsg1
, kLen1
);
932 // Write should block until the read completes
933 AssertWriteReturns(kMsg2
, kLen2
, ERR_IO_PENDING
);
935 AssertAsyncReadEquals(kMsg3
, kLen3
);
937 ASSERT_FALSE(write_callback_
.have_result());
939 // Now the write will complete
941 AssertWriteLength(kLen2
);
944 // ----------- Reading/Writing on Closed socket
946 // Reading from an already closed socket should return 0
947 TEST_P(SpdyProxyClientSocketTest
, ReadOnClosedSocketReturnsZero
) {
948 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
949 MockWrite writes
[] = {
950 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
953 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
955 CreateMockRead(*resp
, 1, ASYNC
),
956 MockRead(ASYNC
, 0, 2), // EOF
959 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
961 AssertConnectSucceeds();
965 ASSERT_FALSE(sock_
->IsConnected());
966 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
967 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
968 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
969 ASSERT_FALSE(sock_
->IsConnectedAndIdle());
972 // Read pending when socket is closed should return 0
973 TEST_P(SpdyProxyClientSocketTest
, PendingReadOnCloseReturnsZero
) {
974 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
975 MockWrite writes
[] = {
976 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
979 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
981 CreateMockRead(*resp
, 1, ASYNC
),
982 MockRead(ASYNC
, 0, 2), // EOF
985 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
987 AssertConnectSucceeds();
989 AssertReadStarts(kMsg1
, kLen1
);
993 ASSERT_EQ(0, read_callback_
.WaitForResult());
996 // Reading from a disconnected socket is an error
997 TEST_P(SpdyProxyClientSocketTest
,
998 ReadOnDisconnectSocketReturnsNotConnected
) {
999 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1000 scoped_ptr
<SpdyFrame
> rst(
1001 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1002 MockWrite writes
[] = {
1003 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1006 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1007 MockRead reads
[] = {
1008 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1011 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1013 AssertConnectSucceeds();
1015 sock_
->Disconnect();
1017 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1018 sock_
->Read(NULL
, 1, CompletionCallback()));
1020 // Let the RST_STREAM write while |rst| is in-scope.
1021 base::MessageLoop::current()->RunUntilIdle();
1024 // Reading buffered data from an already closed socket should return
1025 // buffered data, then 0.
1026 TEST_P(SpdyProxyClientSocketTest
, ReadOnClosedSocketReturnsBufferedData
) {
1027 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1028 MockWrite writes
[] = {
1029 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1032 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1033 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1034 MockRead reads
[] = {
1035 CreateMockRead(*resp
, 1, ASYNC
),
1036 CreateMockRead(*msg1
, 2, ASYNC
),
1037 MockRead(ASYNC
, 0, 3), // EOF
1040 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1042 AssertConnectSucceeds();
1046 ASSERT_FALSE(sock_
->IsConnected());
1047 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen1
));
1048 ASSERT_EQ(kLen1
, sock_
->Read(buf
.get(), kLen1
, CompletionCallback()));
1049 ASSERT_EQ(std::string(kMsg1
, kLen1
), std::string(buf
->data(), kLen1
));
1051 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
1052 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
1053 sock_
->Disconnect();
1054 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1055 sock_
->Read(NULL
, 1, CompletionCallback()));
1058 // Calling Write() on a closed socket is an error
1059 TEST_P(SpdyProxyClientSocketTest
, WriteOnClosedStream
) {
1060 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1061 MockWrite writes
[] = {
1062 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1065 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1066 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1067 MockRead reads
[] = {
1068 CreateMockRead(*resp
, 1, ASYNC
),
1069 MockRead(ASYNC
, 0, 2), // EOF
1072 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1074 AssertConnectSucceeds();
1076 Run(1); // Read EOF which will close the stream
1077 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1078 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1079 sock_
->Write(buf
.get(), buf
->size(), CompletionCallback()));
1082 // Calling Write() on a disconnected socket is an error
1083 TEST_P(SpdyProxyClientSocketTest
, WriteOnDisconnectedSocket
) {
1084 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1085 scoped_ptr
<SpdyFrame
> rst(
1086 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1087 MockWrite writes
[] = {
1088 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1091 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1092 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1093 MockRead reads
[] = {
1094 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1097 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1099 AssertConnectSucceeds();
1101 sock_
->Disconnect();
1103 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1104 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1105 sock_
->Write(buf
.get(), buf
->size(), CompletionCallback()));
1107 // Let the RST_STREAM write while |rst| is in-scope.
1108 base::MessageLoop::current()->RunUntilIdle();
1111 // If the socket is closed with a pending Write(), the callback
1112 // should be called with ERR_CONNECTION_CLOSED.
1113 TEST_P(SpdyProxyClientSocketTest
, WritePendingOnClose
) {
1114 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1115 MockWrite writes
[] = {
1116 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1117 MockWrite(ASYNC
, ERR_ABORTED
, 2),
1120 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1121 MockRead reads
[] = {
1122 CreateMockRead(*resp
, 1, ASYNC
),
1123 MockRead(ASYNC
, 0, 3), // EOF
1126 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1128 AssertConnectSucceeds();
1130 EXPECT_TRUE(sock_
->IsConnected());
1132 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1133 EXPECT_EQ(ERR_IO_PENDING
,
1134 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
1136 CloseSpdySession(ERR_ABORTED
, std::string());
1138 EXPECT_EQ(ERR_CONNECTION_CLOSED
, write_callback_
.WaitForResult());
1141 // If the socket is Disconnected with a pending Write(), the callback
1142 // should not be called.
1143 TEST_P(SpdyProxyClientSocketTest
, DisconnectWithWritePending
) {
1144 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1145 scoped_ptr
<SpdyFrame
> rst(
1146 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1147 MockWrite writes
[] = {
1148 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1149 MockWrite(SYNCHRONOUS
, 0, 3), // EOF
1152 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1153 MockRead reads
[] = {
1154 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 4), // EOF
1157 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1159 AssertConnectSucceeds();
1161 EXPECT_TRUE(sock_
->IsConnected());
1163 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1164 EXPECT_EQ(ERR_IO_PENDING
,
1165 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
1167 sock_
->Disconnect();
1169 EXPECT_FALSE(sock_
->IsConnected());
1170 EXPECT_FALSE(write_callback_
.have_result());
1172 // Let the RST_STREAM write while |rst| is in-scope.
1173 base::MessageLoop::current()->RunUntilIdle();
1176 // If the socket is Disconnected with a pending Read(), the callback
1177 // should not be called.
1178 TEST_P(SpdyProxyClientSocketTest
, DisconnectWithReadPending
) {
1179 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1180 scoped_ptr
<SpdyFrame
> rst(
1181 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1182 MockWrite writes
[] = {
1183 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1186 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1187 MockRead reads
[] = {
1188 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1191 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1193 AssertConnectSucceeds();
1195 EXPECT_TRUE(sock_
->IsConnected());
1197 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen1
));
1198 ASSERT_EQ(ERR_IO_PENDING
,
1199 sock_
->Read(buf
.get(), kLen1
, read_callback_
.callback()));
1201 sock_
->Disconnect();
1203 EXPECT_FALSE(sock_
->IsConnected());
1204 EXPECT_FALSE(read_callback_
.have_result());
1206 // Let the RST_STREAM write while |rst| is in-scope.
1207 base::MessageLoop::current()->RunUntilIdle();
1210 // If the socket is Reset when both a read and write are pending,
1211 // both should be called back.
1212 TEST_P(SpdyProxyClientSocketTest
, RstWithReadAndWritePending
) {
1213 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1214 MockWrite writes
[] = {
1215 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1216 MockWrite(ASYNC
, ERR_ABORTED
, 3),
1219 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1220 scoped_ptr
<SpdyFrame
> rst(
1221 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1222 MockRead reads
[] = {
1223 CreateMockRead(*resp
, 1, ASYNC
),
1224 CreateMockRead(*rst
, 2, ASYNC
),
1225 MockRead(ASYNC
, 0, 4) // EOF
1228 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1230 AssertConnectSucceeds();
1232 EXPECT_TRUE(sock_
->IsConnected());
1234 scoped_refptr
<IOBuffer
> read_buf(new IOBuffer(kLen1
));
1235 ASSERT_EQ(ERR_IO_PENDING
,
1236 sock_
->Read(read_buf
.get(), kLen1
, read_callback_
.callback()));
1238 scoped_refptr
<IOBufferWithSize
> write_buf(CreateBuffer(kMsg1
, kLen1
));
1242 write_buf
.get(), write_buf
->size(), write_callback_
.callback()));
1246 EXPECT_TRUE(sock_
.get());
1247 EXPECT_TRUE(read_callback_
.have_result());
1248 EXPECT_TRUE(write_callback_
.have_result());
1250 // Let the RST_STREAM write while |rst| is in-scope.
1251 base::MessageLoop::current()->RunUntilIdle();
1254 // Makes sure the proxy client socket's source gets the expected NetLog events
1255 // and only the expected NetLog events (No SpdySession events).
1256 TEST_P(SpdyProxyClientSocketTest
, NetLog
) {
1257 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1258 scoped_ptr
<SpdyFrame
> rst(
1259 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1260 MockWrite writes
[] = {
1261 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 3),
1264 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1265 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1266 MockRead reads
[] = {
1267 CreateMockRead(*resp
, 1, ASYNC
), CreateMockRead(*msg1
, 2, ASYNC
),
1268 MockRead(ASYNC
, 0, 4), // EOF
1271 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1273 AssertConnectSucceeds();
1275 Run(1); // SpdySession consumes the next read and sends it to
1276 // sock_ to be buffered.
1277 AssertSyncReadEquals(kMsg1
, kLen1
);
1279 NetLog::Source sock_source
= sock_
->NetLog().source();
1282 TestNetLogEntry::List entry_list
;
1283 net_log_
.GetEntriesForSource(sock_source
, &entry_list
);
1285 ASSERT_EQ(entry_list
.size(), 10u);
1286 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 0, NetLog::TYPE_SOCKET_ALIVE
));
1287 EXPECT_TRUE(LogContainsEvent(entry_list
, 1,
1288 NetLog::TYPE_HTTP2_PROXY_CLIENT_SESSION
,
1289 NetLog::PHASE_NONE
));
1290 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 2,
1291 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST
));
1292 EXPECT_TRUE(LogContainsEvent(entry_list
, 3,
1293 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
1294 NetLog::PHASE_NONE
));
1295 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 4,
1296 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST
));
1297 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 5,
1298 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS
));
1299 EXPECT_TRUE(LogContainsEvent(entry_list
, 6,
1300 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
1301 NetLog::PHASE_NONE
));
1302 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 7,
1303 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS
));
1304 EXPECT_TRUE(LogContainsEvent(entry_list
, 8,
1305 NetLog::TYPE_SOCKET_BYTES_RECEIVED
,
1306 NetLog::PHASE_NONE
));
1307 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 9, NetLog::TYPE_SOCKET_ALIVE
));
1309 // Let the RST_STREAM write while |rst| is in-scope.
1310 base::MessageLoop::current()->RunUntilIdle();
1313 // CompletionCallback that causes the SpdyProxyClientSocket to be
1314 // deleted when Run is invoked.
1315 class DeleteSockCallback
: public TestCompletionCallbackBase
{
1317 explicit DeleteSockCallback(scoped_ptr
<SpdyProxyClientSocket
>* sock
)
1319 callback_(base::Bind(&DeleteSockCallback::OnComplete
,
1320 base::Unretained(this))) {
1323 ~DeleteSockCallback() override
{}
1325 const CompletionCallback
& callback() const { return callback_
; }
1328 void OnComplete(int result
) {
1333 scoped_ptr
<SpdyProxyClientSocket
>* sock_
;
1334 CompletionCallback callback_
;
1336 DISALLOW_COPY_AND_ASSIGN(DeleteSockCallback
);
1339 // If the socket is Reset when both a read and write are pending, and the
1340 // read callback causes the socket to be deleted, the write callback should
1342 TEST_P(SpdyProxyClientSocketTest
, RstWithReadAndWritePendingDelete
) {
1343 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1344 MockWrite writes
[] = {
1345 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1346 MockWrite(ASYNC
, ERR_ABORTED
, 3),
1349 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1350 scoped_ptr
<SpdyFrame
> rst(
1351 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1352 MockRead reads
[] = {
1353 CreateMockRead(*resp
, 1, ASYNC
),
1354 CreateMockRead(*rst
, 2, ASYNC
),
1355 MockRead(ASYNC
, 0, 4), // EOF
1358 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1360 AssertConnectSucceeds();
1362 EXPECT_TRUE(sock_
->IsConnected());
1364 DeleteSockCallback
read_callback(&sock_
);
1366 scoped_refptr
<IOBuffer
> read_buf(new IOBuffer(kLen1
));
1367 ASSERT_EQ(ERR_IO_PENDING
,
1368 sock_
->Read(read_buf
.get(), kLen1
, read_callback
.callback()));
1370 scoped_refptr
<IOBufferWithSize
> write_buf(CreateBuffer(kMsg1
, kLen1
));
1374 write_buf
.get(), write_buf
->size(), write_callback_
.callback()));
1378 EXPECT_FALSE(sock_
.get());
1379 EXPECT_TRUE(read_callback
.have_result());
1380 EXPECT_FALSE(write_callback_
.have_result());
1382 // Let the RST_STREAM write while |rst| is in-scope.
1383 base::MessageLoop::current()->RunUntilIdle();