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
,
148 SpdyProxyClientSocketTest::SpdyProxyClientSocketTest()
149 : spdy_util_(GetParam()),
152 session_deps_(GetParam()),
153 connect_data_(SYNCHRONOUS
, OK
),
154 framer_(spdy_util_
.spdy_version(), false),
155 user_agent_(kUserAgent
),
157 proxy_host_port_(kProxyHost
, kProxyPort
),
158 endpoint_host_port_pair_(kOriginHost
, kOriginPort
),
159 proxy_(ProxyServer::SCHEME_HTTPS
, proxy_host_port_
),
160 endpoint_spdy_session_key_(endpoint_host_port_pair_
,
162 PRIVACY_MODE_DISABLED
) {
163 session_deps_
.net_log
= net_log_
.bound().net_log();
166 void SpdyProxyClientSocketTest::TearDown() {
167 if (session_
.get() != NULL
)
168 session_
->spdy_session_pool()->CloseAllSessions();
170 // Empty the current queue.
171 base::MessageLoop::current()->RunUntilIdle();
172 PlatformTest::TearDown();
175 void SpdyProxyClientSocketTest::Initialize(MockRead
* reads
,
178 size_t writes_count
) {
179 data_
.reset(new DeterministicSocketData(reads
, reads_count
,
180 writes
, writes_count
));
181 data_
->set_connect_data(connect_data_
);
184 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
186 session_deps_
.host_resolver
->set_synchronous_mode(true);
188 session_
= SpdySessionDependencies::SpdyCreateSessionDeterministic(
191 // Creates the SPDY session and stream.
193 CreateInsecureSpdySession(
194 session_
, endpoint_spdy_session_key_
, BoundNetLog());
195 base::WeakPtr
<SpdyStream
> spdy_stream(
196 CreateStreamSynchronously(
197 SPDY_BIDIRECTIONAL_STREAM
, spdy_session_
, url_
, LOWEST
,
199 ASSERT_TRUE(spdy_stream
.get() != NULL
);
201 // Create the SpdyProxyClientSocket.
202 sock_
.reset(new SpdyProxyClientSocket(
203 spdy_stream
, user_agent_
, endpoint_host_port_pair_
, proxy_host_port_
,
204 net_log_
.bound(), session_
->http_auth_cache(),
205 session_
->http_auth_handler_factory()));
208 scoped_refptr
<IOBufferWithSize
> SpdyProxyClientSocketTest::CreateBuffer(
209 const char* data
, int size
) {
210 scoped_refptr
<IOBufferWithSize
> buf(new IOBufferWithSize(size
));
211 memcpy(buf
->data(), data
, size
);
215 void SpdyProxyClientSocketTest::AssertConnectSucceeds() {
216 ASSERT_EQ(ERR_IO_PENDING
, sock_
->Connect(read_callback_
.callback()));
218 ASSERT_EQ(OK
, read_callback_
.WaitForResult());
221 void SpdyProxyClientSocketTest::AssertConnectFails(int result
) {
222 ASSERT_EQ(ERR_IO_PENDING
, sock_
->Connect(read_callback_
.callback()));
224 ASSERT_EQ(result
, read_callback_
.WaitForResult());
227 void SpdyProxyClientSocketTest::AssertConnectionEstablished() {
228 const HttpResponseInfo
* response
= sock_
->GetConnectResponseInfo();
229 ASSERT_TRUE(response
!= NULL
);
230 ASSERT_EQ(200, response
->headers
->response_code());
233 void SpdyProxyClientSocketTest::AssertSyncReadEquals(const char* data
,
235 scoped_refptr
<IOBuffer
> buf(new IOBuffer(len
));
236 ASSERT_EQ(len
, sock_
->Read(buf
.get(), len
, CompletionCallback()));
237 ASSERT_EQ(std::string(data
, len
), std::string(buf
->data(), len
));
238 ASSERT_TRUE(sock_
->IsConnected());
241 void SpdyProxyClientSocketTest::AssertAsyncReadEquals(const char* data
,
244 // Issue the read, which will be completed asynchronously
245 scoped_refptr
<IOBuffer
> buf(new IOBuffer(len
));
246 ASSERT_EQ(ERR_IO_PENDING
,
247 sock_
->Read(buf
.get(), len
, read_callback_
.callback()));
248 EXPECT_TRUE(sock_
->IsConnected());
251 EXPECT_TRUE(sock_
->IsConnected());
253 // Now the read will return
254 EXPECT_EQ(len
, read_callback_
.WaitForResult());
255 ASSERT_EQ(std::string(data
, len
), std::string(buf
->data(), len
));
258 void SpdyProxyClientSocketTest::AssertReadStarts(const char* data
,
261 // Issue the read, which will be completed asynchronously
262 read_buf_
= new IOBuffer(len
);
263 ASSERT_EQ(ERR_IO_PENDING
,
264 sock_
->Read(read_buf_
.get(), len
, read_callback_
.callback()));
265 EXPECT_TRUE(sock_
->IsConnected());
268 void SpdyProxyClientSocketTest::AssertReadReturns(const char* data
,
270 EXPECT_TRUE(sock_
->IsConnected());
272 // Now the read will return
273 EXPECT_EQ(len
, read_callback_
.WaitForResult());
274 ASSERT_EQ(std::string(data
, len
), std::string(read_buf_
->data(), len
));
277 void SpdyProxyClientSocketTest::AssertAsyncWriteSucceeds(const char* data
,
279 AssertWriteReturns(data
, len
, ERR_IO_PENDING
);
281 AssertWriteLength(len
);
284 void SpdyProxyClientSocketTest::AssertWriteReturns(const char* data
,
287 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(data
, len
));
289 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
292 void SpdyProxyClientSocketTest::AssertWriteLength(int len
) {
293 EXPECT_EQ(len
, write_callback_
.WaitForResult());
296 void SpdyProxyClientSocketTest::AssertAsyncWriteWithReadsSucceeds(
297 const char* data
, int len
, int num_reads
) {
298 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(data
, len
));
300 EXPECT_EQ(ERR_IO_PENDING
,
301 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
303 for (int i
= 0; i
< num_reads
; i
++) {
305 AssertSyncReadEquals(kMsg2
, kLen2
);
308 write_callback_
.WaitForResult();
311 void SpdyProxyClientSocketTest::PopulateConnectRequestIR(
312 SpdyHeaderBlock
* block
) {
313 (*block
)[spdy_util_
.GetMethodKey()] = "CONNECT";
314 if (spdy_util_
.spdy_version() == HTTP2
) {
315 (*block
)[spdy_util_
.GetHostKey()] = kOriginHostPort
;
317 (*block
)[spdy_util_
.GetPathKey()] = kOriginHostPort
;
318 (*block
)[spdy_util_
.GetHostKey()] = kOriginHost
;
320 (*block
)["user-agent"] = kUserAgent
;
321 spdy_util_
.MaybeAddVersionHeader(block
);
324 void SpdyProxyClientSocketTest::PopulateConnectReplyIR(SpdyHeaderBlock
* block
,
325 const char* status
) {
326 (*block
)[spdy_util_
.GetStatusKey()] = status
;
327 spdy_util_
.MaybeAddVersionHeader(block
);
330 // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
332 SpdyProxyClientSocketTest::ConstructConnectRequestFrame() {
333 SpdyHeaderBlock block
;
334 PopulateConnectRequestIR(&block
);
335 return spdy_util_
.ConstructSpdySyn(kStreamId
, block
, LOWEST
, false, false);
338 // Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes
339 // Proxy-Authorization headers.
340 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() {
341 SpdyHeaderBlock block
;
342 PopulateConnectRequestIR(&block
);
343 block
["proxy-authorization"] = "Basic Zm9vOmJhcg==";
344 return spdy_util_
.ConstructSpdySyn(kStreamId
, block
, LOWEST
, false, false);
347 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT.
348 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() {
349 SpdyHeaderBlock block
;
350 PopulateConnectReplyIR(&block
, "200");
351 SpdySynReplyIR
reply_ir(kStreamId
);
352 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
355 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT,
356 // including Proxy-Authenticate headers.
357 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() {
358 SpdyHeaderBlock block
;
359 PopulateConnectReplyIR(&block
, "407");
360 block
["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
361 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
364 // Constructs a SPDY SYN_REPLY frame with an HTTP 302 redirect.
365 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectRedirectReplyFrame() {
366 SpdyHeaderBlock block
;
367 PopulateConnectReplyIR(&block
, "302");
368 block
["location"] = kRedirectUrl
;
369 block
["set-cookie"] = "foo=bar";
370 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
373 // Constructs a SPDY SYN_REPLY frame with an HTTP 500 error.
374 SpdyFrame
* SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() {
375 SpdyHeaderBlock block
;
376 PopulateConnectReplyIR(&block
, "500");
377 return spdy_util_
.ConstructSpdyReply(kStreamId
, block
);
380 SpdyFrame
* SpdyProxyClientSocketTest::ConstructBodyFrame(
383 return framer_
.CreateDataFrame(kStreamId
, data
, length
, DATA_FLAG_NONE
);
386 // ----------- Connect
388 TEST_P(SpdyProxyClientSocketTest
, ConnectSendsCorrectRequest
) {
389 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
390 MockWrite writes
[] = {
391 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
394 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
396 CreateMockRead(*resp
, 1, ASYNC
),
397 MockRead(ASYNC
, 0, 2), // EOF
400 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
402 ASSERT_FALSE(sock_
->IsConnected());
404 AssertConnectSucceeds();
406 AssertConnectionEstablished();
409 TEST_P(SpdyProxyClientSocketTest
, ConnectWithAuthRequested
) {
410 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
411 MockWrite writes
[] = {
412 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
415 scoped_ptr
<SpdyFrame
> resp(ConstructConnectAuthReplyFrame());
417 CreateMockRead(*resp
, 1, ASYNC
),
418 MockRead(ASYNC
, 0, 2), // EOF
421 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
423 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED
);
425 const HttpResponseInfo
* response
= sock_
->GetConnectResponseInfo();
426 ASSERT_TRUE(response
!= NULL
);
427 ASSERT_EQ(407, response
->headers
->response_code());
430 TEST_P(SpdyProxyClientSocketTest
, ConnectWithAuthCredentials
) {
431 scoped_ptr
<SpdyFrame
> conn(ConstructConnectAuthRequestFrame());
432 MockWrite writes
[] = {
433 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
436 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
438 CreateMockRead(*resp
, 1, ASYNC
),
439 MockRead(ASYNC
, 0, 2), // EOF
442 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
445 AssertConnectSucceeds();
447 AssertConnectionEstablished();
450 TEST_P(SpdyProxyClientSocketTest
, ConnectRedirects
) {
451 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
452 scoped_ptr
<SpdyFrame
> rst(
453 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
454 MockWrite writes
[] = {
455 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
458 scoped_ptr
<SpdyFrame
> resp(ConstructConnectRedirectReplyFrame());
460 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
463 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
465 AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE
);
467 const HttpResponseInfo
* response
= sock_
->GetConnectResponseInfo();
468 ASSERT_TRUE(response
!= NULL
);
470 const HttpResponseHeaders
* headers
= response
->headers
.get();
471 ASSERT_EQ(302, headers
->response_code());
472 ASSERT_FALSE(headers
->HasHeader("set-cookie"));
473 ASSERT_TRUE(headers
->HasHeaderValue("content-length", "0"));
475 std::string location
;
476 ASSERT_TRUE(headers
->IsRedirect(&location
));
477 ASSERT_EQ(location
, kRedirectUrl
);
479 // Let the RST_STREAM write while |rst| is in-scope.
480 base::MessageLoop::current()->RunUntilIdle();
483 TEST_P(SpdyProxyClientSocketTest
, ConnectFails
) {
484 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
485 MockWrite writes
[] = {
486 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
489 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
491 MockRead(ASYNC
, 0, 1), // EOF
494 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
496 ASSERT_FALSE(sock_
->IsConnected());
498 AssertConnectFails(ERR_CONNECTION_CLOSED
);
500 ASSERT_FALSE(sock_
->IsConnected());
503 // ----------- WasEverUsed
505 TEST_P(SpdyProxyClientSocketTest
, WasEverUsedReturnsCorrectValues
) {
506 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
507 scoped_ptr
<SpdyFrame
> rst(
508 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
509 MockWrite writes
[] = {
510 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
513 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
515 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
518 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
520 EXPECT_FALSE(sock_
->WasEverUsed());
521 AssertConnectSucceeds();
522 EXPECT_TRUE(sock_
->WasEverUsed());
524 EXPECT_TRUE(sock_
->WasEverUsed());
526 // Let the RST_STREAM write while |rst| is in-scope.
527 base::MessageLoop::current()->RunUntilIdle();
530 // ----------- GetPeerAddress
532 TEST_P(SpdyProxyClientSocketTest
, GetPeerAddressReturnsCorrectValues
) {
533 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
534 MockWrite writes
[] = {
535 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
538 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
540 CreateMockRead(*resp
, 1, ASYNC
),
541 MockRead(ASYNC
, 0, 2), // EOF
544 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
547 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
549 AssertConnectSucceeds();
550 EXPECT_TRUE(sock_
->IsConnected());
551 EXPECT_EQ(OK
, sock_
->GetPeerAddress(&addr
));
555 EXPECT_FALSE(sock_
->IsConnected());
556 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
560 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
, sock_
->GetPeerAddress(&addr
));
565 TEST_P(SpdyProxyClientSocketTest
, WriteSendsDataInDataFrame
) {
566 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
567 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
568 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
569 MockWrite writes
[] = {
570 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
571 CreateMockWrite(*msg1
, 2, SYNCHRONOUS
),
572 CreateMockWrite(*msg2
, 3, SYNCHRONOUS
),
575 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
577 CreateMockRead(*resp
, 1, ASYNC
),
578 MockRead(ASYNC
, 0, 4), // EOF
581 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
583 AssertConnectSucceeds();
585 AssertAsyncWriteSucceeds(kMsg1
, kLen1
);
586 AssertAsyncWriteSucceeds(kMsg2
, kLen2
);
589 TEST_P(SpdyProxyClientSocketTest
, WriteSplitsLargeDataIntoMultipleFrames
) {
590 std::string
chunk_data(kMaxSpdyFrameChunkSize
, 'x');
591 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
592 scoped_ptr
<SpdyFrame
> chunk(ConstructBodyFrame(chunk_data
.data(),
593 chunk_data
.length()));
594 MockWrite writes
[] = {
595 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
596 CreateMockWrite(*chunk
, 2, SYNCHRONOUS
),
597 CreateMockWrite(*chunk
, 3, SYNCHRONOUS
),
598 CreateMockWrite(*chunk
, 4, SYNCHRONOUS
)
601 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
603 CreateMockRead(*resp
, 1, ASYNC
),
604 MockRead(ASYNC
, 0, 5), // EOF
607 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
609 AssertConnectSucceeds();
611 std::string
big_data(kMaxSpdyFrameChunkSize
* 3, 'x');
612 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(big_data
.data(),
615 EXPECT_EQ(ERR_IO_PENDING
,
616 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
619 EXPECT_EQ(buf
->size(), write_callback_
.WaitForResult());
624 TEST_P(SpdyProxyClientSocketTest
, ReadReadsDataInDataFrame
) {
625 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
626 MockWrite writes
[] = {
627 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
630 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
631 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
633 CreateMockRead(*resp
, 1, ASYNC
),
634 CreateMockRead(*msg1
, 2, ASYNC
),
635 MockRead(ASYNC
, 0, 3), // EOF
638 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
640 AssertConnectSucceeds();
642 Run(1); // SpdySession consumes the next read and sends it to
643 // sock_ to be buffered.
644 AssertSyncReadEquals(kMsg1
, kLen1
);
647 TEST_P(SpdyProxyClientSocketTest
, ReadDataFromBufferedFrames
) {
648 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
649 MockWrite writes
[] = {
650 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
653 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
654 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
655 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
657 CreateMockRead(*resp
, 1, ASYNC
),
658 CreateMockRead(*msg1
, 2, ASYNC
),
659 CreateMockRead(*msg2
, 3, ASYNC
),
660 MockRead(ASYNC
, 0, 4), // EOF
663 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
665 AssertConnectSucceeds();
667 Run(1); // SpdySession consumes the next read and sends it to
668 // sock_ to be buffered.
669 AssertSyncReadEquals(kMsg1
, kLen1
);
670 Run(1); // SpdySession consumes the next read and sends it to
671 // sock_ to be buffered.
672 AssertSyncReadEquals(kMsg2
, kLen2
);
675 TEST_P(SpdyProxyClientSocketTest
, ReadDataMultipleBufferedFrames
) {
676 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
677 MockWrite writes
[] = {
678 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
681 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
682 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
683 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
685 CreateMockRead(*resp
, 1, ASYNC
),
686 CreateMockRead(*msg1
, 2, ASYNC
),
687 CreateMockRead(*msg2
, 3, ASYNC
),
688 MockRead(ASYNC
, 0, 4), // EOF
691 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
693 AssertConnectSucceeds();
695 Run(2); // SpdySession consumes the next two reads and sends then to
696 // sock_ to be buffered.
697 AssertSyncReadEquals(kMsg1
, kLen1
);
698 AssertSyncReadEquals(kMsg2
, kLen2
);
701 TEST_P(SpdyProxyClientSocketTest
,
702 LargeReadWillMergeDataFromDifferentFrames
) {
703 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
704 MockWrite writes
[] = {
705 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
708 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
709 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
710 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
712 CreateMockRead(*resp
, 1, ASYNC
),
713 CreateMockRead(*msg3
, 2, ASYNC
),
714 CreateMockRead(*msg3
, 3, ASYNC
),
715 MockRead(ASYNC
, 0, 4), // EOF
718 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
720 AssertConnectSucceeds();
722 Run(2); // SpdySession consumes the next two reads and sends then to
723 // sock_ to be buffered.
724 // The payload from two data frames, each with kMsg3 will be combined
725 // together into a single read().
726 AssertSyncReadEquals(kMsg33
, kLen33
);
729 TEST_P(SpdyProxyClientSocketTest
, MultipleShortReadsThenMoreRead
) {
730 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
731 MockWrite writes
[] = {
732 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
735 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
736 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
737 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
738 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
740 CreateMockRead(*resp
, 1, ASYNC
),
741 CreateMockRead(*msg1
, 2, ASYNC
),
742 CreateMockRead(*msg3
, 3, ASYNC
),
743 CreateMockRead(*msg3
, 4, ASYNC
),
744 CreateMockRead(*msg2
, 5, ASYNC
),
745 MockRead(ASYNC
, 0, 6), // EOF
748 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
750 AssertConnectSucceeds();
752 Run(4); // SpdySession consumes the next four reads and sends then to
753 // sock_ to be buffered.
754 AssertSyncReadEquals(kMsg1
, kLen1
);
755 // The payload from two data frames, each with kMsg3 will be combined
756 // together into a single read().
757 AssertSyncReadEquals(kMsg33
, kLen33
);
758 AssertSyncReadEquals(kMsg2
, kLen2
);
761 TEST_P(SpdyProxyClientSocketTest
, ReadWillSplitDataFromLargeFrame
) {
762 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
763 MockWrite writes
[] = {
764 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
767 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
768 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
769 scoped_ptr
<SpdyFrame
> msg33(ConstructBodyFrame(kMsg33
, kLen33
));
770 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
772 CreateMockRead(*resp
, 1, ASYNC
),
773 CreateMockRead(*msg1
, 2, ASYNC
),
774 CreateMockRead(*msg33
, 3, ASYNC
),
775 MockRead(ASYNC
, 0, 4), // EOF
778 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
780 AssertConnectSucceeds();
782 Run(2); // SpdySession consumes the next two reads and sends then to
783 // sock_ to be buffered.
784 AssertSyncReadEquals(kMsg1
, kLen1
);
785 // The payload from the single large data frame will be read across
786 // two different reads.
787 AssertSyncReadEquals(kMsg3
, kLen3
);
788 AssertSyncReadEquals(kMsg3
, kLen3
);
791 TEST_P(SpdyProxyClientSocketTest
, MultipleReadsFromSameLargeFrame
) {
792 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
793 MockWrite writes
[] = {
794 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
797 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
798 scoped_ptr
<SpdyFrame
> msg333(ConstructBodyFrame(kMsg333
, kLen333
));
800 CreateMockRead(*resp
, 1, ASYNC
),
801 CreateMockRead(*msg333
, 2, ASYNC
),
802 MockRead(ASYNC
, 0, 3), // EOF
805 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
807 AssertConnectSucceeds();
809 Run(1); // SpdySession consumes the next read and sends it to
810 // sock_ to be buffered.
811 // The payload from the single large data frame will be read across
812 // two different reads.
813 AssertSyncReadEquals(kMsg33
, kLen33
);
815 // Now attempt to do a read of more data than remains buffered
816 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen33
));
817 ASSERT_EQ(kLen3
, sock_
->Read(buf
.get(), kLen33
, read_callback_
.callback()));
818 ASSERT_EQ(std::string(kMsg3
, kLen3
), std::string(buf
->data(), kLen3
));
819 ASSERT_TRUE(sock_
->IsConnected());
822 TEST_P(SpdyProxyClientSocketTest
, ReadAuthResponseBody
) {
823 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
824 MockWrite writes
[] = {
825 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
828 scoped_ptr
<SpdyFrame
> resp(ConstructConnectAuthReplyFrame());
829 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
830 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
832 CreateMockRead(*resp
, 1, ASYNC
),
833 CreateMockRead(*msg1
, 2, ASYNC
),
834 CreateMockRead(*msg2
, 3, ASYNC
),
835 MockRead(ASYNC
, 0, 4), // EOF
838 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
840 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED
);
842 Run(2); // SpdySession consumes the next two reads and sends then to
843 // sock_ to be buffered.
844 AssertSyncReadEquals(kMsg1
, kLen1
);
845 AssertSyncReadEquals(kMsg2
, kLen2
);
848 TEST_P(SpdyProxyClientSocketTest
, ReadErrorResponseBody
) {
849 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
850 MockWrite writes
[] = {
851 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
854 scoped_ptr
<SpdyFrame
> resp(ConstructConnectErrorReplyFrame());
855 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
856 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
858 CreateMockRead(*resp
, 1, ASYNC
),
859 CreateMockRead(*msg1
, 2, ASYNC
),
860 CreateMockRead(*msg2
, 3, ASYNC
),
861 MockRead(ASYNC
, 0, 4), // EOF
864 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
866 AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED
);
869 // ----------- Reads and Writes
871 TEST_P(SpdyProxyClientSocketTest
, AsyncReadAroundWrite
) {
872 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
873 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
874 MockWrite writes
[] = {
875 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
876 CreateMockWrite(*msg2
, 3, SYNCHRONOUS
),
879 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
880 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
881 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
883 CreateMockRead(*resp
, 1, ASYNC
),
884 CreateMockRead(*msg1
, 2, ASYNC
), // sync read
885 CreateMockRead(*msg3
, 4, ASYNC
), // async read
886 MockRead(ASYNC
, 0, 5), // EOF
889 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
891 AssertConnectSucceeds();
894 AssertSyncReadEquals(kMsg1
, kLen1
);
896 AssertReadStarts(kMsg3
, kLen3
);
897 // Read should block until after the write succeeds
899 AssertAsyncWriteSucceeds(kMsg2
, kLen2
); // Runs 1 step
901 ASSERT_FALSE(read_callback_
.have_result());
903 // Now the read will return
904 AssertReadReturns(kMsg3
, kLen3
);
907 TEST_P(SpdyProxyClientSocketTest
, AsyncWriteAroundReads
) {
908 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
909 scoped_ptr
<SpdyFrame
> msg2(ConstructBodyFrame(kMsg2
, kLen2
));
910 MockWrite writes
[] = {
911 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
912 CreateMockWrite(*msg2
, 4, ASYNC
),
915 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
916 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
917 scoped_ptr
<SpdyFrame
> msg3(ConstructBodyFrame(kMsg3
, kLen3
));
919 CreateMockRead(*resp
, 1, ASYNC
),
920 CreateMockRead(*msg1
, 2, ASYNC
),
921 CreateMockRead(*msg3
, 3, ASYNC
),
922 MockRead(ASYNC
, 0, 5), // EOF
925 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
927 AssertConnectSucceeds();
930 AssertSyncReadEquals(kMsg1
, kLen1
);
931 // Write should block until the read completes
932 AssertWriteReturns(kMsg2
, kLen2
, ERR_IO_PENDING
);
934 AssertAsyncReadEquals(kMsg3
, kLen3
);
936 ASSERT_FALSE(write_callback_
.have_result());
938 // Now the write will complete
940 AssertWriteLength(kLen2
);
943 // ----------- Reading/Writing on Closed socket
945 // Reading from an already closed socket should return 0
946 TEST_P(SpdyProxyClientSocketTest
, ReadOnClosedSocketReturnsZero
) {
947 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
948 MockWrite writes
[] = {
949 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
952 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
954 CreateMockRead(*resp
, 1, ASYNC
),
955 MockRead(ASYNC
, 0, 2), // EOF
958 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
960 AssertConnectSucceeds();
964 ASSERT_FALSE(sock_
->IsConnected());
965 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
966 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
967 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
968 ASSERT_FALSE(sock_
->IsConnectedAndIdle());
971 // Read pending when socket is closed should return 0
972 TEST_P(SpdyProxyClientSocketTest
, PendingReadOnCloseReturnsZero
) {
973 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
974 MockWrite writes
[] = {
975 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
978 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
980 CreateMockRead(*resp
, 1, ASYNC
),
981 MockRead(ASYNC
, 0, 2), // EOF
984 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
986 AssertConnectSucceeds();
988 AssertReadStarts(kMsg1
, kLen1
);
992 ASSERT_EQ(0, read_callback_
.WaitForResult());
995 // Reading from a disconnected socket is an error
996 TEST_P(SpdyProxyClientSocketTest
,
997 ReadOnDisconnectSocketReturnsNotConnected
) {
998 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
999 scoped_ptr
<SpdyFrame
> rst(
1000 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1001 MockWrite writes
[] = {
1002 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1005 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1006 MockRead reads
[] = {
1007 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1010 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1012 AssertConnectSucceeds();
1014 sock_
->Disconnect();
1016 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1017 sock_
->Read(NULL
, 1, CompletionCallback()));
1019 // Let the RST_STREAM write while |rst| is in-scope.
1020 base::MessageLoop::current()->RunUntilIdle();
1023 // Reading buffered data from an already closed socket should return
1024 // buffered data, then 0.
1025 TEST_P(SpdyProxyClientSocketTest
, ReadOnClosedSocketReturnsBufferedData
) {
1026 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1027 MockWrite writes
[] = {
1028 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1031 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1032 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1033 MockRead reads
[] = {
1034 CreateMockRead(*resp
, 1, ASYNC
),
1035 CreateMockRead(*msg1
, 2, ASYNC
),
1036 MockRead(ASYNC
, 0, 3), // EOF
1039 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1041 AssertConnectSucceeds();
1045 ASSERT_FALSE(sock_
->IsConnected());
1046 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen1
));
1047 ASSERT_EQ(kLen1
, sock_
->Read(buf
.get(), kLen1
, CompletionCallback()));
1048 ASSERT_EQ(std::string(kMsg1
, kLen1
), std::string(buf
->data(), kLen1
));
1050 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
1051 ASSERT_EQ(0, sock_
->Read(NULL
, 1, CompletionCallback()));
1052 sock_
->Disconnect();
1053 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1054 sock_
->Read(NULL
, 1, CompletionCallback()));
1057 // Calling Write() on a closed socket is an error
1058 TEST_P(SpdyProxyClientSocketTest
, WriteOnClosedStream
) {
1059 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1060 MockWrite writes
[] = {
1061 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1064 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1065 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1066 MockRead reads
[] = {
1067 CreateMockRead(*resp
, 1, ASYNC
),
1068 MockRead(ASYNC
, 0, 2), // EOF
1071 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1073 AssertConnectSucceeds();
1075 Run(1); // Read EOF which will close the stream
1076 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1077 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1078 sock_
->Write(buf
.get(), buf
->size(), CompletionCallback()));
1081 // Calling Write() on a disconnected socket is an error
1082 TEST_P(SpdyProxyClientSocketTest
, WriteOnDisconnectedSocket
) {
1083 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1084 scoped_ptr
<SpdyFrame
> rst(
1085 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1086 MockWrite writes
[] = {
1087 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1090 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1091 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1092 MockRead reads
[] = {
1093 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1096 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1098 AssertConnectSucceeds();
1100 sock_
->Disconnect();
1102 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1103 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED
,
1104 sock_
->Write(buf
.get(), buf
->size(), CompletionCallback()));
1106 // Let the RST_STREAM write while |rst| is in-scope.
1107 base::MessageLoop::current()->RunUntilIdle();
1110 // If the socket is closed with a pending Write(), the callback
1111 // should be called with ERR_CONNECTION_CLOSED.
1112 TEST_P(SpdyProxyClientSocketTest
, WritePendingOnClose
) {
1113 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1114 MockWrite writes
[] = {
1115 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1116 MockWrite(ASYNC
, ERR_ABORTED
, 2),
1119 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1120 MockRead reads
[] = {
1121 CreateMockRead(*resp
, 1, ASYNC
),
1122 MockRead(ASYNC
, 0, 3), // EOF
1125 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1127 AssertConnectSucceeds();
1129 EXPECT_TRUE(sock_
->IsConnected());
1131 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1132 EXPECT_EQ(ERR_IO_PENDING
,
1133 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
1135 CloseSpdySession(ERR_ABORTED
, std::string());
1137 EXPECT_EQ(ERR_CONNECTION_CLOSED
, write_callback_
.WaitForResult());
1140 // If the socket is Disconnected with a pending Write(), the callback
1141 // should not be called.
1142 TEST_P(SpdyProxyClientSocketTest
, DisconnectWithWritePending
) {
1143 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1144 scoped_ptr
<SpdyFrame
> rst(
1145 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1146 MockWrite writes
[] = {
1147 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1148 MockWrite(SYNCHRONOUS
, 0, 3), // EOF
1151 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1152 MockRead reads
[] = {
1153 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 4), // EOF
1156 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1158 AssertConnectSucceeds();
1160 EXPECT_TRUE(sock_
->IsConnected());
1162 scoped_refptr
<IOBufferWithSize
> buf(CreateBuffer(kMsg1
, kLen1
));
1163 EXPECT_EQ(ERR_IO_PENDING
,
1164 sock_
->Write(buf
.get(), buf
->size(), write_callback_
.callback()));
1166 sock_
->Disconnect();
1168 EXPECT_FALSE(sock_
->IsConnected());
1169 EXPECT_FALSE(write_callback_
.have_result());
1171 // Let the RST_STREAM write while |rst| is in-scope.
1172 base::MessageLoop::current()->RunUntilIdle();
1175 // If the socket is Disconnected with a pending Read(), the callback
1176 // should not be called.
1177 TEST_P(SpdyProxyClientSocketTest
, DisconnectWithReadPending
) {
1178 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1179 scoped_ptr
<SpdyFrame
> rst(
1180 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1181 MockWrite writes
[] = {
1182 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 2),
1185 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1186 MockRead reads
[] = {
1187 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3), // EOF
1190 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1192 AssertConnectSucceeds();
1194 EXPECT_TRUE(sock_
->IsConnected());
1196 scoped_refptr
<IOBuffer
> buf(new IOBuffer(kLen1
));
1197 ASSERT_EQ(ERR_IO_PENDING
,
1198 sock_
->Read(buf
.get(), kLen1
, read_callback_
.callback()));
1200 sock_
->Disconnect();
1202 EXPECT_FALSE(sock_
->IsConnected());
1203 EXPECT_FALSE(read_callback_
.have_result());
1205 // Let the RST_STREAM write while |rst| is in-scope.
1206 base::MessageLoop::current()->RunUntilIdle();
1209 // If the socket is Reset when both a read and write are pending,
1210 // both should be called back.
1211 TEST_P(SpdyProxyClientSocketTest
, RstWithReadAndWritePending
) {
1212 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1213 MockWrite writes
[] = {
1214 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1215 MockWrite(ASYNC
, ERR_ABORTED
, 3),
1218 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1219 scoped_ptr
<SpdyFrame
> rst(
1220 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1221 MockRead reads
[] = {
1222 CreateMockRead(*resp
, 1, ASYNC
),
1223 CreateMockRead(*rst
, 2, ASYNC
),
1224 MockRead(ASYNC
, 0, 4) // EOF
1227 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1229 AssertConnectSucceeds();
1231 EXPECT_TRUE(sock_
->IsConnected());
1233 scoped_refptr
<IOBuffer
> read_buf(new IOBuffer(kLen1
));
1234 ASSERT_EQ(ERR_IO_PENDING
,
1235 sock_
->Read(read_buf
.get(), kLen1
, read_callback_
.callback()));
1237 scoped_refptr
<IOBufferWithSize
> write_buf(CreateBuffer(kMsg1
, kLen1
));
1241 write_buf
.get(), write_buf
->size(), write_callback_
.callback()));
1245 EXPECT_TRUE(sock_
.get());
1246 EXPECT_TRUE(read_callback_
.have_result());
1247 EXPECT_TRUE(write_callback_
.have_result());
1249 // Let the RST_STREAM write while |rst| is in-scope.
1250 base::MessageLoop::current()->RunUntilIdle();
1253 // Makes sure the proxy client socket's source gets the expected NetLog events
1254 // and only the expected NetLog events (No SpdySession events).
1255 TEST_P(SpdyProxyClientSocketTest
, NetLog
) {
1256 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1257 scoped_ptr
<SpdyFrame
> rst(
1258 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1259 MockWrite writes
[] = {
1260 CreateMockWrite(*conn
, 0, SYNCHRONOUS
), CreateMockWrite(*rst
, 3),
1263 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1264 scoped_ptr
<SpdyFrame
> msg1(ConstructBodyFrame(kMsg1
, kLen1
));
1265 MockRead reads
[] = {
1266 CreateMockRead(*resp
, 1, ASYNC
), CreateMockRead(*msg1
, 2, ASYNC
),
1267 MockRead(ASYNC
, 0, 4), // EOF
1270 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1272 AssertConnectSucceeds();
1274 Run(1); // SpdySession consumes the next read and sends it to
1275 // sock_ to be buffered.
1276 AssertSyncReadEquals(kMsg1
, kLen1
);
1278 NetLog::Source sock_source
= sock_
->NetLog().source();
1281 TestNetLogEntry::List entry_list
;
1282 net_log_
.GetEntriesForSource(sock_source
, &entry_list
);
1284 ASSERT_EQ(entry_list
.size(), 10u);
1285 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 0, NetLog::TYPE_SOCKET_ALIVE
));
1286 EXPECT_TRUE(LogContainsEvent(entry_list
, 1,
1287 NetLog::TYPE_HTTP2_PROXY_CLIENT_SESSION
,
1288 NetLog::PHASE_NONE
));
1289 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 2,
1290 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST
));
1291 EXPECT_TRUE(LogContainsEvent(entry_list
, 3,
1292 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
1293 NetLog::PHASE_NONE
));
1294 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 4,
1295 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST
));
1296 EXPECT_TRUE(LogContainsBeginEvent(entry_list
, 5,
1297 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS
));
1298 EXPECT_TRUE(LogContainsEvent(entry_list
, 6,
1299 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
1300 NetLog::PHASE_NONE
));
1301 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 7,
1302 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS
));
1303 EXPECT_TRUE(LogContainsEvent(entry_list
, 8,
1304 NetLog::TYPE_SOCKET_BYTES_RECEIVED
,
1305 NetLog::PHASE_NONE
));
1306 EXPECT_TRUE(LogContainsEndEvent(entry_list
, 9, NetLog::TYPE_SOCKET_ALIVE
));
1308 // Let the RST_STREAM write while |rst| is in-scope.
1309 base::MessageLoop::current()->RunUntilIdle();
1312 // CompletionCallback that causes the SpdyProxyClientSocket to be
1313 // deleted when Run is invoked.
1314 class DeleteSockCallback
: public TestCompletionCallbackBase
{
1316 explicit DeleteSockCallback(scoped_ptr
<SpdyProxyClientSocket
>* sock
)
1318 callback_(base::Bind(&DeleteSockCallback::OnComplete
,
1319 base::Unretained(this))) {
1322 ~DeleteSockCallback() override
{}
1324 const CompletionCallback
& callback() const { return callback_
; }
1327 void OnComplete(int result
) {
1332 scoped_ptr
<SpdyProxyClientSocket
>* sock_
;
1333 CompletionCallback callback_
;
1335 DISALLOW_COPY_AND_ASSIGN(DeleteSockCallback
);
1338 // If the socket is Reset when both a read and write are pending, and the
1339 // read callback causes the socket to be deleted, the write callback should
1341 TEST_P(SpdyProxyClientSocketTest
, RstWithReadAndWritePendingDelete
) {
1342 scoped_ptr
<SpdyFrame
> conn(ConstructConnectRequestFrame());
1343 MockWrite writes
[] = {
1344 CreateMockWrite(*conn
, 0, SYNCHRONOUS
),
1345 MockWrite(ASYNC
, ERR_ABORTED
, 3),
1348 scoped_ptr
<SpdyFrame
> resp(ConstructConnectReplyFrame());
1349 scoped_ptr
<SpdyFrame
> rst(
1350 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
1351 MockRead reads
[] = {
1352 CreateMockRead(*resp
, 1, ASYNC
),
1353 CreateMockRead(*rst
, 2, ASYNC
),
1354 MockRead(ASYNC
, 0, 4), // EOF
1357 Initialize(reads
, arraysize(reads
), writes
, arraysize(writes
));
1359 AssertConnectSucceeds();
1361 EXPECT_TRUE(sock_
->IsConnected());
1363 DeleteSockCallback
read_callback(&sock_
);
1365 scoped_refptr
<IOBuffer
> read_buf(new IOBuffer(kLen1
));
1366 ASSERT_EQ(ERR_IO_PENDING
,
1367 sock_
->Read(read_buf
.get(), kLen1
, read_callback
.callback()));
1369 scoped_refptr
<IOBufferWithSize
> write_buf(CreateBuffer(kMsg1
, kLen1
));
1373 write_buf
.get(), write_buf
->size(), write_callback_
.callback()));
1377 EXPECT_FALSE(sock_
.get());
1378 EXPECT_TRUE(read_callback
.have_result());
1379 EXPECT_FALSE(write_callback_
.have_result());
1381 // Let the RST_STREAM write while |rst| is in-scope.
1382 base::MessageLoop::current()->RunUntilIdle();