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 virtual void TearDown();
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(kProtoDeprecatedSPDY2
,
146 kProtoSPDY3
, kProtoSPDY31
, kProtoSPDY4
));
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.
203 new SpdyProxyClientSocket(spdy_stream
, user_agent_
,
204 endpoint_host_port_pair_
, url_
,
205 proxy_host_port_
, net_log_
.bound(),
206 session_
->http_auth_cache(),
207 session_
->http_auth_handler_factory()));
210 scoped_refptr
<IOBufferWithSize
> SpdyProxyClientSocketTest::CreateBuffer(
211 const char* data
, int size
) {
212 scoped_refptr
<IOBufferWithSize
> buf(new IOBufferWithSize(size
));
213 memcpy(buf
->data(), data
, size
);
217 void SpdyProxyClientSocketTest::AssertConnectSucceeds() {
218 ASSERT_EQ(ERR_IO_PENDING
, sock_
->Connect(read_callback_
.callback()));
220 ASSERT_EQ(OK
, read_callback_
.WaitForResult());
223 void SpdyProxyClientSocketTest::AssertConnectFails(int result
) {
224 ASSERT_EQ(ERR_IO_PENDING
, sock_
->Connect(read_callback_
.callback()));
226 ASSERT_EQ(result
, read_callback_
.WaitForResult());
229 void SpdyProxyClientSocketTest::AssertConnectionEstablished() {
230 const HttpResponseInfo
* response
= sock_
->GetConnectResponseInfo();
231 ASSERT_TRUE(response
!= NULL
);
232 ASSERT_EQ(200, response
->headers
->response_code());
235 void SpdyProxyClientSocketTest::AssertSyncReadEquals(const char* data
,
237 scoped_refptr
<IOBuffer
> buf(new IOBuffer(len
));
238 ASSERT_EQ(len
, sock_
->Read(buf
.get(), len
, CompletionCallback()));
239 ASSERT_EQ(std::string(data
, len
), std::string(buf
->data(), len
));
240 ASSERT_TRUE(sock_
->IsConnected());
243 void SpdyProxyClientSocketTest::AssertAsyncReadEquals(const char* data
,
246 // Issue the read, which will be completed asynchronously
247 scoped_refptr
<IOBuffer
> buf(new IOBuffer(len
));
248 ASSERT_EQ(ERR_IO_PENDING
,
249 sock_
->Read(buf
.get(), len
, read_callback_
.callback()));
250 EXPECT_TRUE(sock_
->IsConnected());
253 EXPECT_TRUE(sock_
->IsConnected());
255 // Now the read will return
256 EXPECT_EQ(len
, read_callback_
.WaitForResult());
257 ASSERT_EQ(std::string(data
, len
), std::string(buf
->data(), len
));
260 void SpdyProxyClientSocketTest::AssertReadStarts(const char* data
,
263 // Issue the read, which will be completed asynchronously
264 read_buf_
= new IOBuffer(len
);
265 ASSERT_EQ(ERR_IO_PENDING
,
266 sock_
->Read(read_buf_
.get(), len
, read_callback_
.callback()));
267 EXPECT_TRUE(sock_
->IsConnected());
270 void SpdyProxyClientSocketTest::AssertReadReturns(const char* data
,
272 EXPECT_TRUE(sock_
->IsConnected());
274 // Now the read will return
275 EXPECT_EQ(len
, read_callback_
.WaitForResult());
276 ASSERT_EQ(std::string(data
, len
), std::string(read_buf_
->data(), len
));
279 void SpdyProxyClientSocketTest::AssertAsyncWriteSucceeds(const char* data
,
281 AssertWriteReturns(data
, len
, ERR_IO_PENDING
);
283 AssertWriteLength(len
);
286 void SpdyProxyClientSocketTest::AssertWriteReturns(const char* data
,
289 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(data
, len
));
291 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
294 void SpdyProxyClientSocketTest::AssertWriteLength(int len
) {
295 EXPECT_EQ(len
, write_callback_
.WaitForResult());
298 void SpdyProxyClientSocketTest::AssertAsyncWriteWithReadsSucceeds(
299 const char* data
, int len
, int num_reads
) {
300 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(data
, len
));
302 EXPECT_EQ(ERR_IO_PENDING
,
303 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
305 for (int i
= 0; i
< num_reads
; i
++) {
307 AssertSyncReadEquals(kMsg2
, kLen2
);
310 write_callback_
.WaitForResult();
313 void SpdyProxyClientSocketTest::PopulateConnectRequestIR(
314 SpdyHeaderBlock
* block
) {
315 (*block
)[spdy_util_
.GetMethodKey()] = "CONNECT";
316 (*block
)[spdy_util_
.GetPathKey()] = kOriginHostPort
;
317 (*block
)[spdy_util_
.GetHostKey()] = kOriginHost
;
318 (*block
)["user-agent"] = kUserAgent
;
319 spdy_util_
.MaybeAddVersionHeader(block
);
322 void SpdyProxyClientSocketTest::PopulateConnectReplyIR(SpdyHeaderBlock
* block
,
323 const char* status
) {
324 (*block
)[spdy_util_
.GetStatusKey()] = status
;
325 spdy_util_
.MaybeAddVersionHeader(block
);
328 // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
330 SpdyProxyClientSocketTest::ConstructConnectRequestFrame() {
331 SpdyHeaderBlock block
;
332 PopulateConnectRequestIR(&block
);
333 return spdy_util_
.ConstructSpdySyn(kStreamId
, block
, LOWEST
, false, false);
336 // Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes
337 // Proxy-Authorization headers.
338 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() {
339 SpdyHeaderBlock block
;
340 PopulateConnectRequestIR(&block
);
341 block
["proxy-authorization"] = "Basic Zm9vOmJhcg==";
342 return spdy_util_
.ConstructSpdySyn(kStreamId
, block
, LOWEST
, false, false);
345 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT.
346 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() {
347 SpdyHeaderBlock block
;
348 PopulateConnectReplyIR(&block
, "200");
349 SpdySynReplyIR
reply_ir(kStreamId
);
350 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
353 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT,
354 // including Proxy-Authenticate headers.
355 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() {
356 SpdyHeaderBlock block
;
357 PopulateConnectReplyIR(&block
, "407");
358 block
["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
359 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
362 // Constructs a SPDY SYN_REPLY frame with an HTTP 302 redirect.
363 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectRedirectReplyFrame() {
364 SpdyHeaderBlock block
;
365 PopulateConnectReplyIR(&block
, "302");
366 block
["location"] = kRedirectUrl
;
367 block
["set-cookie"] = "foo=bar";
368 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
371 // Constructs a SPDY SYN_REPLY frame with an HTTP 500 error.
372 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() {
373 SpdyHeaderBlock block
;
374 PopulateConnectReplyIR(&block
, "500");
375 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
378 SpdyFrame
* SpdyProxyClientSocketTest::ConstructBodyFrame(
381 return framer_
.CreateDataFrame(kStreamId
, data
, length
, DATA_FLAG_NONE
);
384 // ----------- Connect
386 TEST_P(SpdyProxyClientSocketTest
, ConnectSendsCorrectRequest
) {
387 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
388 MockWrite writes
[] = {
389 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
392 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
394 CreateMockRead(*resp
, 1, ASYNC
),
395 MockRead(ASYNC
, 0, 2), // EOF
398 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
400 ASSERT_FALSE(sock_
->IsConnected());
402 AssertConnectSucceeds();
404 AssertConnectionEstablished();
407 TEST_P(SpdyProxyClientSocketTest
, ConnectWithAuthRequested
) {
408 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
409 MockWrite writes
[] = {
410 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
413 scoped_ptr
<SpdyFrame
> resp(ConstructConnectAuthReplyFrame());
415 CreateMockRead(*resp
, 1, ASYNC
),
416 MockRead(ASYNC
, 0, 2), // EOF
419 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
421 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED
);
423 const HttpResponseInfo
* response
= sock_
->GetConnectResponseInfo();
424 ASSERT_TRUE(response
!= NULL
);
425 ASSERT_EQ(407, response
->headers
->response_code());
428 TEST_P(SpdyProxyClientSocketTest
, ConnectWithAuthCredentials
) {
429 scoped_ptr
<SpdyFrame
> conn(ConstructConnectAuthRequestFrame());
430 MockWrite writes
[] = {
431 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
434 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
436 CreateMockRead(*resp
, 1, ASYNC
),
437 MockRead(ASYNC
, 0, 2), // EOF
440 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
443 AssertConnectSucceeds();
445 AssertConnectionEstablished();
448 TEST_P(SpdyProxyClientSocketTest
, ConnectRedirects
) {
449 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
450 scoped_ptr
<SpdyFrame
> rst(
451 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
452 MockWrite writes
[] = {
453 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
456 scoped_ptr
<SpdyFrame
> resp(ConstructConnectRedirectReplyFrame());
458 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
461 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
463 AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE
);
465 const HttpResponseInfo
* response
= sock_
->GetConnectResponseInfo();
466 ASSERT_TRUE(response
!= NULL
);
468 const HttpResponseHeaders
* headers
= response
->headers
.get();
469 ASSERT_EQ(302, headers
->response_code());
470 ASSERT_FALSE(headers
->HasHeader("set-cookie"));
471 ASSERT_TRUE(headers
->HasHeaderValue("content-length", "0"));
473 std::string location
;
474 ASSERT_TRUE(headers
->IsRedirect(&location
));
475 ASSERT_EQ(location
, kRedirectUrl
);
477 // Let the RST_STREAM write while |rst| is in-scope.
478 base::MessageLoop::current()->RunUntilIdle();
481 TEST_P(SpdyProxyClientSocketTest
, ConnectFails
) {
482 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
483 MockWrite writes
[] = {
484 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
487 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
489 MockRead(ASYNC
, 0, 1), // EOF
492 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
494 ASSERT_FALSE(sock_
->IsConnected());
496 AssertConnectFails(ERR_CONNECTION_CLOSED
);
498 ASSERT_FALSE(sock_
->IsConnected());
501 // ----------- WasEverUsed
503 TEST_P(SpdyProxyClientSocketTest
, WasEverUsedReturnsCorrectValues
) {
504 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
505 scoped_ptr
<SpdyFrame
> rst(
506 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
507 MockWrite writes
[] = {
508 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
511 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
513 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
516 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
518 EXPECT_FALSE(sock_
->WasEverUsed());
519 AssertConnectSucceeds();
520 EXPECT_TRUE(sock_
->WasEverUsed());
522 EXPECT_TRUE(sock_
->WasEverUsed());
524 // Let the RST_STREAM write while |rst| is in-scope.
525 base::MessageLoop::current()->RunUntilIdle();
528 // ----------- GetPeerAddress
530 TEST_P(SpdyProxyClientSocketTest
, GetPeerAddressReturnsCorrectValues
) {
531 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
532 MockWrite writes
[] = {
533 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
536 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
538 CreateMockRead(*resp
, 1, ASYNC
),
539 MockRead(ASYNC
, 0, 2), // EOF
542 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
544 net::IPEndPoint addr
;
545 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
547 AssertConnectSucceeds();
548 EXPECT_TRUE(sock_
->IsConnected());
549 EXPECT_EQ(OK
, sock_
->GetPeerAddress(&addr
));
553 EXPECT_FALSE(sock_
->IsConnected());
554 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
558 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
563 TEST_P(SpdyProxyClientSocketTest
, WriteSendsDataInDataFrame
) {
564 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
565 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
566 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
567 MockWrite writes
[] = {
568 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
569 CreateMockWrite(*msg1
, 2, SYNCHRONOUS
),
570 CreateMockWrite(*msg2
, 3, SYNCHRONOUS
),
573 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
575 CreateMockRead(*resp
, 1, ASYNC
),
576 MockRead(ASYNC
, 0, 4), // EOF
579 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
581 AssertConnectSucceeds();
583 AssertAsyncWriteSucceeds(kMsg1
, kLen1
);
584 AssertAsyncWriteSucceeds(kMsg2
, kLen2
);
587 TEST_P(SpdyProxyClientSocketTest
, WriteSplitsLargeDataIntoMultipleFrames
) {
588 std::string
chunk_data(kMaxSpdyFrameChunkSize
, 'x');
589 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
590 scoped_ptr
<SpdyFrame
> chunk(ConstructBodyFrame(chunk_data
.data(),
591 chunk_data
.length()));
592 MockWrite writes
[] = {
593 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
594 CreateMockWrite(*chunk
, 2, SYNCHRONOUS
),
595 CreateMockWrite(*chunk
, 3, SYNCHRONOUS
),
596 CreateMockWrite(*chunk
, 4, SYNCHRONOUS
)
599 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
601 CreateMockRead(*resp
, 1, ASYNC
),
602 MockRead(ASYNC
, 0, 5), // EOF
605 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
607 AssertConnectSucceeds();
609 std::string
big_data(kMaxSpdyFrameChunkSize
* 3, 'x');
610 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(big_data
.data(),
613 EXPECT_EQ(ERR_IO_PENDING
,
614 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
617 EXPECT_EQ(buf
->size(), write_callback_
.WaitForResult());
622 TEST_P(SpdyProxyClientSocketTest
, ReadReadsDataInDataFrame
) {
623 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
624 MockWrite writes
[] = {
625 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
628 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
629 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
631 CreateMockRead(*resp
, 1, ASYNC
),
632 CreateMockRead(*msg1
, 2, ASYNC
),
633 MockRead(ASYNC
, 0, 3), // EOF
636 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
638 AssertConnectSucceeds();
640 Run(1); // SpdySession consumes the next read and sends it to
641 // sock_ to be buffered.
642 AssertSyncReadEquals(kMsg1
, kLen1
);
645 TEST_P(SpdyProxyClientSocketTest
, ReadDataFromBufferedFrames
) {
646 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
647 MockWrite writes
[] = {
648 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
651 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
652 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
653 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
655 CreateMockRead(*resp
, 1, ASYNC
),
656 CreateMockRead(*msg1
, 2, ASYNC
),
657 CreateMockRead(*msg2
, 3, ASYNC
),
658 MockRead(ASYNC
, 0, 4), // EOF
661 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
663 AssertConnectSucceeds();
665 Run(1); // SpdySession consumes the next read and sends it to
666 // sock_ to be buffered.
667 AssertSyncReadEquals(kMsg1
, kLen1
);
668 Run(1); // SpdySession consumes the next read and sends it to
669 // sock_ to be buffered.
670 AssertSyncReadEquals(kMsg2
, kLen2
);
673 TEST_P(SpdyProxyClientSocketTest
, ReadDataMultipleBufferedFrames
) {
674 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
675 MockWrite writes
[] = {
676 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
679 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
680 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
681 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
683 CreateMockRead(*resp
, 1, ASYNC
),
684 CreateMockRead(*msg1
, 2, ASYNC
),
685 CreateMockRead(*msg2
, 3, ASYNC
),
686 MockRead(ASYNC
, 0, 4), // EOF
689 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
691 AssertConnectSucceeds();
693 Run(2); // SpdySession consumes the next two reads and sends then to
694 // sock_ to be buffered.
695 AssertSyncReadEquals(kMsg1
, kLen1
);
696 AssertSyncReadEquals(kMsg2
, kLen2
);
699 TEST_P(SpdyProxyClientSocketTest
,
700 LargeReadWillMergeDataFromDifferentFrames
) {
701 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
702 MockWrite writes
[] = {
703 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
706 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
707 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
708 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
710 CreateMockRead(*resp
, 1, ASYNC
),
711 CreateMockRead(*msg3
, 2, ASYNC
),
712 CreateMockRead(*msg3
, 3, ASYNC
),
713 MockRead(ASYNC
, 0, 4), // EOF
716 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
718 AssertConnectSucceeds();
720 Run(2); // SpdySession consumes the next two reads and sends then to
721 // sock_ to be buffered.
722 // The payload from two data frames, each with kMsg3 will be combined
723 // together into a single read().
724 AssertSyncReadEquals(kMsg33
, kLen33
);
727 TEST_P(SpdyProxyClientSocketTest
, MultipleShortReadsThenMoreRead
) {
728 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
729 MockWrite writes
[] = {
730 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
733 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
734 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
735 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
736 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
738 CreateMockRead(*resp
, 1, ASYNC
),
739 CreateMockRead(*msg1
, 2, ASYNC
),
740 CreateMockRead(*msg3
, 3, ASYNC
),
741 CreateMockRead(*msg3
, 4, ASYNC
),
742 CreateMockRead(*msg2
, 5, ASYNC
),
743 MockRead(ASYNC
, 0, 6), // EOF
746 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
748 AssertConnectSucceeds();
750 Run(4); // SpdySession consumes the next four reads and sends then to
751 // sock_ to be buffered.
752 AssertSyncReadEquals(kMsg1
, kLen1
);
753 // The payload from two data frames, each with kMsg3 will be combined
754 // together into a single read().
755 AssertSyncReadEquals(kMsg33
, kLen33
);
756 AssertSyncReadEquals(kMsg2
, kLen2
);
759 TEST_P(SpdyProxyClientSocketTest
, ReadWillSplitDataFromLargeFrame
) {
760 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
761 MockWrite writes
[] = {
762 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
765 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
766 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
767 scoped_ptr
<SpdyFrame
> msg33(ConstructBodyFrame(kMsg33
, kLen33
));
768 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
770 CreateMockRead(*resp
, 1, ASYNC
),
771 CreateMockRead(*msg1
, 2, ASYNC
),
772 CreateMockRead(*msg33
, 3, ASYNC
),
773 MockRead(ASYNC
, 0, 4), // EOF
776 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
778 AssertConnectSucceeds();
780 Run(2); // SpdySession consumes the next two reads and sends then to
781 // sock_ to be buffered.
782 AssertSyncReadEquals(kMsg1
, kLen1
);
783 // The payload from the single large data frame will be read across
784 // two different reads.
785 AssertSyncReadEquals(kMsg3
, kLen3
);
786 AssertSyncReadEquals(kMsg3
, kLen3
);
789 TEST_P(SpdyProxyClientSocketTest
, MultipleReadsFromSameLargeFrame
) {
790 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
791 MockWrite writes
[] = {
792 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
795 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
796 scoped_ptr
<SpdyFrame
> msg333(ConstructBodyFrame(kMsg333
, kLen333
));
798 CreateMockRead(*resp
, 1, ASYNC
),
799 CreateMockRead(*msg333
, 2, ASYNC
),
800 MockRead(ASYNC
, 0, 3), // EOF
803 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
805 AssertConnectSucceeds();
807 Run(1); // SpdySession consumes the next read and sends it to
808 // sock_ to be buffered.
809 // The payload from the single large data frame will be read across
810 // two different reads.
811 AssertSyncReadEquals(kMsg33
, kLen33
);
813 // Now attempt to do a read of more data than remains buffered
814 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen33
));
815 ASSERT_EQ(kLen3
, sock_
->Read(buf
.get(), kLen33
, read_callback_
.callback()));
816 ASSERT_EQ(std::string(kMsg3
, kLen3
), std::string(buf
->data(), kLen3
));
817 ASSERT_TRUE(sock_
->IsConnected());
820 TEST_P(SpdyProxyClientSocketTest
, ReadAuthResponseBody
) {
821 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
822 MockWrite writes
[] = {
823 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
826 scoped_ptr
<SpdyFrame
> resp(ConstructConnectAuthReplyFrame());
827 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
828 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
830 CreateMockRead(*resp
, 1, ASYNC
),
831 CreateMockRead(*msg1
, 2, ASYNC
),
832 CreateMockRead(*msg2
, 3, ASYNC
),
833 MockRead(ASYNC
, 0, 4), // EOF
836 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
838 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED
);
840 Run(2); // SpdySession consumes the next two reads and sends then to
841 // sock_ to be buffered.
842 AssertSyncReadEquals(kMsg1
, kLen1
);
843 AssertSyncReadEquals(kMsg2
, kLen2
);
846 TEST_P(SpdyProxyClientSocketTest
, ReadErrorResponseBody
) {
847 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
848 MockWrite writes
[] = {
849 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
852 scoped_ptr
<SpdyFrame
> resp(ConstructConnectErrorReplyFrame());
853 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
854 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
856 CreateMockRead(*resp
, 1, ASYNC
),
857 CreateMockRead(*msg1
, 2, ASYNC
),
858 CreateMockRead(*msg2
, 3, ASYNC
),
859 MockRead(ASYNC
, 0, 4), // EOF
862 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
864 AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED
);
867 // ----------- Reads and Writes
869 TEST_P(SpdyProxyClientSocketTest
, AsyncReadAroundWrite
) {
870 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
871 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
872 MockWrite writes
[] = {
873 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
874 CreateMockWrite(*msg2
, 3, SYNCHRONOUS
),
877 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
878 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
879 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
881 CreateMockRead(*resp
, 1, ASYNC
),
882 CreateMockRead(*msg1
, 2, ASYNC
), // sync read
883 CreateMockRead(*msg3
, 4, ASYNC
), // async read
884 MockRead(ASYNC
, 0, 5), // EOF
887 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
889 AssertConnectSucceeds();
892 AssertSyncReadEquals(kMsg1
, kLen1
);
894 AssertReadStarts(kMsg3
, kLen3
);
895 // Read should block until after the write succeeds
897 AssertAsyncWriteSucceeds(kMsg2
, kLen2
); // Runs 1 step
899 ASSERT_FALSE(read_callback_
.have_result());
901 // Now the read will return
902 AssertReadReturns(kMsg3
, kLen3
);
905 TEST_P(SpdyProxyClientSocketTest
, AsyncWriteAroundReads
) {
906 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
907 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
908 MockWrite writes
[] = {
909 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
910 CreateMockWrite(*msg2
, 4, ASYNC
),
913 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
914 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
915 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
917 CreateMockRead(*resp
, 1, ASYNC
),
918 CreateMockRead(*msg1
, 2, ASYNC
),
919 CreateMockRead(*msg3
, 3, ASYNC
),
920 MockRead(ASYNC
, 0, 5), // EOF
923 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
925 AssertConnectSucceeds();
928 AssertSyncReadEquals(kMsg1
, kLen1
);
929 // Write should block until the read completes
930 AssertWriteReturns(kMsg2
, kLen2
, ERR_IO_PENDING
);
932 AssertAsyncReadEquals(kMsg3
, kLen3
);
934 ASSERT_FALSE(write_callback_
.have_result());
936 // Now the write will complete
938 AssertWriteLength(kLen2
);
941 // ----------- Reading/Writing on Closed socket
943 // Reading from an already closed socket should return 0
944 TEST_P(SpdyProxyClientSocketTest
, ReadOnClosedSocketReturnsZero
) {
945 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
946 MockWrite writes
[] = {
947 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
950 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
952 CreateMockRead(*resp
, 1, ASYNC
),
953 MockRead(ASYNC
, 0, 2), // EOF
956 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
958 AssertConnectSucceeds();
962 ASSERT_FALSE(sock_
->IsConnected());
963 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
964 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
965 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
966 ASSERT_FALSE(sock_
->IsConnectedAndIdle());
969 // Read pending when socket is closed should return 0
970 TEST_P(SpdyProxyClientSocketTest
, PendingReadOnCloseReturnsZero
) {
971 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
972 MockWrite writes
[] = {
973 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
976 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
978 CreateMockRead(*resp
, 1, ASYNC
),
979 MockRead(ASYNC
, 0, 2), // EOF
982 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
984 AssertConnectSucceeds();
986 AssertReadStarts(kMsg1
, kLen1
);
990 ASSERT_EQ(0, read_callback_
.WaitForResult());
993 // Reading from a disconnected socket is an error
994 TEST_P(SpdyProxyClientSocketTest
,
995 ReadOnDisconnectSocketReturnsNotConnected
) {
996 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
997 scoped_ptr
<SpdyFrame
> rst(
998 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
999 MockWrite writes
[] = {
1000 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1003 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1004 MockRead reads
[] = {
1005 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1008 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1010 AssertConnectSucceeds();
1012 sock_
->Disconnect();
1014 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1015 sock_
->Read(NULL
, 1, CompletionCallback()));
1017 // Let the RST_STREAM write while |rst| is in-scope.
1018 base::MessageLoop::current()->RunUntilIdle();
1021 // Reading buffered data from an already closed socket should return
1022 // buffered data, then 0.
1023 TEST_P(SpdyProxyClientSocketTest
, ReadOnClosedSocketReturnsBufferedData
) {
1024 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1025 MockWrite writes
[] = {
1026 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1029 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1030 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1031 MockRead reads
[] = {
1032 CreateMockRead(*resp
, 1, ASYNC
),
1033 CreateMockRead(*msg1
, 2, ASYNC
),
1034 MockRead(ASYNC
, 0, 3), // EOF
1037 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1039 AssertConnectSucceeds();
1043 ASSERT_FALSE(sock_
->IsConnected());
1044 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen1
));
1045 ASSERT_EQ(kLen1
, sock_
->Read(buf
.get(), kLen1
, CompletionCallback()));
1046 ASSERT_EQ(std::string(kMsg1
, kLen1
), std::string(buf
->data(), kLen1
));
1048 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
1049 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
1050 sock_
->Disconnect();
1051 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1052 sock_
->Read(NULL
, 1, CompletionCallback()));
1055 // Calling Write() on a closed socket is an error
1056 TEST_P(SpdyProxyClientSocketTest
, WriteOnClosedStream
) {
1057 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1058 MockWrite writes
[] = {
1059 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1062 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1063 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1064 MockRead reads
[] = {
1065 CreateMockRead(*resp
, 1, ASYNC
),
1066 MockRead(ASYNC
, 0, 2), // EOF
1069 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1071 AssertConnectSucceeds();
1073 Run(1); // Read EOF which will close the stream
1074 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1075 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1076 sock_
->Write(buf
.get(), buf
->size(), CompletionCallback()));
1079 // Calling Write() on a disconnected socket is an error
1080 TEST_P(SpdyProxyClientSocketTest
, WriteOnDisconnectedSocket
) {
1081 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1082 scoped_ptr
<SpdyFrame
> rst(
1083 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1084 MockWrite writes
[] = {
1085 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1088 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1089 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1090 MockRead reads
[] = {
1091 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1094 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1096 AssertConnectSucceeds();
1098 sock_
->Disconnect();
1100 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1101 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1102 sock_
->Write(buf
.get(), buf
->size(), CompletionCallback()));
1104 // Let the RST_STREAM write while |rst| is in-scope.
1105 base::MessageLoop::current()->RunUntilIdle();
1108 // If the socket is closed with a pending Write(), the callback
1109 // should be called with ERR_CONNECTION_CLOSED.
1110 TEST_P(SpdyProxyClientSocketTest
, WritePendingOnClose
) {
1111 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1112 MockWrite writes
[] = {
1113 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1114 MockWrite(ASYNC
, ERR_ABORTED
, 2),
1117 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1118 MockRead reads
[] = {
1119 CreateMockRead(*resp
, 1, ASYNC
),
1120 MockRead(ASYNC
, 0, 3), // EOF
1123 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1125 AssertConnectSucceeds();
1127 EXPECT_TRUE(sock_
->IsConnected());
1129 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1130 EXPECT_EQ(ERR_IO_PENDING
,
1131 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
1133 CloseSpdySession(ERR_ABORTED
, std::string());
1135 EXPECT_EQ(ERR_CONNECTION_CLOSED
, write_callback_
.WaitForResult());
1138 // If the socket is Disconnected with a pending Write(), the callback
1139 // should not be called.
1140 TEST_P(SpdyProxyClientSocketTest
, DisconnectWithWritePending
) {
1141 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1142 scoped_ptr
<SpdyFrame
> rst(
1143 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1144 MockWrite writes
[] = {
1145 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1146 MockWrite(SYNCHRONOUS
, 0, 3), // EOF
1149 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1150 MockRead reads
[] = {
1151 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 4), // EOF
1154 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1156 AssertConnectSucceeds();
1158 EXPECT_TRUE(sock_
->IsConnected());
1160 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1161 EXPECT_EQ(ERR_IO_PENDING
,
1162 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
1164 sock_
->Disconnect();
1166 EXPECT_FALSE(sock_
->IsConnected());
1167 EXPECT_FALSE(write_callback_
.have_result());
1169 // Let the RST_STREAM write while |rst| is in-scope.
1170 base::MessageLoop::current()->RunUntilIdle();
1173 // If the socket is Disconnected with a pending Read(), the callback
1174 // should not be called.
1175 TEST_P(SpdyProxyClientSocketTest
, DisconnectWithReadPending
) {
1176 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1177 scoped_ptr
<SpdyFrame
> rst(
1178 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1179 MockWrite writes
[] = {
1180 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1183 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1184 MockRead reads
[] = {
1185 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1188 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1190 AssertConnectSucceeds();
1192 EXPECT_TRUE(sock_
->IsConnected());
1194 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen1
));
1195 ASSERT_EQ(ERR_IO_PENDING
,
1196 sock_
->Read(buf
.get(), kLen1
, read_callback_
.callback()));
1198 sock_
->Disconnect();
1200 EXPECT_FALSE(sock_
->IsConnected());
1201 EXPECT_FALSE(read_callback_
.have_result());
1203 // Let the RST_STREAM write while |rst| is in-scope.
1204 base::MessageLoop::current()->RunUntilIdle();
1207 // If the socket is Reset when both a read and write are pending,
1208 // both should be called back.
1209 TEST_P(SpdyProxyClientSocketTest
, RstWithReadAndWritePending
) {
1210 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1211 MockWrite writes
[] = {
1212 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1213 MockWrite(ASYNC
, ERR_ABORTED
, 3),
1216 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1217 scoped_ptr
<SpdyFrame
> rst(
1218 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1219 MockRead reads
[] = {
1220 CreateMockRead(*resp
, 1, ASYNC
),
1221 CreateMockRead(*rst
, 2, ASYNC
),
1222 MockRead(ASYNC
, 0, 4) // EOF
1225 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1227 AssertConnectSucceeds();
1229 EXPECT_TRUE(sock_
->IsConnected());
1231 scoped_refptr
<IOBuffer
> read_buf(new IOBuffer(kLen1
));
1232 ASSERT_EQ(ERR_IO_PENDING
,
1233 sock_
->Read(read_buf
.get(), kLen1
, read_callback_
.callback()));
1235 scoped_refptr
<IOBufferWithSize
> write_buf(CreateBuffer(kMsg1
, kLen1
));
1239 write_buf
.get(), write_buf
->size(), write_callback_
.callback()));
1243 EXPECT_TRUE(sock_
.get());
1244 EXPECT_TRUE(read_callback_
.have_result());
1245 EXPECT_TRUE(write_callback_
.have_result());
1247 // Let the RST_STREAM write while |rst| is in-scope.
1248 base::MessageLoop::current()->RunUntilIdle();
1251 // Makes sure the proxy client socket's source gets the expected NetLog events
1252 // and only the expected NetLog events (No SpdySession events).
1253 TEST_P(SpdyProxyClientSocketTest
, NetLog
) {
1254 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1255 scoped_ptr
<SpdyFrame
> rst(
1256 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1257 MockWrite writes
[] = {
1258 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 3),
1261 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1262 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1263 MockRead reads
[] = {
1264 CreateMockRead(*resp
, 1, ASYNC
), CreateMockRead(*msg1
, 2, ASYNC
),
1265 MockRead(ASYNC
, 0, 4), // EOF
1268 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1270 AssertConnectSucceeds();
1272 Run(1); // SpdySession consumes the next read and sends it to
1273 // sock_ to be buffered.
1274 AssertSyncReadEquals(kMsg1
, kLen1
);
1276 NetLog::Source sock_source
= sock_
->NetLog().source();
1279 CapturingNetLog::CapturedEntryList entry_list
;
1280 net_log_
.GetEntriesForSource(sock_source
, &entry_list
);
1282 ASSERT_EQ(entry_list
.size(), 10u);
1283 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 0, NetLog::TYPE_SOCKET_ALIVE
));
1284 EXPECT_TRUE(LogContainsEvent(entry_list
, 1,
1285 NetLog::TYPE_SPDY_PROXY_CLIENT_SESSION
,
1286 NetLog::PHASE_NONE
));
1287 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 2,
1288 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST
));
1289 EXPECT_TRUE(LogContainsEvent(entry_list
, 3,
1290 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
1291 NetLog::PHASE_NONE
));
1292 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 4,
1293 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST
));
1294 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 5,
1295 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS
));
1296 EXPECT_TRUE(LogContainsEvent(entry_list
, 6,
1297 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
1298 NetLog::PHASE_NONE
));
1299 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 7,
1300 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS
));
1301 EXPECT_TRUE(LogContainsEvent(entry_list
, 8,
1302 NetLog::TYPE_SOCKET_BYTES_RECEIVED
,
1303 NetLog::PHASE_NONE
));
1304 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 9, NetLog::TYPE_SOCKET_ALIVE
));
1306 // Let the RST_STREAM write while |rst| is in-scope.
1307 base::MessageLoop::current()->RunUntilIdle();
1310 // CompletionCallback that causes the SpdyProxyClientSocket to be
1311 // deleted when Run is invoked.
1312 class DeleteSockCallback
: public TestCompletionCallbackBase
{
1314 explicit DeleteSockCallback(scoped_ptr
<SpdyProxyClientSocket
>* sock
)
1316 callback_(base::Bind(&DeleteSockCallback::OnComplete
,
1317 base::Unretained(this))) {
1320 virtual ~DeleteSockCallback() {
1323 const CompletionCallback
& callback() const { return callback_
; }
1326 void OnComplete(int result
) {
1331 scoped_ptr
<SpdyProxyClientSocket
>* sock_
;
1332 CompletionCallback callback_
;
1334 DISALLOW_COPY_AND_ASSIGN(DeleteSockCallback
);
1337 // If the socket is Reset when both a read and write are pending, and the
1338 // read callback causes the socket to be deleted, the write callback should
1340 TEST_P(SpdyProxyClientSocketTest
, RstWithReadAndWritePendingDelete
) {
1341 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1342 MockWrite writes
[] = {
1343 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1344 MockWrite(ASYNC
, ERR_ABORTED
, 3),
1347 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1348 scoped_ptr
<SpdyFrame
> rst(
1349 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1350 MockRead reads
[] = {
1351 CreateMockRead(*resp
, 1, ASYNC
),
1352 CreateMockRead(*rst
, 2, ASYNC
),
1353 MockRead(ASYNC
, 0, 4), // EOF
1356 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1358 AssertConnectSucceeds();
1360 EXPECT_TRUE(sock_
->IsConnected());
1362 DeleteSockCallback
read_callback(&sock_
);
1364 scoped_refptr
<IOBuffer
> read_buf(new IOBuffer(kLen1
));
1365 ASSERT_EQ(ERR_IO_PENDING
,
1366 sock_
->Read(read_buf
.get(), kLen1
, read_callback
.callback()));
1368 scoped_refptr
<IOBufferWithSize
> write_buf(CreateBuffer(kMsg1
, kLen1
));
1372 write_buf
.get(), write_buf
->size(), write_callback_
.callback()));
1376 EXPECT_FALSE(sock_
.get());
1377 EXPECT_TRUE(read_callback
.have_result());
1378 EXPECT_FALSE(write_callback_
.have_result());
1380 // Let the RST_STREAM write while |rst| is in-scope.
1381 base::MessageLoop::current()->RunUntilIdle();