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_session.h"
7 #include "base/base64.h"
9 #include "base/callback.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/test/histogram_tester.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/ip_endpoint.h"
15 #include "net/base/request_priority.h"
16 #include "net/base/test_data_directory.h"
17 #include "net/base/test_data_stream.h"
18 #include "net/log/test_net_log.h"
19 #include "net/log/test_net_log_entry.h"
20 #include "net/log/test_net_log_util.h"
21 #include "net/socket/client_socket_pool_manager.h"
22 #include "net/socket/next_proto.h"
23 #include "net/socket/socket_test_util.h"
24 #include "net/spdy/spdy_http_utils.h"
25 #include "net/spdy/spdy_session_pool.h"
26 #include "net/spdy/spdy_session_test_util.h"
27 #include "net/spdy/spdy_stream.h"
28 #include "net/spdy/spdy_stream_test_util.h"
29 #include "net/spdy/spdy_test_util_common.h"
30 #include "net/spdy/spdy_test_utils.h"
31 #include "net/test/cert_test_util.h"
32 #include "testing/platform_test.h"
38 const char kBodyData
[] = "Body data";
39 const size_t kBodyDataSize
= arraysize(kBodyData
);
40 const base::StringPiece
kBodyDataStringPiece(kBodyData
, kBodyDataSize
);
42 static base::TimeDelta g_time_delta
;
43 static base::TimeTicks g_time_now
;
45 base::TimeTicks
TheNearFuture() {
46 return base::TimeTicks::Now() + g_time_delta
;
49 base::TimeTicks
SlowReads() {
51 base::TimeDelta::FromMilliseconds(2 * kYieldAfterDurationMilliseconds
);
52 return base::TimeTicks::Now() + g_time_delta
;
55 base::TimeTicks
InstantaneousReads() {
61 class SpdySessionTest
: public PlatformTest
,
62 public ::testing::WithParamInterface
<NextProto
> {
64 // Functions used with RunResumeAfterUnstallTest().
66 void StallSessionOnly(SpdyStream
* stream
) { StallSessionSend(); }
68 void StallStreamOnly(SpdyStream
* stream
) { StallStreamSend(stream
); }
70 void StallSessionStream(SpdyStream
* stream
) {
72 StallStreamSend(stream
);
75 void StallStreamSession(SpdyStream
* stream
) {
76 StallStreamSend(stream
);
80 void UnstallSessionOnly(SpdyStream
* stream
, int32 delta_window_size
) {
81 UnstallSessionSend(delta_window_size
);
84 void UnstallStreamOnly(SpdyStream
* stream
, int32 delta_window_size
) {
85 UnstallStreamSend(stream
, delta_window_size
);
88 void UnstallSessionStream(SpdyStream
* stream
, int32 delta_window_size
) {
89 UnstallSessionSend(delta_window_size
);
90 UnstallStreamSend(stream
, delta_window_size
);
93 void UnstallStreamSession(SpdyStream
* stream
, int32 delta_window_size
) {
94 UnstallStreamSend(stream
, delta_window_size
);
95 UnstallSessionSend(delta_window_size
);
100 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
101 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
102 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
103 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
104 spdy_util_(GetParam()),
105 session_deps_(GetParam()),
106 spdy_session_pool_(nullptr),
107 test_url_(kDefaultURL
),
108 test_host_port_pair_(HostPortPair::FromURL(test_url_
)),
109 key_(test_host_port_pair_
,
110 ProxyServer::Direct(),
111 PRIVACY_MODE_DISABLED
) {}
113 virtual ~SpdySessionTest() {
114 // Important to restore the per-pool limit first, since the pool limit must
115 // always be greater than group limit, and the tests reduce both limits.
116 ClientSocketPoolManager::set_max_sockets_per_pool(
117 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
118 ClientSocketPoolManager::set_max_sockets_per_group(
119 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
122 void SetUp() override
{
123 g_time_delta
= base::TimeDelta();
124 g_time_now
= base::TimeTicks::Now();
125 session_deps_
.net_log
= log_
.bound().net_log();
128 void CreateNetworkSession() {
129 DCHECK(!http_session_
);
130 DCHECK(!spdy_session_pool_
);
132 SpdySessionDependencies::SpdyCreateSession(&session_deps_
);
133 spdy_session_pool_
= http_session_
->spdy_session_pool();
136 void CreateInsecureSpdySession() {
139 ::net::CreateInsecureSpdySession(http_session_
, key_
, log_
.bound());
142 void StallSessionSend() {
143 // Reduce the send window size to 0 to stall.
144 while (session_
->session_send_window_size_
> 0) {
145 session_
->DecreaseSendWindowSize(std::min(
146 kMaxSpdyFrameChunkSize
, session_
->session_send_window_size_
));
150 void UnstallSessionSend(int32 delta_window_size
) {
151 session_
->IncreaseSendWindowSize(delta_window_size
);
154 void StallStreamSend(SpdyStream
* stream
) {
155 // Reduce the send window size to 0 to stall.
156 while (stream
->send_window_size() > 0) {
157 stream
->DecreaseSendWindowSize(
158 std::min(kMaxSpdyFrameChunkSize
, stream
->send_window_size()));
162 void UnstallStreamSend(SpdyStream
* stream
, int32 delta_window_size
) {
163 stream
->IncreaseSendWindowSize(delta_window_size
);
166 void RunResumeAfterUnstallTest(
167 const base::Callback
<void(SpdyStream
*)>& stall_function
,
168 const base::Callback
<void(SpdyStream
*, int32
)>& unstall_function
);
170 // Original socket limits. Some tests set these. Safest to always restore
171 // them once each test has been run.
172 int old_max_group_sockets_
;
173 int old_max_pool_sockets_
;
175 SpdyTestUtil spdy_util_
;
176 SpdySessionDependencies session_deps_
;
177 scoped_refptr
<HttpNetworkSession
> http_session_
;
178 base::WeakPtr
<SpdySession
> session_
;
179 SpdySessionPool
* spdy_session_pool_
;
181 HostPortPair test_host_port_pair_
;
183 BoundTestNetLog log_
;
186 INSTANTIATE_TEST_CASE_P(NextProto
,
188 testing::Values(kProtoSPDY31
,
191 // Try to create a SPDY session that will fail during
192 // initialization. Nothing should blow up.
193 TEST_P(SpdySessionTest
, InitialReadError
) {
194 CreateNetworkSession();
196 session_
= TryCreateFakeSpdySessionExpectingFailure(spdy_session_pool_
, key_
,
197 ERR_CONNECTION_CLOSED
);
198 EXPECT_TRUE(session_
);
200 base::RunLoop().RunUntilIdle();
201 EXPECT_FALSE(session_
);
206 // A helper class that vends a callback that, when fired, destroys a
207 // given SpdyStreamRequest.
208 class StreamRequestDestroyingCallback
: public TestCompletionCallbackBase
{
210 StreamRequestDestroyingCallback() {}
212 ~StreamRequestDestroyingCallback() override
{}
214 void SetRequestToDestroy(scoped_ptr
<SpdyStreamRequest
> request
) {
215 request_
= request
.Pass();
218 CompletionCallback
MakeCallback() {
219 return base::Bind(&StreamRequestDestroyingCallback::OnComplete
,
220 base::Unretained(this));
224 void OnComplete(int result
) {
229 scoped_ptr
<SpdyStreamRequest
> request_
;
234 // Request kInitialMaxConcurrentStreams streams. Request two more
235 // streams, but have the callback for one destroy the second stream
236 // request. Close the session. Nothing should blow up. This is a
237 // regression test for http://crbug.com/250841 .
238 TEST_P(SpdySessionTest
, PendingStreamCancellingAnother
) {
239 session_deps_
.host_resolver
->set_synchronous_mode(true);
241 MockRead reads
[] = {MockRead(ASYNC
, 0, 0), };
243 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
244 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
246 CreateNetworkSession();
247 CreateInsecureSpdySession();
249 // Create the maximum number of concurrent streams.
250 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
251 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
252 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
253 ASSERT_TRUE(spdy_stream
!= nullptr);
256 SpdyStreamRequest request1
;
257 scoped_ptr
<SpdyStreamRequest
> request2(new SpdyStreamRequest
);
259 StreamRequestDestroyingCallback callback1
;
262 request1
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
263 MEDIUM
, BoundNetLog(), callback1
.MakeCallback()));
265 // |callback2| is never called.
266 TestCompletionCallback callback2
;
267 ASSERT_EQ(ERR_IO_PENDING
, request2
->StartRequest(
268 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
269 MEDIUM
, BoundNetLog(), callback2
.callback()));
271 callback1
.SetRequestToDestroy(request2
.Pass());
273 session_
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
275 EXPECT_EQ(ERR_ABORTED
, callback1
.WaitForResult());
278 // A session receiving a GOAWAY frame with no active streams should close.
279 TEST_P(SpdySessionTest
, GoAwayWithNoActiveStreams
) {
280 session_deps_
.host_resolver
->set_synchronous_mode(true);
282 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
284 CreateMockRead(*goaway
, 0),
286 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
287 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
289 CreateNetworkSession();
290 CreateInsecureSpdySession();
292 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
294 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
296 // Read and process the GOAWAY frame.
297 base::RunLoop().RunUntilIdle();
298 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
299 EXPECT_FALSE(session_
);
302 // A session receiving a GOAWAY frame immediately with no active
303 // streams should then close.
304 TEST_P(SpdySessionTest
, GoAwayImmediatelyWithNoActiveStreams
) {
305 session_deps_
.host_resolver
->set_synchronous_mode(true);
307 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
309 CreateMockRead(*goaway
, 0, SYNCHRONOUS
), MockRead(ASYNC
, 0, 1) // EOF
311 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
312 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
314 CreateNetworkSession();
316 session_
= TryCreateInsecureSpdySessionExpectingFailure(
317 http_session_
, key_
, ERR_CONNECTION_CLOSED
, BoundNetLog());
318 base::RunLoop().RunUntilIdle();
320 EXPECT_FALSE(session_
);
321 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
322 EXPECT_FALSE(data
.AllReadDataConsumed());
325 // A session receiving a GOAWAY frame with active streams should close
326 // when the last active stream is closed.
327 TEST_P(SpdySessionTest
, GoAwayWithActiveStreams
) {
328 session_deps_
.host_resolver
->set_synchronous_mode(true);
330 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
332 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
333 CreateMockRead(*goaway
, 3),
334 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
335 MockRead(ASYNC
, 0, 5) // EOF
337 scoped_ptr
<SpdyFrame
> req1(
338 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
339 scoped_ptr
<SpdyFrame
> req2(
340 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
341 MockWrite writes
[] = {
342 CreateMockWrite(*req1
, 0),
343 CreateMockWrite(*req2
, 1),
345 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
346 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
348 CreateNetworkSession();
349 CreateInsecureSpdySession();
351 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
353 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
354 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
355 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
356 spdy_stream1
->SetDelegate(&delegate1
);
358 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
359 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
360 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
361 spdy_stream2
->SetDelegate(&delegate2
);
363 scoped_ptr
<SpdyHeaderBlock
> headers(
364 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
365 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
367 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
368 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
369 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
370 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
372 base::RunLoop().RunUntilIdle();
374 EXPECT_EQ(1u, spdy_stream1
->stream_id());
375 EXPECT_EQ(3u, spdy_stream2
->stream_id());
377 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
379 // Read and process the GOAWAY frame.
381 base::RunLoop().RunUntilIdle();
383 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
385 EXPECT_FALSE(session_
->IsStreamActive(3));
386 EXPECT_FALSE(spdy_stream2
);
387 EXPECT_TRUE(session_
->IsStreamActive(1));
389 EXPECT_TRUE(session_
->IsGoingAway());
391 // Should close the session.
392 spdy_stream1
->Close();
393 EXPECT_FALSE(spdy_stream1
);
395 EXPECT_TRUE(session_
);
397 base::RunLoop().RunUntilIdle();
398 EXPECT_FALSE(session_
);
401 // Have a session receive two GOAWAY frames, with the last one causing
402 // the last active stream to be closed. The session should then be
403 // closed after the second GOAWAY frame.
404 TEST_P(SpdySessionTest
, GoAwayTwice
) {
405 session_deps_
.host_resolver
->set_synchronous_mode(true);
407 scoped_ptr
<SpdyFrame
> goaway1(spdy_util_
.ConstructSpdyGoAway(1));
408 scoped_ptr
<SpdyFrame
> goaway2(spdy_util_
.ConstructSpdyGoAway(0));
410 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
411 CreateMockRead(*goaway1
, 3),
412 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
413 CreateMockRead(*goaway2
, 5),
414 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
415 MockRead(ASYNC
, 0, 7) // EOF
417 scoped_ptr
<SpdyFrame
> req1(
418 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
419 scoped_ptr
<SpdyFrame
> req2(
420 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
421 MockWrite writes
[] = {
422 CreateMockWrite(*req1
, 0),
423 CreateMockWrite(*req2
, 1),
425 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
426 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
428 CreateNetworkSession();
429 CreateInsecureSpdySession();
431 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
433 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
434 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
435 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
436 spdy_stream1
->SetDelegate(&delegate1
);
438 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
439 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
440 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
441 spdy_stream2
->SetDelegate(&delegate2
);
443 scoped_ptr
<SpdyHeaderBlock
> headers(
444 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
445 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
447 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
448 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
449 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
450 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
452 base::RunLoop().RunUntilIdle();
454 EXPECT_EQ(1u, spdy_stream1
->stream_id());
455 EXPECT_EQ(3u, spdy_stream2
->stream_id());
457 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
459 // Read and process the first GOAWAY frame.
461 base::RunLoop().RunUntilIdle();
463 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
465 EXPECT_FALSE(session_
->IsStreamActive(3));
466 EXPECT_FALSE(spdy_stream2
);
467 EXPECT_TRUE(session_
->IsStreamActive(1));
468 EXPECT_TRUE(session_
->IsGoingAway());
470 // Read and process the second GOAWAY frame, which should close the
473 base::RunLoop().RunUntilIdle();
474 EXPECT_FALSE(session_
);
477 // Have a session with active streams receive a GOAWAY frame and then
478 // close it. It should handle the close properly (i.e., not try to
479 // make itself unavailable in its pool twice).
480 TEST_P(SpdySessionTest
, GoAwayWithActiveStreamsThenClose
) {
481 session_deps_
.host_resolver
->set_synchronous_mode(true);
483 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
485 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
486 CreateMockRead(*goaway
, 3),
487 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
488 MockRead(ASYNC
, 0, 5) // EOF
490 scoped_ptr
<SpdyFrame
> req1(
491 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
492 scoped_ptr
<SpdyFrame
> req2(
493 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
494 MockWrite writes
[] = {
495 CreateMockWrite(*req1
, 0),
496 CreateMockWrite(*req2
, 1),
498 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
499 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
501 CreateNetworkSession();
502 CreateInsecureSpdySession();
504 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
506 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
507 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
508 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
509 spdy_stream1
->SetDelegate(&delegate1
);
511 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
512 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
513 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
514 spdy_stream2
->SetDelegate(&delegate2
);
516 scoped_ptr
<SpdyHeaderBlock
> headers(
517 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
518 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
520 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
521 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
522 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
523 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
525 base::RunLoop().RunUntilIdle();
527 EXPECT_EQ(1u, spdy_stream1
->stream_id());
528 EXPECT_EQ(3u, spdy_stream2
->stream_id());
530 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
532 // Read and process the GOAWAY frame.
534 base::RunLoop().RunUntilIdle();
536 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
538 EXPECT_FALSE(session_
->IsStreamActive(3));
539 EXPECT_FALSE(spdy_stream2
);
540 EXPECT_TRUE(session_
->IsStreamActive(1));
541 EXPECT_TRUE(session_
->IsGoingAway());
543 session_
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
544 EXPECT_FALSE(spdy_stream1
);
547 base::RunLoop().RunUntilIdle();
548 EXPECT_FALSE(session_
);
551 // Process a joint read buffer which causes the session to begin draining, and
552 // then processes a GOAWAY. The session should gracefully drain. Regression test
553 // for crbug.com/379469
554 TEST_P(SpdySessionTest
, GoAwayWhileDraining
) {
555 session_deps_
.host_resolver
->set_synchronous_mode(true);
557 scoped_ptr
<SpdyFrame
> req(
558 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
559 MockWrite writes
[] = {
560 CreateMockWrite(*req
, 0),
563 scoped_ptr
<SpdyFrame
> resp(
564 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
565 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
566 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
567 size_t joint_size
= goaway
->size() * 2 + body
->size();
569 // Compose interleaved |goaway| and |body| frames into a single read.
570 scoped_ptr
<char[]> buffer(new char[joint_size
]);
573 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
574 out
+= goaway
->size();
575 memcpy(&buffer
[out
], body
->data(), body
->size());
577 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
578 out
+= goaway
->size();
579 ASSERT_EQ(out
, joint_size
);
581 SpdyFrame
joint_frames(buffer
.get(), joint_size
, false);
584 CreateMockRead(*resp
, 1), CreateMockRead(joint_frames
, 2),
585 MockRead(ASYNC
, 0, 3) // EOF
588 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
589 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
591 CreateNetworkSession();
592 CreateInsecureSpdySession();
594 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
595 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
596 test::StreamDelegateDoNothing
delegate(spdy_stream
);
597 spdy_stream
->SetDelegate(&delegate
);
599 scoped_ptr
<SpdyHeaderBlock
> headers(
600 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
601 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
602 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
604 base::RunLoop().RunUntilIdle();
606 // Stream and session closed gracefully.
607 EXPECT_TRUE(delegate
.StreamIsClosed());
608 EXPECT_EQ(OK
, delegate
.WaitForClose());
609 EXPECT_EQ(kUploadData
, delegate
.TakeReceivedData());
610 EXPECT_FALSE(session_
);
613 // Try to create a stream after receiving a GOAWAY frame. It should
615 TEST_P(SpdySessionTest
, CreateStreamAfterGoAway
) {
616 session_deps_
.host_resolver
->set_synchronous_mode(true);
618 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
620 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
621 CreateMockRead(*goaway
, 2),
622 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
623 MockRead(ASYNC
, 0, 4) // EOF
625 scoped_ptr
<SpdyFrame
> req(
626 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
627 MockWrite writes
[] = {
628 CreateMockWrite(*req
, 0),
630 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
631 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
633 CreateNetworkSession();
634 CreateInsecureSpdySession();
636 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
638 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
639 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
640 test::StreamDelegateDoNothing
delegate(spdy_stream
);
641 spdy_stream
->SetDelegate(&delegate
);
643 scoped_ptr
<SpdyHeaderBlock
> headers(
644 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
645 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
646 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
648 base::RunLoop().RunUntilIdle();
650 EXPECT_EQ(1u, spdy_stream
->stream_id());
652 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
654 // Read and process the GOAWAY frame.
656 base::RunLoop().RunUntilIdle();
658 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
659 EXPECT_TRUE(session_
->IsStreamActive(1));
661 SpdyStreamRequest stream_request
;
662 int rv
= stream_request
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
,
663 test_url_
, MEDIUM
, BoundNetLog(),
664 CompletionCallback());
665 EXPECT_EQ(ERR_FAILED
, rv
);
667 EXPECT_TRUE(session_
);
669 base::RunLoop().RunUntilIdle();
670 EXPECT_FALSE(session_
);
673 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
674 // the stream being refused.
675 TEST_P(SpdySessionTest
, SynStreamAfterGoAway
) {
676 session_deps_
.host_resolver
->set_synchronous_mode(true);
678 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
679 scoped_ptr
<SpdyFrame
> push(
680 spdy_util_
.ConstructSpdyPush(nullptr, 0, 2, 1, kDefaultURL
));
682 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
683 CreateMockRead(*goaway
, 2),
684 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
685 CreateMockRead(*push
, 4),
686 MockRead(ASYNC
, 0, 6) // EOF
688 scoped_ptr
<SpdyFrame
> req(
689 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
690 scoped_ptr
<SpdyFrame
> rst(
691 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
692 MockWrite writes
[] = {CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5)};
693 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
694 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
696 CreateNetworkSession();
697 CreateInsecureSpdySession();
699 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
701 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
702 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
703 test::StreamDelegateDoNothing
delegate(spdy_stream
);
704 spdy_stream
->SetDelegate(&delegate
);
706 scoped_ptr
<SpdyHeaderBlock
> headers(
707 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
708 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
709 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
711 base::RunLoop().RunUntilIdle();
713 EXPECT_EQ(1u, spdy_stream
->stream_id());
715 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
717 // Read and process the GOAWAY frame.
719 base::RunLoop().RunUntilIdle();
721 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
722 EXPECT_TRUE(session_
->IsStreamActive(1));
724 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
727 base::RunLoop().RunUntilIdle();
728 EXPECT_FALSE(session_
);
731 // A session observing a network change with active streams should close
732 // when the last active stream is closed.
733 TEST_P(SpdySessionTest
, NetworkChangeWithActiveStreams
) {
734 session_deps_
.host_resolver
->set_synchronous_mode(true);
737 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
739 scoped_ptr
<SpdyFrame
> req1(
740 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
741 MockWrite writes
[] = {
742 CreateMockWrite(*req1
, 0),
744 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
745 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
747 CreateNetworkSession();
748 CreateInsecureSpdySession();
750 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
752 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
753 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
754 test::StreamDelegateDoNothing
delegate(spdy_stream
);
755 spdy_stream
->SetDelegate(&delegate
);
757 scoped_ptr
<SpdyHeaderBlock
> headers(
758 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
760 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
761 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
763 base::RunLoop().RunUntilIdle();
765 EXPECT_EQ(1u, spdy_stream
->stream_id());
767 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
769 spdy_session_pool_
->OnIPAddressChanged();
771 // The SpdySessionPool behavior differs based on how the OSs reacts to
772 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
773 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
774 // For OSs where the TCP connections will close upon relevant network
775 // changes, SpdySessionPool doesn't need to force them to close, so in these
776 // cases verify the session has become unavailable but remains open and the
777 // pre-existing stream is still active.
778 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
780 EXPECT_TRUE(session_
->IsGoingAway());
782 EXPECT_TRUE(session_
->IsStreamActive(1));
784 // Should close the session.
785 spdy_stream
->Close();
787 EXPECT_FALSE(spdy_stream
);
790 base::RunLoop().RunUntilIdle();
791 EXPECT_FALSE(session_
);
794 TEST_P(SpdySessionTest
, ClientPing
) {
795 session_deps_
.enable_ping
= true;
796 session_deps_
.host_resolver
->set_synchronous_mode(true);
798 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(1, true));
800 CreateMockRead(*read_ping
, 1),
801 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
802 MockRead(ASYNC
, 0, 3) // EOF
804 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
805 MockWrite writes
[] = {
806 CreateMockWrite(*write_ping
, 0),
808 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
809 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
811 CreateNetworkSession();
812 CreateInsecureSpdySession();
814 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
815 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
816 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
817 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
818 spdy_stream1
->SetDelegate(&delegate
);
820 base::TimeTicks before_ping_time
= base::TimeTicks::Now();
822 session_
->set_connection_at_risk_of_loss_time(
823 base::TimeDelta::FromSeconds(-1));
824 session_
->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
826 session_
->SendPrefacePingIfNoneInFlight();
828 base::RunLoop().RunUntilIdle();
830 session_
->CheckPingStatus(before_ping_time
);
832 EXPECT_EQ(0, session_
->pings_in_flight());
833 EXPECT_GE(session_
->next_ping_id(), 1U);
834 EXPECT_FALSE(session_
->check_ping_status_pending());
835 EXPECT_GE(session_
->last_activity_time(), before_ping_time
);
838 base::RunLoop().RunUntilIdle();
840 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
842 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
843 EXPECT_FALSE(session_
);
846 TEST_P(SpdySessionTest
, ServerPing
) {
847 session_deps_
.host_resolver
->set_synchronous_mode(true);
849 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(2, false));
851 CreateMockRead(*read_ping
),
852 MockRead(SYNCHRONOUS
, 0, 0) // EOF
854 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(2, true));
855 MockWrite writes
[] = {
856 CreateMockWrite(*write_ping
),
858 StaticSocketDataProvider
data(
859 reads
, arraysize(reads
), writes
, arraysize(writes
));
860 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
862 CreateNetworkSession();
863 CreateInsecureSpdySession();
865 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
866 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
867 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
868 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
869 spdy_stream1
->SetDelegate(&delegate
);
871 // Flush the read completion task.
872 base::RunLoop().RunUntilIdle();
874 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
876 EXPECT_FALSE(session_
);
877 EXPECT_FALSE(spdy_stream1
);
880 // Cause a ping to be sent out while producing a write. The write loop
881 // should handle this properly, i.e. another DoWriteLoop task should
882 // not be posted. This is a regression test for
883 // http://crbug.com/261043 .
884 TEST_P(SpdySessionTest
, PingAndWriteLoop
) {
885 session_deps_
.enable_ping
= true;
886 session_deps_
.time_func
= TheNearFuture
;
888 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
889 scoped_ptr
<SpdyFrame
> req(
890 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
891 MockWrite writes
[] = {
892 CreateMockWrite(*req
, 0),
893 CreateMockWrite(*write_ping
, 1),
897 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
900 session_deps_
.host_resolver
->set_synchronous_mode(true);
902 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
903 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
905 CreateNetworkSession();
906 CreateInsecureSpdySession();
908 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
909 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
910 test::StreamDelegateDoNothing
delegate(spdy_stream
);
911 spdy_stream
->SetDelegate(&delegate
);
913 scoped_ptr
<SpdyHeaderBlock
> headers(
914 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
915 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
917 // Shift time so that a ping will be sent out.
918 g_time_delta
= base::TimeDelta::FromSeconds(11);
920 base::RunLoop().RunUntilIdle();
921 session_
->CloseSessionOnError(ERR_ABORTED
, "Aborting");
924 base::RunLoop().RunUntilIdle();
925 EXPECT_FALSE(session_
);
928 TEST_P(SpdySessionTest
, StreamIdSpaceExhausted
) {
929 const SpdyStreamId kLastStreamId
= 0x7fffffff;
930 session_deps_
.host_resolver
->set_synchronous_mode(true);
932 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
933 // fixed to allow for two stream ID assignments, and three concurrent
934 // streams. Four streams are started, and two are activated. Verify the
935 // session goes away, and that the created (but not activated) and
936 // stalled streams are aborted. Also verify the activated streams complete,
937 // at which point the session closes.
939 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyGet(
940 nullptr, 0, false, kLastStreamId
- 2, MEDIUM
, true));
941 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyGet(
942 nullptr, 0, false, kLastStreamId
, MEDIUM
, true));
944 MockWrite writes
[] = {
945 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
948 scoped_ptr
<SpdyFrame
> resp1(
949 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId
- 2));
950 scoped_ptr
<SpdyFrame
> resp2(
951 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId
));
953 scoped_ptr
<SpdyFrame
> body1(
954 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
- 2, true));
955 scoped_ptr
<SpdyFrame
> body2(
956 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
, true));
959 CreateMockRead(*resp1
, 2),
960 CreateMockRead(*resp2
, 3),
961 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
962 CreateMockRead(*body1
, 5),
963 CreateMockRead(*body2
, 6),
964 MockRead(ASYNC
, 0, 7) // EOF
967 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
968 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
970 CreateNetworkSession();
971 CreateInsecureSpdySession();
973 // Fix stream_hi_water_mark_ to allow for two stream activations.
974 session_
->stream_hi_water_mark_
= kLastStreamId
- 2;
975 // Fix max_concurrent_streams to allow for three stream creations.
976 session_
->max_concurrent_streams_
= 3;
978 // Create three streams synchronously, and begin a fourth (which is stalled).
979 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
980 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
981 test::StreamDelegateDoNothing
delegate1(stream1
);
982 stream1
->SetDelegate(&delegate1
);
984 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
985 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
986 test::StreamDelegateDoNothing
delegate2(stream2
);
987 stream2
->SetDelegate(&delegate2
);
989 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
990 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
991 test::StreamDelegateDoNothing
delegate3(stream3
);
992 stream3
->SetDelegate(&delegate3
);
994 SpdyStreamRequest request4
;
995 TestCompletionCallback callback4
;
998 request4
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
,
999 MEDIUM
, BoundNetLog(), callback4
.callback()));
1001 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1002 EXPECT_EQ(0u, session_
->num_active_streams());
1003 EXPECT_EQ(3u, session_
->num_created_streams());
1004 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(MEDIUM
));
1006 // Activate stream 1. One ID remains available.
1007 stream1
->SendRequestHeaders(
1008 scoped_ptr
<SpdyHeaderBlock
>(
1009 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
)),
1010 NO_MORE_DATA_TO_SEND
);
1011 base::RunLoop().RunUntilIdle();
1013 EXPECT_EQ(kLastStreamId
- 2u, stream1
->stream_id());
1014 EXPECT_EQ(1u, session_
->num_active_streams());
1015 EXPECT_EQ(2u, session_
->num_created_streams());
1016 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(MEDIUM
));
1018 // Activate stream 2. ID space is exhausted.
1019 stream2
->SendRequestHeaders(
1020 scoped_ptr
<SpdyHeaderBlock
>(
1021 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
)),
1022 NO_MORE_DATA_TO_SEND
);
1023 base::RunLoop().RunUntilIdle();
1025 // Active streams remain active.
1026 EXPECT_EQ(kLastStreamId
, stream2
->stream_id());
1027 EXPECT_EQ(2u, session_
->num_active_streams());
1029 // Session is going away. Created and stalled streams were aborted.
1030 EXPECT_EQ(SpdySession::STATE_GOING_AWAY
, session_
->availability_state_
);
1031 EXPECT_EQ(ERR_ABORTED
, delegate3
.WaitForClose());
1032 EXPECT_EQ(ERR_ABORTED
, callback4
.WaitForResult());
1033 EXPECT_EQ(0u, session_
->num_created_streams());
1034 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(MEDIUM
));
1036 // Read responses on remaining active streams.
1037 data
.CompleteRead();
1038 base::RunLoop().RunUntilIdle();
1039 EXPECT_EQ(OK
, delegate1
.WaitForClose());
1040 EXPECT_EQ(kUploadData
, delegate1
.TakeReceivedData());
1041 EXPECT_EQ(OK
, delegate2
.WaitForClose());
1042 EXPECT_EQ(kUploadData
, delegate2
.TakeReceivedData());
1044 // Session was destroyed.
1045 EXPECT_FALSE(session_
);
1048 // Verifies that an unstalled pending stream creation racing with a new stream
1049 // creation doesn't violate the maximum stream concurrency. Regression test for
1050 // crbug.com/373858.
1051 TEST_P(SpdySessionTest
, UnstallRacesWithStreamCreation
) {
1052 session_deps_
.host_resolver
->set_synchronous_mode(true);
1054 MockRead reads
[] = {
1055 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1058 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1059 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1061 CreateNetworkSession();
1062 CreateInsecureSpdySession();
1064 // Fix max_concurrent_streams to allow for one open stream.
1065 session_
->max_concurrent_streams_
= 1;
1067 // Create two streams: one synchronously, and one which stalls.
1068 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
1069 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1071 SpdyStreamRequest request2
;
1072 TestCompletionCallback callback2
;
1075 request2
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
,
1076 MEDIUM
, BoundNetLog(), callback2
.callback()));
1078 EXPECT_EQ(1u, session_
->num_created_streams());
1079 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(MEDIUM
));
1081 // Cancel the first stream. A callback to unstall the second stream was
1082 // posted. Don't run it yet.
1085 EXPECT_EQ(0u, session_
->num_created_streams());
1086 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(MEDIUM
));
1088 // Create a third stream prior to the second stream's callback.
1089 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
1090 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1092 EXPECT_EQ(1u, session_
->num_created_streams());
1093 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(MEDIUM
));
1095 // Now run the message loop. The unstalled stream will re-stall itself.
1096 base::RunLoop().RunUntilIdle();
1097 EXPECT_EQ(1u, session_
->num_created_streams());
1098 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(MEDIUM
));
1100 // Cancel the third stream and run the message loop. Verify that the second
1101 // stream creation now completes.
1103 base::RunLoop().RunUntilIdle();
1105 EXPECT_EQ(1u, session_
->num_created_streams());
1106 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(MEDIUM
));
1107 EXPECT_EQ(OK
, callback2
.WaitForResult());
1110 TEST_P(SpdySessionTest
, DeleteExpiredPushStreams
) {
1111 session_deps_
.host_resolver
->set_synchronous_mode(true);
1112 session_deps_
.time_func
= TheNearFuture
;
1114 scoped_ptr
<SpdyFrame
> req(
1115 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
1116 scoped_ptr
<SpdyFrame
> rst(
1117 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
1118 MockWrite writes
[] = {CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5)};
1120 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
1121 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
1122 scoped_ptr
<SpdyFrame
> push_a_body(
1123 spdy_util_
.ConstructSpdyBodyFrame(2, false));
1124 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1125 // iterators inside. See http://crbug.com/443490
1126 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
1127 nullptr, 0, 4, 1, "http://www.example.org/0.dat"));
1128 MockRead reads
[] = {
1129 CreateMockRead(*push_a
, 1),
1130 CreateMockRead(*push_a_body
, 2),
1131 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
1132 CreateMockRead(*push_b
, 4),
1133 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
1134 MockRead(ASYNC
, 0, 7) // EOF
1137 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1138 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1140 CreateNetworkSession();
1141 CreateInsecureSpdySession();
1143 // Process the principal request, and the first push stream request & body.
1144 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1145 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1146 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1147 spdy_stream
->SetDelegate(&delegate
);
1149 scoped_ptr
<SpdyHeaderBlock
> headers(
1150 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1151 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1153 base::RunLoop().RunUntilIdle();
1155 // Verify that there is one unclaimed push stream.
1156 EXPECT_EQ(1u, session_
->num_unclaimed_pushed_streams());
1157 SpdySession::PushedStreamMap::iterator iter
=
1158 session_
->unclaimed_pushed_streams_
.find(
1159 GURL("http://www.example.org/a.dat"));
1160 EXPECT_TRUE(session_
->unclaimed_pushed_streams_
.end() != iter
);
1162 if (session_
->flow_control_state_
==
1163 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1164 // Unclaimed push body consumed bytes from the session window.
1166 SpdySession::GetDefaultInitialWindowSize(GetParam()) - kUploadDataSize
,
1167 session_
->session_recv_window_size_
);
1168 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
1171 // Shift time to expire the push stream. Read the second SYN_STREAM,
1172 // and verify a RST_STREAM was written.
1173 g_time_delta
= base::TimeDelta::FromSeconds(301);
1174 data
.CompleteRead();
1175 base::RunLoop().RunUntilIdle();
1177 // Verify that the second pushed stream evicted the first pushed stream.
1178 EXPECT_EQ(1u, session_
->num_unclaimed_pushed_streams());
1179 iter
= session_
->unclaimed_pushed_streams_
.find(
1180 GURL("http://www.example.org/0.dat"));
1181 EXPECT_TRUE(session_
->unclaimed_pushed_streams_
.end() != iter
);
1183 if (session_
->flow_control_state_
==
1184 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1185 // Verify that the session window reclaimed the evicted stream body.
1186 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
1187 session_
->session_recv_window_size_
);
1188 EXPECT_EQ(kUploadDataSize
, session_
->session_unacked_recv_window_bytes_
);
1191 // Read and process EOF.
1192 EXPECT_TRUE(session_
);
1193 data
.CompleteRead();
1194 base::RunLoop().RunUntilIdle();
1195 EXPECT_FALSE(session_
);
1198 TEST_P(SpdySessionTest
, FailedPing
) {
1199 session_deps_
.host_resolver
->set_synchronous_mode(true);
1201 MockRead reads
[] = {
1202 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1204 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
1205 scoped_ptr
<SpdyFrame
> goaway(
1206 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Failed ping."));
1207 MockWrite writes
[] = {CreateMockWrite(*write_ping
), CreateMockWrite(*goaway
)};
1209 StaticSocketDataProvider
data(
1210 reads
, arraysize(reads
), writes
, arraysize(writes
));
1211 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1213 CreateNetworkSession();
1214 CreateInsecureSpdySession();
1216 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1217 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1218 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1219 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
1220 spdy_stream1
->SetDelegate(&delegate
);
1222 session_
->set_connection_at_risk_of_loss_time(
1223 base::TimeDelta::FromSeconds(0));
1224 session_
->set_hung_interval(base::TimeDelta::FromSeconds(0));
1226 // Send a PING frame.
1227 session_
->WritePingFrame(1, false);
1228 EXPECT_LT(0, session_
->pings_in_flight());
1229 EXPECT_GE(session_
->next_ping_id(), 1U);
1230 EXPECT_TRUE(session_
->check_ping_status_pending());
1232 // Assert session is not closed.
1233 EXPECT_TRUE(session_
->IsAvailable());
1235 session_
->num_active_streams() + session_
->num_created_streams());
1236 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1238 // We set last time we have received any data in 1 sec less than now.
1239 // CheckPingStatus will trigger timeout because hung interval is zero.
1240 base::TimeTicks now
= base::TimeTicks::Now();
1241 session_
->last_activity_time_
= now
- base::TimeDelta::FromSeconds(1);
1242 session_
->CheckPingStatus(now
);
1243 base::RunLoop().RunUntilIdle();
1245 EXPECT_FALSE(session_
);
1246 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1247 EXPECT_FALSE(spdy_stream1
);
1250 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1251 // settings frame increasing the max concurrent streams by 1. Make
1252 // sure nothing blows up. This is a regression test for
1253 // http://crbug.com/57331 .
1254 TEST_P(SpdySessionTest
, OnSettings
) {
1255 session_deps_
.host_resolver
->set_synchronous_mode(true);
1257 const SpdySettingsIds kSpdySettingsIds
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1260 std::vector
<MockWrite
> writes
;
1261 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1262 if (GetParam() == kProtoHTTP2
) {
1263 writes
.push_back(CreateMockWrite(*settings_ack
, ++seq
));
1266 SettingsMap new_settings
;
1267 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1268 new_settings
[kSpdySettingsIds
] =
1269 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1270 scoped_ptr
<SpdyFrame
> settings_frame(
1271 spdy_util_
.ConstructSpdySettings(new_settings
));
1272 MockRead reads
[] = {
1273 CreateMockRead(*settings_frame
, 0),
1274 MockRead(ASYNC
, ERR_IO_PENDING
, ++seq
),
1275 MockRead(ASYNC
, 0, ++seq
),
1278 SequencedSocketData
data(reads
, arraysize(reads
), vector_as_array(&writes
),
1280 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1282 CreateNetworkSession();
1283 CreateInsecureSpdySession();
1285 // Create the maximum number of concurrent streams.
1286 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1287 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1288 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1289 ASSERT_TRUE(spdy_stream
!= nullptr);
1292 StreamReleaserCallback stream_releaser
;
1293 SpdyStreamRequest request
;
1294 ASSERT_EQ(ERR_IO_PENDING
,
1295 request
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
1296 MEDIUM
, BoundNetLog(),
1297 stream_releaser
.MakeCallback(&request
)));
1299 base::RunLoop().RunUntilIdle();
1301 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1303 data
.CompleteRead();
1304 base::RunLoop().RunUntilIdle();
1305 EXPECT_FALSE(session_
);
1307 EXPECT_TRUE(data
.AllWriteDataConsumed());
1308 EXPECT_TRUE(data
.AllReadDataConsumed());
1311 // Start with a persisted value for max concurrent streams. Receive a
1312 // settings frame increasing the max concurrent streams by 1 and which
1313 // also clears the persisted data. Verify that persisted data is
1315 TEST_P(SpdySessionTest
, ClearSettings
) {
1316 if (spdy_util_
.spdy_version() >= HTTP2
) {
1317 // HTTP/2 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1318 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in HTTP/2.
1321 session_deps_
.host_resolver
->set_synchronous_mode(true);
1323 SettingsMap new_settings
;
1324 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1325 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1326 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1327 scoped_ptr
<SpdyFrame
> settings_frame(
1328 spdy_util_
.ConstructSpdySettings(new_settings
));
1329 uint8 flags
= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
1330 test::SetFrameFlags(settings_frame
.get(), flags
, spdy_util_
.spdy_version());
1331 MockRead reads
[] = {
1332 CreateMockRead(*settings_frame
, 0),
1333 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
1334 MockRead(ASYNC
, 0, 2),
1337 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
1338 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1340 CreateNetworkSession();
1342 // Initialize the SpdySetting with the default.
1343 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1344 test_host_port_pair_
,
1345 SETTINGS_MAX_CONCURRENT_STREAMS
,
1346 SETTINGS_FLAG_PLEASE_PERSIST
,
1347 kInitialMaxConcurrentStreams
);
1350 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1351 test_host_port_pair_
).empty());
1353 CreateInsecureSpdySession();
1355 // Create the maximum number of concurrent streams.
1356 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1357 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1358 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1359 ASSERT_TRUE(spdy_stream
!= nullptr);
1362 StreamReleaserCallback stream_releaser
;
1364 SpdyStreamRequest request
;
1365 ASSERT_EQ(ERR_IO_PENDING
,
1366 request
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
1367 MEDIUM
, BoundNetLog(),
1368 stream_releaser
.MakeCallback(&request
)));
1370 base::RunLoop().RunUntilIdle();
1372 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1374 // Make sure that persisted data is cleared.
1376 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1377 test_host_port_pair_
).empty());
1379 // Make sure session's max_concurrent_streams is correct.
1380 EXPECT_EQ(kInitialMaxConcurrentStreams
+ 1,
1381 session_
->max_concurrent_streams());
1383 data
.CompleteRead();
1384 base::RunLoop().RunUntilIdle();
1385 EXPECT_FALSE(session_
);
1388 // Start with max concurrent streams set to 1. Request two streams.
1389 // When the first completes, have the callback close its stream, which
1390 // should trigger the second stream creation. Then cancel that one
1391 // immediately. Don't crash. This is a regression test for
1392 // http://crbug.com/63532 .
1393 TEST_P(SpdySessionTest
, CancelPendingCreateStream
) {
1394 session_deps_
.host_resolver
->set_synchronous_mode(true);
1396 MockRead reads
[] = {
1397 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1400 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1401 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1403 CreateNetworkSession();
1405 // Initialize the SpdySetting with 1 max concurrent streams.
1406 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1407 test_host_port_pair_
,
1408 SETTINGS_MAX_CONCURRENT_STREAMS
,
1409 SETTINGS_FLAG_PLEASE_PERSIST
,
1412 CreateInsecureSpdySession();
1414 // Leave room for only one more stream to be created.
1415 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
1416 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1417 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1418 ASSERT_TRUE(spdy_stream
!= nullptr);
1421 // Create 2 more streams. First will succeed. Second will be pending.
1422 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1423 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1424 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1426 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1427 // a valgrind error if the callback is invoked when it's not supposed to be.
1428 scoped_ptr
<TestCompletionCallback
> callback(new TestCompletionCallback
);
1430 SpdyStreamRequest request
;
1431 ASSERT_EQ(ERR_IO_PENDING
,
1432 request
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
1433 MEDIUM
, BoundNetLog(), callback
->callback()));
1435 // Release the first one, this will allow the second to be created.
1436 spdy_stream1
->Cancel();
1437 EXPECT_FALSE(spdy_stream1
);
1439 request
.CancelRequest();
1442 // Should not crash when running the pending callback.
1443 base::RunLoop().RunUntilIdle();
1446 TEST_P(SpdySessionTest
, SendInitialDataOnNewSession
) {
1447 session_deps_
.host_resolver
->set_synchronous_mode(true);
1449 MockRead reads
[] = {
1450 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1453 SettingsMap settings
;
1454 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1455 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
1456 scoped_ptr
<SpdyFrame
> settings_frame(
1457 spdy_util_
.ConstructSpdySettings(settings
));
1458 std::vector
<MockWrite
> writes
;
1459 if (GetParam() == kProtoHTTP2
) {
1462 kHttp2ConnectionHeaderPrefix
,
1463 kHttp2ConnectionHeaderPrefixSize
));
1465 writes
.push_back(CreateMockWrite(*settings_frame
));
1467 SettingsMap server_settings
;
1468 const uint32 initial_max_concurrent_streams
= 1;
1469 server_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1470 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED
,
1471 initial_max_concurrent_streams
);
1472 scoped_ptr
<SpdyFrame
> server_settings_frame(
1473 spdy_util_
.ConstructSpdySettings(server_settings
));
1474 if (GetParam() <= kProtoSPDY31
) {
1475 writes
.push_back(CreateMockWrite(*server_settings_frame
));
1478 StaticSocketDataProvider
data(reads
, arraysize(reads
),
1479 vector_as_array(&writes
), writes
.size());
1480 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1482 CreateNetworkSession();
1484 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1485 test_host_port_pair_
,
1486 SETTINGS_MAX_CONCURRENT_STREAMS
,
1487 SETTINGS_FLAG_PLEASE_PERSIST
,
1488 initial_max_concurrent_streams
);
1490 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
1491 pool_peer
.SetEnableSendingInitialData(true);
1493 CreateInsecureSpdySession();
1495 base::RunLoop().RunUntilIdle();
1496 EXPECT_TRUE(data
.AllWriteDataConsumed());
1499 TEST_P(SpdySessionTest
, ClearSettingsStorageOnIPAddressChanged
) {
1500 CreateNetworkSession();
1502 base::WeakPtr
<HttpServerProperties
> test_http_server_properties
=
1503 spdy_session_pool_
->http_server_properties();
1504 SettingsFlagsAndValue
flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST
, 2);
1505 test_http_server_properties
->SetSpdySetting(
1506 test_host_port_pair_
,
1507 SETTINGS_MAX_CONCURRENT_STREAMS
,
1508 SETTINGS_FLAG_PLEASE_PERSIST
,
1510 EXPECT_NE(0u, test_http_server_properties
->GetSpdySettings(
1511 test_host_port_pair_
).size());
1512 spdy_session_pool_
->OnIPAddressChanged();
1513 EXPECT_EQ(0u, test_http_server_properties
->GetSpdySettings(
1514 test_host_port_pair_
).size());
1517 TEST_P(SpdySessionTest
, Initialize
) {
1518 session_deps_
.host_resolver
->set_synchronous_mode(true);
1520 MockRead reads
[] = {
1521 MockRead(ASYNC
, 0, 0) // EOF
1524 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1525 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1527 CreateNetworkSession();
1528 CreateInsecureSpdySession();
1529 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1531 // Flush the read completion task.
1532 base::RunLoop().RunUntilIdle();
1534 TestNetLogEntry::List entries
;
1535 log_
.GetEntries(&entries
);
1536 EXPECT_LT(0u, entries
.size());
1538 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1539 int pos
= ExpectLogContainsSomewhere(
1540 entries
, 0, NetLog::TYPE_HTTP2_SESSION_INITIALIZED
, NetLog::PHASE_NONE
);
1543 TestNetLogEntry entry
= entries
[pos
];
1544 NetLog::Source socket_source
;
1545 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry
.params
.get(),
1547 EXPECT_TRUE(socket_source
.IsValid());
1548 EXPECT_NE(log_
.bound().source().id
, socket_source
.id
);
1551 TEST_P(SpdySessionTest
, NetLogOnSessionGoaway
) {
1552 session_deps_
.host_resolver
->set_synchronous_mode(true);
1554 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
1555 MockRead reads
[] = {
1556 CreateMockRead(*goaway
),
1557 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1560 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1561 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1563 CreateNetworkSession();
1564 CreateInsecureSpdySession();
1565 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1567 // Flush the read completion task.
1568 base::RunLoop().RunUntilIdle();
1570 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1571 EXPECT_FALSE(session_
);
1573 // Check that the NetLog was filled reasonably.
1574 TestNetLogEntry::List entries
;
1575 log_
.GetEntries(&entries
);
1576 EXPECT_LT(0u, entries
.size());
1578 // Check that we logged SPDY_SESSION_CLOSE correctly.
1579 int pos
= ExpectLogContainsSomewhere(
1580 entries
, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE
, NetLog::PHASE_NONE
);
1582 if (pos
< static_cast<int>(entries
.size())) {
1583 TestNetLogEntry entry
= entries
[pos
];
1585 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1586 EXPECT_EQ(OK
, error_code
);
1592 TEST_P(SpdySessionTest
, NetLogOnSessionEOF
) {
1593 session_deps_
.host_resolver
->set_synchronous_mode(true);
1595 MockRead reads
[] = {
1596 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1599 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1600 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1602 CreateNetworkSession();
1603 CreateInsecureSpdySession();
1604 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1606 // Flush the read completion task.
1607 base::RunLoop().RunUntilIdle();
1609 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1610 EXPECT_FALSE(session_
);
1612 // Check that the NetLog was filled reasonably.
1613 TestNetLogEntry::List entries
;
1614 log_
.GetEntries(&entries
);
1615 EXPECT_LT(0u, entries
.size());
1617 // Check that we logged SPDY_SESSION_CLOSE correctly.
1618 int pos
= ExpectLogContainsSomewhere(
1619 entries
, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE
, NetLog::PHASE_NONE
);
1621 if (pos
< static_cast<int>(entries
.size())) {
1622 TestNetLogEntry entry
= entries
[pos
];
1624 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1625 EXPECT_EQ(ERR_CONNECTION_CLOSED
, error_code
);
1631 TEST_P(SpdySessionTest
, SynCompressionHistograms
) {
1632 session_deps_
.enable_compression
= true;
1634 scoped_ptr
<SpdyFrame
> req(
1635 spdy_util_
.ConstructSpdyGet(nullptr, 0, true, 1, MEDIUM
, true));
1636 MockWrite writes
[] = {
1637 CreateMockWrite(*req
, 0),
1639 MockRead reads
[] = {
1640 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
1642 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1643 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1645 CreateNetworkSession();
1646 CreateInsecureSpdySession();
1648 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1649 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1650 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1651 spdy_stream
->SetDelegate(&delegate
);
1653 scoped_ptr
<SpdyHeaderBlock
> headers(
1654 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1655 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1656 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
1658 // Write request headers & capture resulting histogram update.
1659 base::HistogramTester histogram_tester
;
1661 base::RunLoop().RunUntilIdle();
1662 // Regression test of compression performance under the request fixture.
1663 switch (spdy_util_
.spdy_version()) {
1665 histogram_tester
.ExpectBucketCount(
1666 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1669 histogram_tester
.ExpectBucketCount(
1670 "Net.SpdySynStreamCompressionPercentage", 81, 1);
1676 // Read and process EOF.
1677 EXPECT_TRUE(session_
);
1678 data
.CompleteRead();
1679 base::RunLoop().RunUntilIdle();
1680 EXPECT_FALSE(session_
);
1683 // Queue up a low-priority SYN_STREAM followed by a high-priority
1684 // one. The high priority one should still send first and receive
1686 TEST_P(SpdySessionTest
, OutOfOrderSynStreams
) {
1687 // Construct the request.
1688 scoped_ptr
<SpdyFrame
> req_highest(
1689 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, HIGHEST
, true));
1690 scoped_ptr
<SpdyFrame
> req_lowest(
1691 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST
, true));
1692 MockWrite writes
[] = {
1693 CreateMockWrite(*req_highest
, 0),
1694 CreateMockWrite(*req_lowest
, 1),
1697 scoped_ptr
<SpdyFrame
> resp_highest(
1698 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
1699 scoped_ptr
<SpdyFrame
> body_highest(
1700 spdy_util_
.ConstructSpdyBodyFrame(1, true));
1701 scoped_ptr
<SpdyFrame
> resp_lowest(
1702 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
1703 scoped_ptr
<SpdyFrame
> body_lowest(
1704 spdy_util_
.ConstructSpdyBodyFrame(3, true));
1705 MockRead reads
[] = {
1706 CreateMockRead(*resp_highest
, 2),
1707 CreateMockRead(*body_highest
, 3),
1708 CreateMockRead(*resp_lowest
, 4),
1709 CreateMockRead(*body_lowest
, 5),
1710 MockRead(ASYNC
, 0, 6) // EOF
1713 session_deps_
.host_resolver
->set_synchronous_mode(true);
1715 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1716 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1718 CreateNetworkSession();
1719 CreateInsecureSpdySession();
1721 base::WeakPtr
<SpdyStream
> spdy_stream_lowest
= CreateStreamSynchronously(
1722 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
1723 ASSERT_TRUE(spdy_stream_lowest
);
1724 EXPECT_EQ(0u, spdy_stream_lowest
->stream_id());
1725 test::StreamDelegateDoNothing
delegate_lowest(spdy_stream_lowest
);
1726 spdy_stream_lowest
->SetDelegate(&delegate_lowest
);
1728 base::WeakPtr
<SpdyStream
> spdy_stream_highest
=
1729 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
, session_
,
1730 test_url_
, HIGHEST
, BoundNetLog());
1731 ASSERT_TRUE(spdy_stream_highest
);
1732 EXPECT_EQ(0u, spdy_stream_highest
->stream_id());
1733 test::StreamDelegateDoNothing
delegate_highest(spdy_stream_highest
);
1734 spdy_stream_highest
->SetDelegate(&delegate_highest
);
1736 // Queue the lower priority one first.
1738 scoped_ptr
<SpdyHeaderBlock
> headers_lowest(
1739 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1740 spdy_stream_lowest
->SendRequestHeaders(
1741 headers_lowest
.Pass(), NO_MORE_DATA_TO_SEND
);
1742 EXPECT_TRUE(spdy_stream_lowest
->HasUrlFromHeaders());
1744 scoped_ptr
<SpdyHeaderBlock
> headers_highest(
1745 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1746 spdy_stream_highest
->SendRequestHeaders(
1747 headers_highest
.Pass(), NO_MORE_DATA_TO_SEND
);
1748 EXPECT_TRUE(spdy_stream_highest
->HasUrlFromHeaders());
1750 base::RunLoop().RunUntilIdle();
1752 EXPECT_FALSE(spdy_stream_lowest
);
1753 EXPECT_FALSE(spdy_stream_highest
);
1754 EXPECT_EQ(3u, delegate_lowest
.stream_id());
1755 EXPECT_EQ(1u, delegate_highest
.stream_id());
1758 TEST_P(SpdySessionTest
, CancelStream
) {
1759 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1760 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1761 scoped_ptr
<SpdyFrame
> req2(
1762 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
1763 MockWrite writes
[] = {
1764 CreateMockWrite(*req2
, 0),
1767 scoped_ptr
<SpdyFrame
> resp2(
1768 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
1769 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1770 MockRead reads
[] = {
1771 CreateMockRead(*resp2
, 1),
1772 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
1773 CreateMockRead(*body2
, 3),
1774 MockRead(ASYNC
, 0, 4) // EOF
1777 session_deps_
.host_resolver
->set_synchronous_mode(true);
1779 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1780 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1782 CreateNetworkSession();
1783 CreateInsecureSpdySession();
1785 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1786 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
, session_
,
1787 test_url_
, HIGHEST
, BoundNetLog());
1788 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1789 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1790 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
1791 spdy_stream1
->SetDelegate(&delegate1
);
1793 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
1794 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
1795 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
1796 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1797 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
1798 spdy_stream2
->SetDelegate(&delegate2
);
1800 scoped_ptr
<SpdyHeaderBlock
> headers(
1801 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1802 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1803 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1805 scoped_ptr
<SpdyHeaderBlock
> headers2(
1806 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1807 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1808 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1810 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1812 spdy_stream1
->Cancel();
1813 EXPECT_FALSE(spdy_stream1
);
1815 EXPECT_EQ(0u, delegate1
.stream_id());
1817 base::RunLoop().RunUntilIdle();
1819 EXPECT_EQ(0u, delegate1
.stream_id());
1820 EXPECT_EQ(1u, delegate2
.stream_id());
1822 spdy_stream2
->Cancel();
1823 EXPECT_FALSE(spdy_stream2
);
1826 // Create two streams that are set to re-close themselves on close,
1827 // and then close the session. Nothing should blow up. Also a
1828 // regression test for http://crbug.com/139518 .
1829 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedSelfClosingStreams
) {
1830 session_deps_
.host_resolver
->set_synchronous_mode(true);
1833 // No actual data will be sent.
1834 MockWrite writes
[] = {
1835 MockWrite(ASYNC
, 0, 1) // EOF
1838 MockRead reads
[] = {
1839 MockRead(ASYNC
, 0, 0) // EOF
1841 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1842 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1844 CreateNetworkSession();
1845 CreateInsecureSpdySession();
1847 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1848 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, HIGHEST
, BoundNetLog());
1849 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1850 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1852 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
1853 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
1854 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
1855 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1857 test::ClosingDelegate
delegate1(spdy_stream1
);
1858 spdy_stream1
->SetDelegate(&delegate1
);
1860 test::ClosingDelegate
delegate2(spdy_stream2
);
1861 spdy_stream2
->SetDelegate(&delegate2
);
1863 scoped_ptr
<SpdyHeaderBlock
> headers(
1864 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1865 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1866 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1868 scoped_ptr
<SpdyHeaderBlock
> headers2(
1869 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1870 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1871 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1873 // Ensure that the streams have not yet been activated and assigned an id.
1874 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1875 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1877 // Ensure we don't crash while closing the session.
1878 session_
->CloseSessionOnError(ERR_ABORTED
, std::string());
1880 EXPECT_FALSE(spdy_stream1
);
1881 EXPECT_FALSE(spdy_stream2
);
1883 EXPECT_TRUE(delegate1
.StreamIsClosed());
1884 EXPECT_TRUE(delegate2
.StreamIsClosed());
1886 base::RunLoop().RunUntilIdle();
1887 EXPECT_FALSE(session_
);
1890 // Create two streams that are set to close each other on close, and
1891 // then close the session. Nothing should blow up.
1892 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedMutuallyClosingStreams
) {
1893 session_deps_
.host_resolver
->set_synchronous_mode(true);
1895 SequencedSocketData
data(nullptr, 0, nullptr, 0);
1896 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1898 CreateNetworkSession();
1899 CreateInsecureSpdySession();
1901 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1902 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, HIGHEST
, BoundNetLog());
1903 ASSERT_TRUE(spdy_stream1
);
1904 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1906 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
1907 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
1908 ASSERT_TRUE(spdy_stream2
);
1909 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1911 // Make |spdy_stream1| close |spdy_stream2|.
1912 test::ClosingDelegate
delegate1(spdy_stream2
);
1913 spdy_stream1
->SetDelegate(&delegate1
);
1915 // Make |spdy_stream2| close |spdy_stream1|.
1916 test::ClosingDelegate
delegate2(spdy_stream1
);
1917 spdy_stream2
->SetDelegate(&delegate2
);
1919 scoped_ptr
<SpdyHeaderBlock
> headers(
1920 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1921 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1922 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1924 scoped_ptr
<SpdyHeaderBlock
> headers2(
1925 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1926 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1927 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1929 // Ensure that the streams have not yet been activated and assigned an id.
1930 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1931 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1933 // Ensure we don't crash while closing the session.
1934 session_
->CloseSessionOnError(ERR_ABORTED
, std::string());
1936 EXPECT_FALSE(spdy_stream1
);
1937 EXPECT_FALSE(spdy_stream2
);
1939 EXPECT_TRUE(delegate1
.StreamIsClosed());
1940 EXPECT_TRUE(delegate2
.StreamIsClosed());
1942 base::RunLoop().RunUntilIdle();
1943 EXPECT_FALSE(session_
);
1946 // Create two streams that are set to re-close themselves on close,
1947 // activate them, and then close the session. Nothing should blow up.
1948 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedSelfClosingStreams
) {
1949 session_deps_
.host_resolver
->set_synchronous_mode(true);
1951 scoped_ptr
<SpdyFrame
> req1(
1952 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
1953 scoped_ptr
<SpdyFrame
> req2(
1954 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
1955 MockWrite writes
[] = {
1956 CreateMockWrite(*req1
, 0),
1957 CreateMockWrite(*req2
, 1),
1960 MockRead reads
[] = {
1961 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
1964 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1965 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1967 CreateNetworkSession();
1968 CreateInsecureSpdySession();
1970 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1971 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1972 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1973 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1975 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
1976 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1977 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
1978 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1980 test::ClosingDelegate
delegate1(spdy_stream1
);
1981 spdy_stream1
->SetDelegate(&delegate1
);
1983 test::ClosingDelegate
delegate2(spdy_stream2
);
1984 spdy_stream2
->SetDelegate(&delegate2
);
1986 scoped_ptr
<SpdyHeaderBlock
> headers(
1987 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1988 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1989 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1991 scoped_ptr
<SpdyHeaderBlock
> headers2(
1992 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1993 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1994 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1996 // Ensure that the streams have not yet been activated and assigned an id.
1997 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1998 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2000 base::RunLoop().RunUntilIdle();
2002 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2003 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2005 // Ensure we don't crash while closing the session.
2006 session_
->CloseSessionOnError(ERR_ABORTED
, std::string());
2008 EXPECT_FALSE(spdy_stream1
);
2009 EXPECT_FALSE(spdy_stream2
);
2011 EXPECT_TRUE(delegate1
.StreamIsClosed());
2012 EXPECT_TRUE(delegate2
.StreamIsClosed());
2014 EXPECT_TRUE(session_
);
2015 data
.CompleteRead();
2016 base::RunLoop().RunUntilIdle();
2017 EXPECT_FALSE(session_
);
2020 // Create two streams that are set to close each other on close,
2021 // activate them, and then close the session. Nothing should blow up.
2022 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedMutuallyClosingStreams
) {
2023 session_deps_
.host_resolver
->set_synchronous_mode(true);
2025 scoped_ptr
<SpdyFrame
> req1(
2026 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2027 scoped_ptr
<SpdyFrame
> req2(
2028 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
2029 MockWrite writes
[] = {
2030 CreateMockWrite(*req1
, 0),
2031 CreateMockWrite(*req2
, 1),
2034 MockRead reads
[] = {
2035 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
2038 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2039 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2041 CreateNetworkSession();
2042 CreateInsecureSpdySession();
2044 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2045 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2046 ASSERT_TRUE(spdy_stream1
);
2047 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2049 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
2050 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2051 ASSERT_TRUE(spdy_stream2
);
2052 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2054 // Make |spdy_stream1| close |spdy_stream2|.
2055 test::ClosingDelegate
delegate1(spdy_stream2
);
2056 spdy_stream1
->SetDelegate(&delegate1
);
2058 // Make |spdy_stream2| close |spdy_stream1|.
2059 test::ClosingDelegate
delegate2(spdy_stream1
);
2060 spdy_stream2
->SetDelegate(&delegate2
);
2062 scoped_ptr
<SpdyHeaderBlock
> headers(
2063 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2064 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2065 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2067 scoped_ptr
<SpdyHeaderBlock
> headers2(
2068 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2069 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2070 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2072 // Ensure that the streams have not yet been activated and assigned an id.
2073 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2074 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2076 base::RunLoop().RunUntilIdle();
2078 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2079 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2081 // Ensure we don't crash while closing the session.
2082 session_
->CloseSessionOnError(ERR_ABORTED
, std::string());
2084 EXPECT_FALSE(spdy_stream1
);
2085 EXPECT_FALSE(spdy_stream2
);
2087 EXPECT_TRUE(delegate1
.StreamIsClosed());
2088 EXPECT_TRUE(delegate2
.StreamIsClosed());
2090 EXPECT_TRUE(session_
);
2091 data
.CompleteRead();
2092 base::RunLoop().RunUntilIdle();
2093 EXPECT_FALSE(session_
);
2096 // Delegate that closes a given session when the stream is closed.
2097 class SessionClosingDelegate
: public test::StreamDelegateDoNothing
{
2099 SessionClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
2100 const base::WeakPtr
<SpdySession
>& session_to_close
)
2101 : StreamDelegateDoNothing(stream
),
2102 session_to_close_(session_to_close
) {}
2104 ~SessionClosingDelegate() override
{}
2106 void OnClose(int status
) override
{
2107 session_to_close_
->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR
, "Error");
2111 base::WeakPtr
<SpdySession
> session_to_close_
;
2114 // Close an activated stream that closes its session. Nothing should
2115 // blow up. This is a regression test for https://crbug.com/263691.
2116 TEST_P(SpdySessionTest
, CloseActivatedStreamThatClosesSession
) {
2117 session_deps_
.host_resolver
->set_synchronous_mode(true);
2119 scoped_ptr
<SpdyFrame
> req(
2120 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2121 scoped_ptr
<SpdyFrame
> rst(
2122 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2123 scoped_ptr
<SpdyFrame
> goaway(
2124 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Error"));
2125 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2126 // despite being queued second.
2127 MockWrite writes
[] = {
2128 CreateMockWrite(*req
, 0),
2129 CreateMockWrite(*goaway
, 1),
2130 CreateMockWrite(*rst
, 3),
2133 MockRead reads
[] = {
2134 MockRead(ASYNC
, 0, 2) // EOF
2136 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2137 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2139 CreateNetworkSession();
2140 CreateInsecureSpdySession();
2142 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
2143 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2144 ASSERT_TRUE(spdy_stream
.get() != nullptr);
2145 EXPECT_EQ(0u, spdy_stream
->stream_id());
2147 SessionClosingDelegate
delegate(spdy_stream
, session_
);
2148 spdy_stream
->SetDelegate(&delegate
);
2150 scoped_ptr
<SpdyHeaderBlock
> headers(
2151 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2152 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2153 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
2155 EXPECT_EQ(0u, spdy_stream
->stream_id());
2157 base::RunLoop().RunUntilIdle();
2159 EXPECT_EQ(1u, spdy_stream
->stream_id());
2161 // Ensure we don't crash while closing the stream (which closes the
2163 spdy_stream
->Cancel();
2165 EXPECT_FALSE(spdy_stream
);
2166 EXPECT_TRUE(delegate
.StreamIsClosed());
2168 // Write the RST_STREAM & GOAWAY.
2169 base::RunLoop().RunUntilIdle();
2170 EXPECT_TRUE(data
.AllWriteDataConsumed());
2171 EXPECT_TRUE(data
.AllReadDataConsumed());
2174 TEST_P(SpdySessionTest
, VerifyDomainAuthentication
) {
2175 session_deps_
.host_resolver
->set_synchronous_mode(true);
2177 SequencedSocketData
data(nullptr, 0, nullptr, 0);
2178 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2180 // Load a cert that is valid for:
2184 base::FilePath certs_dir
= GetTestCertsDirectory();
2185 scoped_refptr
<X509Certificate
> test_cert(
2186 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2187 ASSERT_NE(static_cast<X509Certificate
*>(nullptr), test_cert
.get());
2189 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2190 ssl
.cert
= test_cert
;
2191 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2193 CreateNetworkSession();
2195 session_
= CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2197 EXPECT_TRUE(session_
->VerifyDomainAuthentication("www.example.org"));
2198 EXPECT_TRUE(session_
->VerifyDomainAuthentication("mail.example.org"));
2199 EXPECT_TRUE(session_
->VerifyDomainAuthentication("mail.example.com"));
2200 EXPECT_FALSE(session_
->VerifyDomainAuthentication("mail.google.com"));
2203 TEST_P(SpdySessionTest
, ConnectionPooledWithTlsChannelId
) {
2204 session_deps_
.host_resolver
->set_synchronous_mode(true);
2206 SequencedSocketData
data(nullptr, 0, nullptr, 0);
2207 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2209 // Load a cert that is valid for:
2213 base::FilePath certs_dir
= GetTestCertsDirectory();
2214 scoped_refptr
<X509Certificate
> test_cert(
2215 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2216 ASSERT_NE(static_cast<X509Certificate
*>(nullptr), test_cert
.get());
2218 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2219 ssl
.channel_id_sent
= true;
2220 ssl
.cert
= test_cert
;
2221 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2223 CreateNetworkSession();
2225 session_
= CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2227 EXPECT_TRUE(session_
->VerifyDomainAuthentication("www.example.org"));
2228 EXPECT_TRUE(session_
->VerifyDomainAuthentication("mail.example.org"));
2229 EXPECT_FALSE(session_
->VerifyDomainAuthentication("mail.example.com"));
2230 EXPECT_FALSE(session_
->VerifyDomainAuthentication("mail.google.com"));
2233 TEST_P(SpdySessionTest
, CloseTwoStalledCreateStream
) {
2234 // TODO(rtenneti): Define a helper class/methods and move the common code in
2236 SettingsMap new_settings
;
2237 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
2238 const uint32 max_concurrent_streams
= 1;
2239 new_settings
[kSpdySettingsIds1
] =
2240 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
2242 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
2243 scoped_ptr
<SpdyFrame
> req1(
2244 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
2245 scoped_ptr
<SpdyFrame
> req2(
2246 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST
, true));
2247 scoped_ptr
<SpdyFrame
> req3(
2248 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 5, LOWEST
, true));
2249 MockWrite writes
[] = {
2250 CreateMockWrite(*settings_ack
, 1),
2251 CreateMockWrite(*req1
, 2),
2252 CreateMockWrite(*req2
, 5),
2253 CreateMockWrite(*req3
, 8),
2256 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2258 scoped_ptr
<SpdyFrame
> settings_frame(
2259 spdy_util_
.ConstructSpdySettings(new_settings
));
2261 scoped_ptr
<SpdyFrame
> resp1(
2262 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2263 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2265 scoped_ptr
<SpdyFrame
> resp2(
2266 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
2267 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
2269 scoped_ptr
<SpdyFrame
> resp3(
2270 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 5));
2271 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
2273 MockRead reads
[] = {
2274 CreateMockRead(*settings_frame
, 0),
2275 CreateMockRead(*resp1
, 3),
2276 CreateMockRead(*body1
, 4),
2277 CreateMockRead(*resp2
, 6),
2278 CreateMockRead(*body2
, 7),
2279 CreateMockRead(*resp3
, 9),
2280 CreateMockRead(*body3
, 10),
2281 MockRead(ASYNC
, ERR_IO_PENDING
, 11),
2282 MockRead(ASYNC
, 0, 12) // EOF
2285 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2286 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2288 CreateNetworkSession();
2289 CreateInsecureSpdySession();
2291 // Read the settings frame.
2292 base::RunLoop().RunUntilIdle();
2294 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2295 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
2296 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2297 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2298 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2299 spdy_stream1
->SetDelegate(&delegate1
);
2301 TestCompletionCallback callback2
;
2302 SpdyStreamRequest request2
;
2305 request2
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
,
2306 LOWEST
, BoundNetLog(), callback2
.callback()));
2308 TestCompletionCallback callback3
;
2309 SpdyStreamRequest request3
;
2312 request3
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
,
2313 LOWEST
, BoundNetLog(), callback3
.callback()));
2315 EXPECT_EQ(0u, session_
->num_active_streams());
2316 EXPECT_EQ(1u, session_
->num_created_streams());
2317 EXPECT_EQ(2u, session_
->pending_create_stream_queue_size(LOWEST
));
2319 scoped_ptr
<SpdyHeaderBlock
> headers(
2320 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2321 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2322 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2324 // Run until 1st stream is activated and then closed.
2325 EXPECT_EQ(0u, delegate1
.stream_id());
2326 base::RunLoop().RunUntilIdle();
2327 EXPECT_FALSE(spdy_stream1
);
2328 EXPECT_EQ(1u, delegate1
.stream_id());
2330 EXPECT_EQ(0u, session_
->num_active_streams());
2331 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(LOWEST
));
2333 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2334 // create the 2nd stream.
2335 base::RunLoop().RunUntilIdle();
2337 EXPECT_EQ(0u, session_
->num_active_streams());
2338 EXPECT_EQ(1u, session_
->num_created_streams());
2339 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(LOWEST
));
2341 base::WeakPtr
<SpdyStream
> stream2
= request2
.ReleaseStream();
2342 test::StreamDelegateDoNothing
delegate2(stream2
);
2343 stream2
->SetDelegate(&delegate2
);
2344 scoped_ptr
<SpdyHeaderBlock
> headers2(
2345 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2346 stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2347 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
2349 // Run until 2nd stream is activated and then closed.
2350 EXPECT_EQ(0u, delegate2
.stream_id());
2351 base::RunLoop().RunUntilIdle();
2352 EXPECT_FALSE(stream2
);
2353 EXPECT_EQ(3u, delegate2
.stream_id());
2355 EXPECT_EQ(0u, session_
->num_active_streams());
2356 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2358 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2359 // create the 3rd stream.
2360 base::RunLoop().RunUntilIdle();
2362 EXPECT_EQ(0u, session_
->num_active_streams());
2363 EXPECT_EQ(1u, session_
->num_created_streams());
2364 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2366 base::WeakPtr
<SpdyStream
> stream3
= request3
.ReleaseStream();
2367 test::StreamDelegateDoNothing
delegate3(stream3
);
2368 stream3
->SetDelegate(&delegate3
);
2369 scoped_ptr
<SpdyHeaderBlock
> headers3(
2370 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2371 stream3
->SendRequestHeaders(headers3
.Pass(), NO_MORE_DATA_TO_SEND
);
2372 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
2374 // Run until 2nd stream is activated and then closed.
2375 EXPECT_EQ(0u, delegate3
.stream_id());
2376 base::RunLoop().RunUntilIdle();
2377 EXPECT_FALSE(stream3
);
2378 EXPECT_EQ(5u, delegate3
.stream_id());
2380 EXPECT_EQ(0u, session_
->num_active_streams());
2381 EXPECT_EQ(0u, session_
->num_created_streams());
2382 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2384 data
.CompleteRead();
2385 base::RunLoop().RunUntilIdle();
2388 TEST_P(SpdySessionTest
, CancelTwoStalledCreateStream
) {
2389 session_deps_
.host_resolver
->set_synchronous_mode(true);
2391 MockRead reads
[] = {
2392 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2395 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2396 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2398 CreateNetworkSession();
2399 CreateInsecureSpdySession();
2401 // Leave room for only one more stream to be created.
2402 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
2403 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
2404 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2405 ASSERT_TRUE(spdy_stream
!= nullptr);
2408 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2409 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
2410 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2411 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2413 TestCompletionCallback callback2
;
2414 SpdyStreamRequest request2
;
2415 ASSERT_EQ(ERR_IO_PENDING
, request2
.StartRequest(
2416 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
2417 LOWEST
, BoundNetLog(), callback2
.callback()));
2419 TestCompletionCallback callback3
;
2420 SpdyStreamRequest request3
;
2421 ASSERT_EQ(ERR_IO_PENDING
, request3
.StartRequest(
2422 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
2423 LOWEST
, BoundNetLog(), callback3
.callback()));
2425 EXPECT_EQ(0u, session_
->num_active_streams());
2426 EXPECT_EQ(kInitialMaxConcurrentStreams
, session_
->num_created_streams());
2427 EXPECT_EQ(2u, session_
->pending_create_stream_queue_size(LOWEST
));
2429 // Cancel the first stream; this will allow the second stream to be created.
2430 EXPECT_TRUE(spdy_stream1
);
2431 spdy_stream1
->Cancel();
2432 EXPECT_FALSE(spdy_stream1
);
2434 EXPECT_EQ(OK
, callback2
.WaitForResult());
2435 EXPECT_EQ(0u, session_
->num_active_streams());
2436 EXPECT_EQ(kInitialMaxConcurrentStreams
, session_
->num_created_streams());
2437 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(LOWEST
));
2439 // Cancel the second stream; this will allow the third stream to be created.
2440 base::WeakPtr
<SpdyStream
> spdy_stream2
= request2
.ReleaseStream();
2441 spdy_stream2
->Cancel();
2442 EXPECT_FALSE(spdy_stream2
);
2444 EXPECT_EQ(OK
, callback3
.WaitForResult());
2445 EXPECT_EQ(0u, session_
->num_active_streams());
2446 EXPECT_EQ(kInitialMaxConcurrentStreams
, session_
->num_created_streams());
2447 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2449 // Cancel the third stream.
2450 base::WeakPtr
<SpdyStream
> spdy_stream3
= request3
.ReleaseStream();
2451 spdy_stream3
->Cancel();
2452 EXPECT_FALSE(spdy_stream3
);
2453 EXPECT_EQ(0u, session_
->num_active_streams());
2454 EXPECT_EQ(kInitialMaxConcurrentStreams
- 1, session_
->num_created_streams());
2455 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2458 // Test that SpdySession::DoReadLoop reads data from the socket
2459 // without yielding. This test makes 32k - 1 bytes of data available
2460 // on the socket for reading. It then verifies that it has read all
2461 // the available data without yielding.
2462 TEST_P(SpdySessionTest
, ReadDataWithoutYielding
) {
2463 session_deps_
.host_resolver
->set_synchronous_mode(true);
2464 session_deps_
.time_func
= InstantaneousReads
;
2466 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2468 scoped_ptr
<SpdyFrame
> req1(
2469 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2470 MockWrite writes
[] = {
2471 CreateMockWrite(*req1
, 0),
2474 // Build buffer of size kYieldAfterBytesRead / 4
2475 // (-spdy_data_frame_size).
2476 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead
);
2477 const int kPayloadSize
=
2478 kYieldAfterBytesRead
/ 4 - framer
.GetControlFrameHeaderSize();
2479 TestDataStream test_stream
;
2480 scoped_refptr
<IOBuffer
> payload(new IOBuffer(kPayloadSize
));
2481 char* payload_data
= payload
->data();
2482 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2484 scoped_ptr
<SpdyFrame
> partial_data_frame(
2485 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2486 scoped_ptr
<SpdyFrame
> finish_data_frame(
2487 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
- 1, DATA_FLAG_FIN
));
2489 scoped_ptr
<SpdyFrame
> resp1(
2490 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2492 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2494 MockRead reads
[] = {
2495 CreateMockRead(*resp1
, 1),
2496 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2497 CreateMockRead(*partial_data_frame
, 3),
2498 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2499 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2500 CreateMockRead(*finish_data_frame
, 6, SYNCHRONOUS
),
2501 MockRead(ASYNC
, 0, 7) // EOF
2504 // Create SpdySession and SpdyStream and send the request.
2505 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2506 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2508 CreateNetworkSession();
2509 CreateInsecureSpdySession();
2511 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2512 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2513 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2514 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2515 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2516 spdy_stream1
->SetDelegate(&delegate1
);
2518 scoped_ptr
<SpdyHeaderBlock
> headers1(
2519 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2520 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2521 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2523 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2525 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2527 // Run until 1st read.
2528 EXPECT_EQ(0u, delegate1
.stream_id());
2529 base::RunLoop().RunUntilIdle();
2530 EXPECT_EQ(1u, delegate1
.stream_id());
2531 EXPECT_EQ(0u, observer
.executed_count());
2533 // Read all the data and verify SpdySession::DoReadLoop has not
2535 data
.CompleteRead();
2536 base::RunLoop().RunUntilIdle();
2537 EXPECT_FALSE(spdy_stream1
);
2539 // Verify task observer's executed_count is zero, which indicates DoRead read
2540 // all the available data.
2541 EXPECT_EQ(0u, observer
.executed_count());
2542 EXPECT_TRUE(data
.AllWriteDataConsumed());
2543 EXPECT_TRUE(data
.AllReadDataConsumed());
2546 // Test that SpdySession::DoReadLoop yields if more than
2547 // |kYieldAfterDurationMilliseconds| has passed. This test uses a mock time
2548 // function that makes the response frame look very slow to read.
2549 TEST_P(SpdySessionTest
, TestYieldingSlowReads
) {
2550 session_deps_
.host_resolver
->set_synchronous_mode(true);
2551 session_deps_
.time_func
= SlowReads
;
2553 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2555 scoped_ptr
<SpdyFrame
> req1(
2556 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2557 MockWrite writes
[] = {
2558 CreateMockWrite(*req1
, 0),
2561 scoped_ptr
<SpdyFrame
> resp1(
2562 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2564 MockRead reads
[] = {
2565 CreateMockRead(*resp1
, 1), MockRead(ASYNC
, 0, 2) // EOF
2568 // Create SpdySession and SpdyStream and send the request.
2569 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2570 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2572 CreateNetworkSession();
2573 CreateInsecureSpdySession();
2575 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2576 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2577 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2578 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2579 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2580 spdy_stream1
->SetDelegate(&delegate1
);
2582 scoped_ptr
<SpdyHeaderBlock
> headers1(
2583 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2584 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2585 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2587 // Set up the TaskObserver to verify that SpdySession::DoReadLoop posts a
2589 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2591 EXPECT_EQ(0u, delegate1
.stream_id());
2592 EXPECT_EQ(0u, observer
.executed_count());
2594 // Read all the data and verify that SpdySession::DoReadLoop has posted a
2596 base::RunLoop().RunUntilIdle();
2597 EXPECT_EQ(1u, delegate1
.stream_id());
2598 EXPECT_FALSE(spdy_stream1
);
2600 // Verify task that the observer's executed_count is 1, which indicates DoRead
2601 // has posted only one task and thus yielded though there is data available
2603 EXPECT_EQ(1u, observer
.executed_count());
2604 EXPECT_TRUE(data
.AllWriteDataConsumed());
2605 EXPECT_TRUE(data
.AllReadDataConsumed());
2608 // Regression test for https://crbug.com/531570.
2609 // Test the case where DoRead() takes long but returns synchronously.
2610 TEST_P(SpdySessionTest
, TestYieldingSlowSynchronousReads
) {
2611 session_deps_
.host_resolver
->set_synchronous_mode(true);
2612 session_deps_
.time_func
= SlowReads
;
2614 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2616 scoped_ptr
<SpdyFrame
> req1(
2617 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2618 MockWrite writes
[] = {
2619 CreateMockWrite(*req1
, 0),
2622 scoped_ptr
<SpdyFrame
> partial_data_frame(
2623 framer
.CreateDataFrame(1, "foo ", 4, DATA_FLAG_NONE
));
2624 scoped_ptr
<SpdyFrame
> finish_data_frame(
2625 framer
.CreateDataFrame(1, "bar", 3, DATA_FLAG_FIN
));
2627 scoped_ptr
<SpdyFrame
> resp1(
2628 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2630 MockRead reads
[] = {
2631 CreateMockRead(*resp1
, 1), MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2632 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2633 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2634 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2635 CreateMockRead(*finish_data_frame
, 6, SYNCHRONOUS
),
2636 MockRead(ASYNC
, 0, 7) // EOF
2639 // Create SpdySession and SpdyStream and send the request.
2640 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2641 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2643 CreateNetworkSession();
2644 CreateInsecureSpdySession();
2646 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2647 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2648 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2649 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2650 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2651 spdy_stream1
->SetDelegate(&delegate1
);
2653 scoped_ptr
<SpdyHeaderBlock
> headers1(
2654 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2655 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2656 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2658 // Run until 1st read.
2659 EXPECT_EQ(0u, delegate1
.stream_id());
2660 base::RunLoop().RunUntilIdle();
2661 EXPECT_EQ(1u, delegate1
.stream_id());
2663 // Read all the data and verify SpdySession::DoReadLoop has posted a task.
2664 data
.CompleteRead();
2665 base::RunLoop().RunUntilIdle();
2666 EXPECT_EQ("foo foo foo bar", delegate1
.TakeReceivedData());
2667 EXPECT_FALSE(spdy_stream1
);
2669 EXPECT_TRUE(data
.AllWriteDataConsumed());
2670 EXPECT_TRUE(data
.AllReadDataConsumed());
2673 // Test that SpdySession::DoReadLoop yields while reading the
2674 // data. This test makes 32k + 1 bytes of data available on the socket
2675 // for reading. It then verifies that DoRead has yielded even though
2676 // there is data available for it to read (i.e, socket()->Read didn't
2677 // return ERR_IO_PENDING during socket reads).
2678 TEST_P(SpdySessionTest
, TestYieldingDuringReadData
) {
2679 session_deps_
.host_resolver
->set_synchronous_mode(true);
2680 session_deps_
.time_func
= InstantaneousReads
;
2682 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2684 scoped_ptr
<SpdyFrame
> req1(
2685 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2686 MockWrite writes
[] = {
2687 CreateMockWrite(*req1
, 0),
2690 // Build buffer of size kYieldAfterBytesRead / 4
2691 // (-spdy_data_frame_size).
2692 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead
);
2693 const int kPayloadSize
=
2694 kYieldAfterBytesRead
/ 4 - framer
.GetControlFrameHeaderSize();
2695 TestDataStream test_stream
;
2696 scoped_refptr
<IOBuffer
> payload(new IOBuffer(kPayloadSize
));
2697 char* payload_data
= payload
->data();
2698 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2700 scoped_ptr
<SpdyFrame
> partial_data_frame(
2701 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2702 scoped_ptr
<SpdyFrame
> finish_data_frame(
2703 framer
.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN
));
2705 scoped_ptr
<SpdyFrame
> resp1(
2706 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2708 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2709 MockRead reads
[] = {
2710 CreateMockRead(*resp1
, 1),
2711 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2712 CreateMockRead(*partial_data_frame
, 3),
2713 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2714 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2715 CreateMockRead(*partial_data_frame
, 6, SYNCHRONOUS
),
2716 CreateMockRead(*finish_data_frame
, 7, SYNCHRONOUS
),
2717 MockRead(ASYNC
, 0, 8) // EOF
2720 // Create SpdySession and SpdyStream and send the request.
2721 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2722 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2724 CreateNetworkSession();
2725 CreateInsecureSpdySession();
2727 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2728 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2729 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2730 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2731 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2732 spdy_stream1
->SetDelegate(&delegate1
);
2734 scoped_ptr
<SpdyHeaderBlock
> headers1(
2735 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2736 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2737 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2739 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a task.
2740 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2742 // Run until 1st read.
2743 EXPECT_EQ(0u, delegate1
.stream_id());
2744 base::RunLoop().RunUntilIdle();
2745 EXPECT_EQ(1u, delegate1
.stream_id());
2746 EXPECT_EQ(0u, observer
.executed_count());
2748 // Read all the data and verify SpdySession::DoReadLoop has posted a task.
2749 data
.CompleteRead();
2750 base::RunLoop().RunUntilIdle();
2751 EXPECT_FALSE(spdy_stream1
);
2753 // Verify task observer's executed_count is 1, which indicates DoRead has
2754 // posted only one task and thus yielded though there is data available for it
2756 EXPECT_EQ(1u, observer
.executed_count());
2757 EXPECT_TRUE(data
.AllWriteDataConsumed());
2758 EXPECT_TRUE(data
.AllReadDataConsumed());
2761 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2762 // + async, by doing the following MockReads.
2764 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2765 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2767 // The above reads 26K synchronously. Since that is less that 32K, we
2768 // will attempt to read again. However, that DoRead() will return
2769 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2770 // yield. When we come back, DoRead() will read the results from the
2771 // async read, and rest of the data synchronously.
2772 TEST_P(SpdySessionTest
, TestYieldingDuringAsyncReadData
) {
2773 session_deps_
.host_resolver
->set_synchronous_mode(true);
2774 session_deps_
.time_func
= InstantaneousReads
;
2776 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2778 scoped_ptr
<SpdyFrame
> req1(
2779 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2780 MockWrite writes
[] = {
2781 CreateMockWrite(*req1
, 0),
2784 // Build buffer of size kYieldAfterBytesRead / 4
2785 // (-spdy_data_frame_size).
2786 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead
);
2787 TestDataStream test_stream
;
2788 const int kEightKPayloadSize
=
2789 kYieldAfterBytesRead
/ 4 - framer
.GetControlFrameHeaderSize();
2790 scoped_refptr
<IOBuffer
> eightk_payload(new IOBuffer(kEightKPayloadSize
));
2791 char* eightk_payload_data
= eightk_payload
->data();
2792 test_stream
.GetBytes(eightk_payload_data
, kEightKPayloadSize
);
2794 // Build buffer of 2k size.
2795 TestDataStream test_stream2
;
2796 const int kTwoKPayloadSize
= kEightKPayloadSize
- 6 * 1024;
2797 scoped_refptr
<IOBuffer
> twok_payload(new IOBuffer(kTwoKPayloadSize
));
2798 char* twok_payload_data
= twok_payload
->data();
2799 test_stream2
.GetBytes(twok_payload_data
, kTwoKPayloadSize
);
2801 scoped_ptr
<SpdyFrame
> eightk_data_frame(framer
.CreateDataFrame(
2802 1, eightk_payload_data
, kEightKPayloadSize
, DATA_FLAG_NONE
));
2803 scoped_ptr
<SpdyFrame
> twok_data_frame(framer
.CreateDataFrame(
2804 1, twok_payload_data
, kTwoKPayloadSize
, DATA_FLAG_NONE
));
2805 scoped_ptr
<SpdyFrame
> finish_data_frame(framer
.CreateDataFrame(
2806 1, "h", 1, DATA_FLAG_FIN
));
2808 scoped_ptr
<SpdyFrame
> resp1(
2809 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2811 MockRead reads
[] = {
2812 CreateMockRead(*resp1
, 1),
2813 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2814 CreateMockRead(*eightk_data_frame
, 3),
2815 CreateMockRead(*eightk_data_frame
, 4, SYNCHRONOUS
),
2816 CreateMockRead(*eightk_data_frame
, 5, SYNCHRONOUS
),
2817 CreateMockRead(*twok_data_frame
, 6, SYNCHRONOUS
),
2818 CreateMockRead(*eightk_data_frame
, 7, ASYNC
),
2819 CreateMockRead(*eightk_data_frame
, 8, SYNCHRONOUS
),
2820 CreateMockRead(*eightk_data_frame
, 9, SYNCHRONOUS
),
2821 CreateMockRead(*eightk_data_frame
, 10, SYNCHRONOUS
),
2822 CreateMockRead(*twok_data_frame
, 11, SYNCHRONOUS
),
2823 CreateMockRead(*finish_data_frame
, 12, SYNCHRONOUS
),
2824 MockRead(ASYNC
, 0, 13) // EOF
2827 // Create SpdySession and SpdyStream and send the request.
2828 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2829 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2831 CreateNetworkSession();
2832 CreateInsecureSpdySession();
2834 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2835 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2836 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2837 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2838 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2839 spdy_stream1
->SetDelegate(&delegate1
);
2841 scoped_ptr
<SpdyHeaderBlock
> headers1(
2842 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2843 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2844 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2846 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2847 // posting of tasks.
2848 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2850 // Run until 1st read.
2851 EXPECT_EQ(0u, delegate1
.stream_id());
2852 base::RunLoop().RunUntilIdle();
2853 EXPECT_EQ(1u, delegate1
.stream_id());
2854 EXPECT_EQ(0u, observer
.executed_count());
2856 // Read all the data and verify SpdySession::DoReadLoop has posted a
2858 data
.CompleteRead();
2859 base::RunLoop().RunUntilIdle();
2860 EXPECT_FALSE(spdy_stream1
);
2862 // Verify task observer's executed_count is 1, which indicates DoRead has
2863 // posted only one task and thus yielded though there is data available for
2865 EXPECT_EQ(1u, observer
.executed_count());
2866 EXPECT_TRUE(data
.AllWriteDataConsumed());
2867 EXPECT_TRUE(data
.AllReadDataConsumed());
2870 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2871 // nothing blows up.
2872 TEST_P(SpdySessionTest
, GoAwayWhileInDoReadLoop
) {
2873 session_deps_
.host_resolver
->set_synchronous_mode(true);
2875 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2877 scoped_ptr
<SpdyFrame
> req1(
2878 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2879 MockWrite writes
[] = {
2880 CreateMockWrite(*req1
, 0),
2883 scoped_ptr
<SpdyFrame
> resp1(
2884 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2885 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2886 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
2888 MockRead reads
[] = {
2889 CreateMockRead(*resp1
, 1),
2890 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2891 CreateMockRead(*body1
, 3),
2892 CreateMockRead(*goaway
, 4),
2895 // Create SpdySession and SpdyStream and send the request.
2896 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2897 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2899 CreateNetworkSession();
2900 CreateInsecureSpdySession();
2902 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2903 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2904 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2905 spdy_stream1
->SetDelegate(&delegate1
);
2906 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2907 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2909 scoped_ptr
<SpdyHeaderBlock
> headers1(
2910 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2911 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2912 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2914 // Run until 1st read.
2915 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2916 base::RunLoop().RunUntilIdle();
2917 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2919 // Run until GoAway.
2920 data
.CompleteRead();
2921 base::RunLoop().RunUntilIdle();
2922 EXPECT_FALSE(spdy_stream1
);
2923 EXPECT_TRUE(data
.AllWriteDataConsumed());
2924 EXPECT_TRUE(data
.AllReadDataConsumed());
2925 EXPECT_FALSE(session_
);
2928 // Within this framework, a SpdySession should be initialized with
2929 // flow control disabled for protocol version 2, with flow control
2930 // enabled only for streams for protocol version 3, and with flow
2931 // control enabled for streams and sessions for higher versions.
2932 TEST_P(SpdySessionTest
, ProtocolNegotiation
) {
2933 session_deps_
.host_resolver
->set_synchronous_mode(true);
2935 MockRead reads
[] = {
2936 MockRead(SYNCHRONOUS
, 0, 0) // EOF
2938 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2939 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2941 CreateNetworkSession();
2942 session_
= CreateFakeSpdySession(spdy_session_pool_
, key_
);
2944 EXPECT_EQ(spdy_util_
.spdy_version(),
2945 session_
->buffered_spdy_framer_
->protocol_version());
2946 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
2947 session_
->flow_control_state());
2948 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
2949 session_
->session_send_window_size_
);
2950 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
2951 session_
->session_recv_window_size_
);
2952 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
2955 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2956 // pointers to the idle session are currently held.
2957 TEST_P(SpdySessionTest
, CloseOneIdleConnection
) {
2958 ClientSocketPoolManager::set_max_sockets_per_group(
2959 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2960 ClientSocketPoolManager::set_max_sockets_per_pool(
2961 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2963 MockRead reads
[] = {
2964 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2966 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2967 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2968 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2970 CreateNetworkSession();
2972 TransportClientSocketPool
* pool
=
2973 http_session_
->GetTransportSocketPool(
2974 HttpNetworkSession::NORMAL_SOCKET_POOL
);
2976 // Create an idle SPDY session.
2977 CreateInsecureSpdySession();
2978 EXPECT_FALSE(pool
->IsStalled());
2980 // Trying to create a new connection should cause the pool to be stalled, and
2981 // post a task asynchronously to try and close the session.
2982 TestCompletionCallback callback2
;
2983 HostPortPair
host_port2("2.com", 80);
2984 scoped_refptr
<TransportSocketParams
> params2(
2985 new TransportSocketParams(
2986 host_port2
, false, false, OnHostResolutionCallback(),
2987 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
2988 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
2989 EXPECT_EQ(ERR_IO_PENDING
,
2990 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
2991 callback2
.callback(), pool
, BoundNetLog()));
2992 EXPECT_TRUE(pool
->IsStalled());
2994 // The socket pool should close the connection asynchronously and establish a
2996 EXPECT_EQ(OK
, callback2
.WaitForResult());
2997 EXPECT_FALSE(pool
->IsStalled());
2998 EXPECT_FALSE(session_
);
3001 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3002 // pointers to the idle session are currently held, in the case the SPDY session
3004 TEST_P(SpdySessionTest
, CloseOneIdleConnectionWithAlias
) {
3005 ClientSocketPoolManager::set_max_sockets_per_group(
3006 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3007 ClientSocketPoolManager::set_max_sockets_per_pool(
3008 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3010 MockRead reads
[] = {
3011 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3013 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
3014 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3015 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3017 session_deps_
.host_resolver
->set_synchronous_mode(true);
3018 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3019 "1.com", "192.168.0.2", std::string());
3020 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3021 "2.com", "192.168.0.2", std::string());
3022 // Not strictly needed.
3023 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3024 "3.com", "192.168.0.3", std::string());
3026 CreateNetworkSession();
3028 TransportClientSocketPool
* pool
=
3029 http_session_
->GetTransportSocketPool(
3030 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3032 // Create an idle SPDY session.
3033 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3034 PRIVACY_MODE_DISABLED
);
3035 base::WeakPtr
<SpdySession
> session1
=
3036 ::net::CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3037 EXPECT_FALSE(pool
->IsStalled());
3039 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3040 SpdySessionKey
key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3041 PRIVACY_MODE_DISABLED
);
3042 HostResolver::RequestInfo
info(key2
.host_port_pair());
3043 AddressList addresses
;
3044 // Pre-populate the DNS cache, since a synchronous resolution is required in
3045 // order to create the alias.
3046 session_deps_
.host_resolver
->Resolve(info
, DEFAULT_PRIORITY
, &addresses
,
3047 CompletionCallback(), nullptr,
3049 // Get a session for |key2|, which should return the session created earlier.
3050 base::WeakPtr
<SpdySession
> session2
=
3051 spdy_session_pool_
->FindAvailableSession(key2
, BoundNetLog());
3052 ASSERT_EQ(session1
.get(), session2
.get());
3053 EXPECT_FALSE(pool
->IsStalled());
3055 // Trying to create a new connection should cause the pool to be stalled, and
3056 // post a task asynchronously to try and close the session.
3057 TestCompletionCallback callback3
;
3058 HostPortPair
host_port3("3.com", 80);
3059 scoped_refptr
<TransportSocketParams
> params3(
3060 new TransportSocketParams(
3061 host_port3
, false, false, OnHostResolutionCallback(),
3062 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3063 scoped_ptr
<ClientSocketHandle
> connection3(new ClientSocketHandle
);
3064 EXPECT_EQ(ERR_IO_PENDING
,
3065 connection3
->Init(host_port3
.ToString(), params3
, DEFAULT_PRIORITY
,
3066 callback3
.callback(), pool
, BoundNetLog()));
3067 EXPECT_TRUE(pool
->IsStalled());
3069 // The socket pool should close the connection asynchronously and establish a
3071 EXPECT_EQ(OK
, callback3
.WaitForResult());
3072 EXPECT_FALSE(pool
->IsStalled());
3073 EXPECT_FALSE(session1
);
3074 EXPECT_FALSE(session2
);
3077 // Tests that when a SPDY session becomes idle, it closes itself if there is
3078 // a lower layer pool stalled on the per-pool socket limit.
3079 TEST_P(SpdySessionTest
, CloseSessionOnIdleWhenPoolStalled
) {
3080 ClientSocketPoolManager::set_max_sockets_per_group(
3081 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3082 ClientSocketPoolManager::set_max_sockets_per_pool(
3083 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3085 MockRead reads
[] = {
3086 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3088 scoped_ptr
<SpdyFrame
> req1(
3089 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3090 scoped_ptr
<SpdyFrame
> cancel1(
3091 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3092 MockWrite writes
[] = {
3093 CreateMockWrite(*req1
, 1),
3094 CreateMockWrite(*cancel1
, 1),
3096 StaticSocketDataProvider
data(reads
, arraysize(reads
),
3097 writes
, arraysize(writes
));
3098 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3100 MockRead http_reads
[] = {
3101 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3103 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
), nullptr,
3105 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
3108 CreateNetworkSession();
3110 TransportClientSocketPool
* pool
=
3111 http_session_
->GetTransportSocketPool(
3112 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3114 // Create a SPDY session.
3115 CreateInsecureSpdySession();
3116 EXPECT_FALSE(pool
->IsStalled());
3118 // Create a stream using the session, and send a request.
3120 TestCompletionCallback callback1
;
3121 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3122 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
, session_
,
3123 test_url_
, DEFAULT_PRIORITY
, BoundNetLog());
3124 ASSERT_TRUE(spdy_stream1
.get());
3125 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3126 spdy_stream1
->SetDelegate(&delegate1
);
3128 scoped_ptr
<SpdyHeaderBlock
> headers1(
3129 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
3130 EXPECT_EQ(ERR_IO_PENDING
,
3131 spdy_stream1
->SendRequestHeaders(
3132 headers1
.Pass(), NO_MORE_DATA_TO_SEND
));
3133 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3135 base::RunLoop().RunUntilIdle();
3137 // Trying to create a new connection should cause the pool to be stalled, and
3138 // post a task asynchronously to try and close the session.
3139 TestCompletionCallback callback2
;
3140 HostPortPair
host_port2("2.com", 80);
3141 scoped_refptr
<TransportSocketParams
> params2(
3142 new TransportSocketParams(
3143 host_port2
, false, false, OnHostResolutionCallback(),
3144 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3145 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3146 EXPECT_EQ(ERR_IO_PENDING
,
3147 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3148 callback2
.callback(), pool
, BoundNetLog()));
3149 EXPECT_TRUE(pool
->IsStalled());
3151 // Running the message loop should cause the socket pool to ask the SPDY
3152 // session to close an idle socket, but since the socket is in use, nothing
3154 base::RunLoop().RunUntilIdle();
3155 EXPECT_TRUE(pool
->IsStalled());
3156 EXPECT_FALSE(callback2
.have_result());
3158 // Cancelling the request should result in the session's socket being
3159 // closed, since the pool is stalled.
3160 ASSERT_TRUE(spdy_stream1
.get());
3161 spdy_stream1
->Cancel();
3162 base::RunLoop().RunUntilIdle();
3163 ASSERT_FALSE(pool
->IsStalled());
3164 EXPECT_EQ(OK
, callback2
.WaitForResult());
3167 // Verify that SpdySessionKey and therefore SpdySession is different when
3168 // privacy mode is enabled or disabled.
3169 TEST_P(SpdySessionTest
, SpdySessionKeyPrivacyMode
) {
3170 CreateNetworkSession();
3172 HostPortPair
host_port_pair("www.example.org", 443);
3173 SpdySessionKey
key_privacy_enabled(host_port_pair
, ProxyServer::Direct(),
3174 PRIVACY_MODE_ENABLED
);
3175 SpdySessionKey
key_privacy_disabled(host_port_pair
, ProxyServer::Direct(),
3176 PRIVACY_MODE_DISABLED
);
3178 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3179 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3181 // Add SpdySession with PrivacyMode Enabled to the pool.
3182 base::WeakPtr
<SpdySession
> session_privacy_enabled
=
3183 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_enabled
);
3185 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3186 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3188 // Add SpdySession with PrivacyMode Disabled to the pool.
3189 base::WeakPtr
<SpdySession
> session_privacy_disabled
=
3190 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_disabled
);
3192 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3193 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3195 session_privacy_enabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3196 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3197 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3199 session_privacy_disabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3200 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3201 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3204 // Delegate that creates another stream when its stream is closed.
3205 class StreamCreatingDelegate
: public test::StreamDelegateDoNothing
{
3207 StreamCreatingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3208 const base::WeakPtr
<SpdySession
>& session
)
3209 : StreamDelegateDoNothing(stream
),
3210 session_(session
) {}
3212 ~StreamCreatingDelegate() override
{}
3214 void OnClose(int status
) override
{
3215 GURL
url(kDefaultURL
);
3217 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3218 session_
, url
, MEDIUM
, BoundNetLog()));
3222 const base::WeakPtr
<SpdySession
> session_
;
3225 // Create another stream in response to a stream being reset. Nothing
3226 // should blow up. This is a regression test for
3227 // http://crbug.com/263690 .
3228 TEST_P(SpdySessionTest
, CreateStreamOnStreamReset
) {
3229 session_deps_
.host_resolver
->set_synchronous_mode(true);
3231 scoped_ptr
<SpdyFrame
> req(
3232 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
3233 MockWrite writes
[] = {
3234 CreateMockWrite(*req
, 0),
3237 scoped_ptr
<SpdyFrame
> rst(
3238 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
3239 MockRead reads
[] = {
3240 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3241 CreateMockRead(*rst
, 2),
3242 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3243 MockRead(ASYNC
, 0, 4) // EOF
3245 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3246 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3248 CreateNetworkSession();
3249 CreateInsecureSpdySession();
3251 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
3252 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
3253 ASSERT_TRUE(spdy_stream
.get() != nullptr);
3254 EXPECT_EQ(0u, spdy_stream
->stream_id());
3256 StreamCreatingDelegate
delegate(spdy_stream
, session_
);
3257 spdy_stream
->SetDelegate(&delegate
);
3259 scoped_ptr
<SpdyHeaderBlock
> headers(
3260 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
3261 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
3262 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
3264 EXPECT_EQ(0u, spdy_stream
->stream_id());
3266 base::RunLoop().RunUntilIdle();
3268 EXPECT_EQ(1u, spdy_stream
->stream_id());
3270 // Cause the stream to be reset, which should cause another stream
3272 data
.CompleteRead();
3273 base::RunLoop().RunUntilIdle();
3275 EXPECT_FALSE(spdy_stream
);
3276 EXPECT_TRUE(delegate
.StreamIsClosed());
3277 EXPECT_EQ(0u, session_
->num_active_streams());
3278 EXPECT_EQ(1u, session_
->num_created_streams());
3280 data
.CompleteRead();
3281 base::RunLoop().RunUntilIdle();
3282 EXPECT_FALSE(session_
);
3285 TEST_P(SpdySessionTest
, UpdateStreamsSendWindowSize
) {
3286 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3288 SettingsMap new_settings
;
3289 int32 window_size
= 1;
3290 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
3291 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, window_size
);
3293 // Set up the socket so we read a SETTINGS frame that sets
3294 // INITIAL_WINDOW_SIZE.
3295 scoped_ptr
<SpdyFrame
> settings_frame(
3296 spdy_util_
.ConstructSpdySettings(new_settings
));
3297 MockRead reads
[] = {
3298 CreateMockRead(*settings_frame
, 0),
3299 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3300 MockRead(ASYNC
, 0, 2) // EOF
3303 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
3304 MockWrite writes
[] = {
3305 CreateMockWrite(*settings_ack
, 3),
3308 session_deps_
.host_resolver
->set_synchronous_mode(true);
3310 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3311 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3313 CreateNetworkSession();
3314 CreateInsecureSpdySession();
3315 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
3316 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
3317 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
3318 TestCompletionCallback callback1
;
3319 EXPECT_NE(spdy_stream1
->send_window_size(), window_size
);
3321 // Process the SETTINGS frame.
3322 base::RunLoop().RunUntilIdle();
3323 EXPECT_EQ(session_
->stream_initial_send_window_size(), window_size
);
3324 EXPECT_EQ(spdy_stream1
->send_window_size(), window_size
);
3326 // Release the first one, this will allow the second to be created.
3327 spdy_stream1
->Cancel();
3328 EXPECT_FALSE(spdy_stream1
);
3330 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
3331 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
3332 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
3333 EXPECT_EQ(spdy_stream2
->send_window_size(), window_size
);
3334 spdy_stream2
->Cancel();
3335 EXPECT_FALSE(spdy_stream2
);
3337 EXPECT_TRUE(session_
);
3338 data
.CompleteRead();
3339 base::RunLoop().RunUntilIdle();
3340 EXPECT_FALSE(session_
);
3343 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3344 // adjust the session receive window size. In addition,
3345 // SpdySession::IncreaseRecvWindowSize should trigger
3346 // sending a WINDOW_UPDATE frame for a large enough delta.
3347 TEST_P(SpdySessionTest
, AdjustRecvWindowSize
) {
3348 session_deps_
.host_resolver
->set_synchronous_mode(true);
3350 const int32 initial_window_size
=
3351 SpdySession::GetDefaultInitialWindowSize(GetParam());
3352 const int32 delta_window_size
= 100;
3354 MockRead reads
[] = {
3355 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
3357 scoped_ptr
<SpdyFrame
> window_update(spdy_util_
.ConstructSpdyWindowUpdate(
3358 kSessionFlowControlStreamId
, initial_window_size
+ delta_window_size
));
3359 MockWrite writes
[] = {
3360 CreateMockWrite(*window_update
, 0),
3362 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3363 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3365 CreateNetworkSession();
3366 CreateInsecureSpdySession();
3367 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3368 session_
->flow_control_state());
3370 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3371 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3373 session_
->IncreaseRecvWindowSize(delta_window_size
);
3374 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3375 session_
->session_recv_window_size_
);
3376 EXPECT_EQ(delta_window_size
, session_
->session_unacked_recv_window_bytes_
);
3378 // Should trigger sending a WINDOW_UPDATE frame.
3379 session_
->IncreaseRecvWindowSize(initial_window_size
);
3380 EXPECT_EQ(initial_window_size
+ delta_window_size
+ initial_window_size
,
3381 session_
->session_recv_window_size_
);
3382 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3384 base::RunLoop().RunUntilIdle();
3386 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3387 session_
->in_io_loop_
= true;
3388 session_
->DecreaseRecvWindowSize(initial_window_size
+ delta_window_size
+
3389 initial_window_size
);
3390 session_
->in_io_loop_
= false;
3391 EXPECT_EQ(0, session_
->session_recv_window_size_
);
3392 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3394 EXPECT_TRUE(session_
);
3395 data
.CompleteRead();
3396 base::RunLoop().RunUntilIdle();
3397 EXPECT_FALSE(session_
);
3400 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3401 // adjust the session send window size when the "enable_spdy_31" flag
3403 TEST_P(SpdySessionTest
, AdjustSendWindowSize
) {
3404 session_deps_
.host_resolver
->set_synchronous_mode(true);
3406 MockRead reads
[] = {
3407 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3409 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
3410 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3412 CreateNetworkSession();
3413 session_
= CreateFakeSpdySession(spdy_session_pool_
, key_
);
3414 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3415 session_
->flow_control_state());
3417 const int32 initial_window_size
=
3418 SpdySession::GetDefaultInitialWindowSize(GetParam());
3419 const int32 delta_window_size
= 100;
3421 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3423 session_
->IncreaseSendWindowSize(delta_window_size
);
3424 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3425 session_
->session_send_window_size_
);
3427 session_
->DecreaseSendWindowSize(delta_window_size
);
3428 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3431 // Incoming data for an inactive stream should not cause the session
3432 // receive window size to decrease, but it should cause the unacked
3433 // bytes to increase.
3434 TEST_P(SpdySessionTest
, SessionFlowControlInactiveStream
) {
3435 session_deps_
.host_resolver
->set_synchronous_mode(true);
3437 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(1, false));
3438 MockRead reads
[] = {
3439 CreateMockRead(*resp
, 0),
3440 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3441 MockRead(ASYNC
, 0, 2) // EOF
3443 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
3444 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3446 CreateNetworkSession();
3447 CreateInsecureSpdySession();
3448 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3449 session_
->flow_control_state());
3451 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3452 session_
->session_recv_window_size_
);
3453 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3455 base::RunLoop().RunUntilIdle();
3457 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3458 session_
->session_recv_window_size_
);
3459 EXPECT_EQ(kUploadDataSize
, session_
->session_unacked_recv_window_bytes_
);
3461 EXPECT_TRUE(session_
);
3462 data
.CompleteRead();
3463 base::RunLoop().RunUntilIdle();
3464 EXPECT_FALSE(session_
);
3467 // The frame header is not included in flow control, but frame payload
3468 // (including optional pad length and padding) is.
3469 TEST_P(SpdySessionTest
, SessionFlowControlPadding
) {
3470 // Padding only exists in HTTP/2.
3471 if (GetParam() < kProtoHTTP2
)
3474 session_deps_
.host_resolver
->set_synchronous_mode(true);
3476 const int padding_length
= 42;
3477 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(
3478 1, kUploadData
, kUploadDataSize
, false, padding_length
));
3479 MockRead reads
[] = {
3480 CreateMockRead(*resp
, 0),
3481 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3482 MockRead(ASYNC
, 0, 2) // EOF
3484 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
3485 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3487 CreateNetworkSession();
3488 CreateInsecureSpdySession();
3489 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3490 session_
->flow_control_state());
3492 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3493 session_
->session_recv_window_size_
);
3494 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3496 base::RunLoop().RunUntilIdle();
3498 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3499 session_
->session_recv_window_size_
);
3500 EXPECT_EQ(kUploadDataSize
+ padding_length
,
3501 session_
->session_unacked_recv_window_bytes_
);
3503 data
.CompleteRead();
3504 base::RunLoop().RunUntilIdle();
3505 EXPECT_FALSE(session_
);
3508 // Peer sends more data than stream level receiving flow control window.
3509 TEST_P(SpdySessionTest
, StreamFlowControlTooMuchData
) {
3510 const int32 stream_max_recv_window_size
= 1024;
3511 const int32 data_frame_size
= 2 * stream_max_recv_window_size
;
3513 scoped_ptr
<SpdyFrame
> req(
3514 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3515 scoped_ptr
<SpdyFrame
> rst(
3516 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
3517 MockWrite writes
[] = {
3518 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 4),
3521 scoped_ptr
<SpdyFrame
> resp(
3522 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3523 const std::string
payload(data_frame_size
, 'a');
3524 scoped_ptr
<SpdyFrame
> data_frame(spdy_util_
.ConstructSpdyBodyFrame(
3525 1, payload
.data(), data_frame_size
, false));
3526 MockRead reads
[] = {
3527 CreateMockRead(*resp
, 1),
3528 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
3529 CreateMockRead(*data_frame
, 3),
3530 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
3531 MockRead(ASYNC
, 0, 6),
3534 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3535 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3536 CreateNetworkSession();
3538 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
3539 pool_peer
.SetStreamInitialRecvWindowSize(stream_max_recv_window_size
);
3540 CreateInsecureSpdySession();
3541 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM
, session_
->flow_control_state());
3543 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
3544 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
3545 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3547 test::StreamDelegateDoNothing
delegate(spdy_stream
);
3548 spdy_stream
->SetDelegate(&delegate
);
3550 scoped_ptr
<SpdyHeaderBlock
> headers(
3551 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
3552 EXPECT_EQ(ERR_IO_PENDING
, spdy_stream
->SendRequestHeaders(
3553 headers
.Pass(), NO_MORE_DATA_TO_SEND
));
3555 // Request and response.
3556 base::RunLoop().RunUntilIdle();
3557 EXPECT_EQ(1u, spdy_stream
->stream_id());
3559 // Too large data frame causes flow control error, should close stream.
3560 data
.CompleteRead();
3561 base::RunLoop().RunUntilIdle();
3562 EXPECT_FALSE(spdy_stream
);
3564 EXPECT_TRUE(session_
);
3565 data
.CompleteRead();
3566 base::RunLoop().RunUntilIdle();
3567 EXPECT_FALSE(session_
);
3570 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3571 // deltas in the receiving window size when checking incoming frames for flow
3572 // control errors at session level.
3573 TEST_P(SpdySessionTest
, SessionFlowControlTooMuchDataTwoDataFrames
) {
3574 const int32 session_max_recv_window_size
= 500;
3575 const int32 first_data_frame_size
= 200;
3576 const int32 second_data_frame_size
= 400;
3578 // First data frame should not trigger a WINDOW_UPDATE.
3579 ASSERT_GT(session_max_recv_window_size
/ 2, first_data_frame_size
);
3580 // Second data frame would be fine had there been a WINDOW_UPDATE.
3581 ASSERT_GT(session_max_recv_window_size
, second_data_frame_size
);
3582 // But in fact, the two data frames together overflow the receiving window at
3584 ASSERT_LT(session_max_recv_window_size
,
3585 first_data_frame_size
+ second_data_frame_size
);
3587 session_deps_
.host_resolver
->set_synchronous_mode(true);
3589 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3590 0, GOAWAY_FLOW_CONTROL_ERROR
,
3591 "delta_window_size is 400 in DecreaseRecvWindowSize, which is larger "
3592 "than the receive window size of 500"));
3593 MockWrite writes
[] = {
3594 CreateMockWrite(*goaway
, 4),
3597 const std::string
first_data_frame(first_data_frame_size
, 'a');
3598 scoped_ptr
<SpdyFrame
> first(spdy_util_
.ConstructSpdyBodyFrame(
3599 1, first_data_frame
.data(), first_data_frame_size
, false));
3600 const std::string
second_data_frame(second_data_frame_size
, 'b');
3601 scoped_ptr
<SpdyFrame
> second(spdy_util_
.ConstructSpdyBodyFrame(
3602 1, second_data_frame
.data(), second_data_frame_size
, false));
3603 MockRead reads
[] = {
3604 CreateMockRead(*first
, 0),
3605 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3606 CreateMockRead(*second
, 2),
3607 MockRead(ASYNC
, 0, 3),
3609 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3610 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3612 CreateNetworkSession();
3613 CreateInsecureSpdySession();
3614 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3615 session_
->flow_control_state());
3616 // Setting session level receiving window size to smaller than initial is not
3617 // possible via SpdySessionPoolPeer.
3618 session_
->session_recv_window_size_
= session_max_recv_window_size
;
3620 // First data frame is immediately consumed and does not trigger
3622 base::RunLoop().RunUntilIdle();
3623 EXPECT_EQ(first_data_frame_size
,
3624 session_
->session_unacked_recv_window_bytes_
);
3625 EXPECT_EQ(session_max_recv_window_size
, session_
->session_recv_window_size_
);
3626 EXPECT_EQ(SpdySession::STATE_AVAILABLE
, session_
->availability_state_
);
3628 // Second data frame overflows receiving window, causes session to close.
3629 data
.CompleteRead();
3630 base::RunLoop().RunUntilIdle();
3631 EXPECT_EQ(SpdySession::STATE_DRAINING
, session_
->availability_state_
);
3634 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3635 // deltas in the receiving window size when checking incoming data frames for
3636 // flow control errors at stream level.
3637 TEST_P(SpdySessionTest
, StreamFlowControlTooMuchDataTwoDataFrames
) {
3638 const int32 stream_max_recv_window_size
= 500;
3639 const int32 first_data_frame_size
= 200;
3640 const int32 second_data_frame_size
= 400;
3642 // First data frame should not trigger a WINDOW_UPDATE.
3643 ASSERT_GT(stream_max_recv_window_size
/ 2, first_data_frame_size
);
3644 // Second data frame would be fine had there been a WINDOW_UPDATE.
3645 ASSERT_GT(stream_max_recv_window_size
, second_data_frame_size
);
3646 // But in fact, they should overflow the receiving window at stream level.
3647 ASSERT_LT(stream_max_recv_window_size
,
3648 first_data_frame_size
+ second_data_frame_size
);
3650 scoped_ptr
<SpdyFrame
> req(
3651 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3652 scoped_ptr
<SpdyFrame
> rst(
3653 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
3654 MockWrite writes
[] = {
3655 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 6),
3658 scoped_ptr
<SpdyFrame
> resp(
3659 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3660 const std::string
first_data_frame(first_data_frame_size
, 'a');
3661 scoped_ptr
<SpdyFrame
> first(spdy_util_
.ConstructSpdyBodyFrame(
3662 1, first_data_frame
.data(), first_data_frame_size
, false));
3663 const std::string
second_data_frame(second_data_frame_size
, 'b');
3664 scoped_ptr
<SpdyFrame
> second(spdy_util_
.ConstructSpdyBodyFrame(
3665 1, second_data_frame
.data(), second_data_frame_size
, false));
3666 MockRead reads
[] = {
3667 CreateMockRead(*resp
, 1),
3668 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
3669 CreateMockRead(*first
, 3),
3670 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
3671 CreateMockRead(*second
, 5),
3672 MockRead(ASYNC
, ERR_IO_PENDING
, 7),
3673 MockRead(ASYNC
, 0, 8),
3676 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3677 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3679 CreateNetworkSession();
3680 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
3681 pool_peer
.SetStreamInitialRecvWindowSize(stream_max_recv_window_size
);
3683 CreateInsecureSpdySession();
3684 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM
, session_
->flow_control_state());
3686 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
3687 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
3688 test::StreamDelegateDoNothing
delegate(spdy_stream
);
3689 spdy_stream
->SetDelegate(&delegate
);
3691 scoped_ptr
<SpdyHeaderBlock
> headers(
3692 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
3693 EXPECT_EQ(ERR_IO_PENDING
, spdy_stream
->SendRequestHeaders(
3694 headers
.Pass(), NO_MORE_DATA_TO_SEND
));
3696 // Request and response.
3697 base::RunLoop().RunUntilIdle();
3698 EXPECT_TRUE(spdy_stream
->IsLocallyClosed());
3699 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3701 // First data frame.
3702 data
.CompleteRead();
3703 base::RunLoop().RunUntilIdle();
3704 EXPECT_TRUE(spdy_stream
->IsLocallyClosed());
3705 EXPECT_EQ(stream_max_recv_window_size
- first_data_frame_size
,
3706 spdy_stream
->recv_window_size());
3708 // Consume first data frame. This does not trigger a WINDOW_UPDATE.
3709 std::string received_data
= delegate
.TakeReceivedData();
3710 EXPECT_EQ(static_cast<size_t>(first_data_frame_size
), received_data
.size());
3711 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3713 // Second data frame overflows receiving window, causes the stream to close.
3714 data
.CompleteRead();
3715 base::RunLoop().RunUntilIdle();
3716 EXPECT_FALSE(spdy_stream
.get());
3719 EXPECT_TRUE(session_
);
3720 data
.CompleteRead();
3721 base::RunLoop().RunUntilIdle();
3722 EXPECT_FALSE(session_
);
3725 // A delegate that drops any received data.
3726 class DropReceivedDataDelegate
: public test::StreamDelegateSendImmediate
{
3728 DropReceivedDataDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3729 base::StringPiece data
)
3730 : StreamDelegateSendImmediate(stream
, data
) {}
3732 ~DropReceivedDataDelegate() override
{}
3734 // Drop any received data.
3735 void OnDataReceived(scoped_ptr
<SpdyBuffer
> buffer
) override
{}
3738 // Send data back and forth but use a delegate that drops its received
3739 // data. The receive window should still increase to its original
3740 // value, i.e. we shouldn't "leak" receive window bytes.
3741 TEST_P(SpdySessionTest
, SessionFlowControlNoReceiveLeaks
) {
3742 const int32 msg_data_size
= 100;
3743 const std::string
msg_data(msg_data_size
, 'a');
3745 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3746 kDefaultURL
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
3747 scoped_ptr
<SpdyFrame
> msg(
3748 spdy_util_
.ConstructSpdyBodyFrame(
3749 1, msg_data
.data(), msg_data_size
, false));
3750 MockWrite writes
[] = {
3751 CreateMockWrite(*req
, 0),
3752 CreateMockWrite(*msg
, 2),
3755 scoped_ptr
<SpdyFrame
> resp(
3756 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3757 scoped_ptr
<SpdyFrame
> echo(
3758 spdy_util_
.ConstructSpdyBodyFrame(
3759 1, msg_data
.data(), msg_data_size
, false));
3760 scoped_ptr
<SpdyFrame
> window_update(
3761 spdy_util_
.ConstructSpdyWindowUpdate(
3762 kSessionFlowControlStreamId
, msg_data_size
));
3763 MockRead reads
[] = {
3764 CreateMockRead(*resp
, 1),
3765 CreateMockRead(*echo
, 3),
3766 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
3767 MockRead(ASYNC
, 0, 5) // EOF
3770 // Create SpdySession and SpdyStream and send the request.
3771 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3772 session_deps_
.host_resolver
->set_synchronous_mode(true);
3773 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3775 CreateNetworkSession();
3776 CreateInsecureSpdySession();
3778 base::WeakPtr
<SpdyStream
> stream
= CreateStreamSynchronously(
3779 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
3780 ASSERT_TRUE(stream
.get() != nullptr);
3781 EXPECT_EQ(0u, stream
->stream_id());
3783 DropReceivedDataDelegate
delegate(stream
, msg_data
);
3784 stream
->SetDelegate(&delegate
);
3786 scoped_ptr
<SpdyHeaderBlock
> headers(
3787 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, msg_data_size
));
3788 EXPECT_EQ(ERR_IO_PENDING
,
3789 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3790 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3792 const int32 initial_window_size
=
3793 SpdySession::GetDefaultInitialWindowSize(GetParam());
3794 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3795 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3797 base::RunLoop().RunUntilIdle();
3799 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3800 EXPECT_EQ(msg_data_size
, session_
->session_unacked_recv_window_bytes_
);
3803 EXPECT_FALSE(stream
);
3805 EXPECT_EQ(OK
, delegate
.WaitForClose());
3807 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3808 EXPECT_EQ(msg_data_size
, session_
->session_unacked_recv_window_bytes_
);
3810 data
.CompleteRead();
3811 base::RunLoop().RunUntilIdle();
3812 EXPECT_FALSE(session_
);
3815 // Send data back and forth but close the stream before its data frame
3816 // can be written to the socket. The send window should then increase
3817 // to its original value, i.e. we shouldn't "leak" send window bytes.
3818 TEST_P(SpdySessionTest
, SessionFlowControlNoSendLeaks
) {
3819 const int32 msg_data_size
= 100;
3820 const std::string
msg_data(msg_data_size
, 'a');
3822 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3823 kDefaultURL
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
3824 MockWrite writes
[] = {
3825 CreateMockWrite(*req
, 0),
3828 scoped_ptr
<SpdyFrame
> resp(
3829 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3830 MockRead reads
[] = {
3831 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3832 CreateMockRead(*resp
, 2),
3833 MockRead(ASYNC
, 0, 3) // EOF
3836 // Create SpdySession and SpdyStream and send the request.
3837 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3838 session_deps_
.host_resolver
->set_synchronous_mode(true);
3839 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3841 CreateNetworkSession();
3842 CreateInsecureSpdySession();
3844 base::WeakPtr
<SpdyStream
> stream
= CreateStreamSynchronously(
3845 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
3846 ASSERT_TRUE(stream
.get() != nullptr);
3847 EXPECT_EQ(0u, stream
->stream_id());
3849 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3850 stream
->SetDelegate(&delegate
);
3852 scoped_ptr
<SpdyHeaderBlock
> headers(
3853 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, msg_data_size
));
3854 EXPECT_EQ(ERR_IO_PENDING
,
3855 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3856 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3858 const int32 initial_window_size
=
3859 SpdySession::GetDefaultInitialWindowSize(GetParam());
3860 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3863 base::RunLoop().RunUntilIdle();
3865 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3867 // Read response, but do not run the message loop, so that the body is not
3868 // written to the socket.
3869 data
.CompleteRead();
3871 EXPECT_EQ(initial_window_size
- msg_data_size
,
3872 session_
->session_send_window_size_
);
3874 // Closing the stream should increase the session's send window.
3876 EXPECT_FALSE(stream
);
3878 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3880 EXPECT_EQ(OK
, delegate
.WaitForClose());
3882 base::RunLoop().RunUntilIdle();
3883 EXPECT_FALSE(session_
);
3885 EXPECT_TRUE(data
.AllWriteDataConsumed());
3886 EXPECT_TRUE(data
.AllReadDataConsumed());
3889 // Send data back and forth; the send and receive windows should
3890 // change appropriately.
3891 TEST_P(SpdySessionTest
, SessionFlowControlEndToEnd
) {
3892 const int32 msg_data_size
= 100;
3893 const std::string
msg_data(msg_data_size
, 'a');
3895 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3896 kDefaultURL
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
3897 scoped_ptr
<SpdyFrame
> msg(
3898 spdy_util_
.ConstructSpdyBodyFrame(
3899 1, msg_data
.data(), msg_data_size
, false));
3900 MockWrite writes
[] = {
3901 CreateMockWrite(*req
, 0),
3902 CreateMockWrite(*msg
, 2),
3905 scoped_ptr
<SpdyFrame
> resp(
3906 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3907 scoped_ptr
<SpdyFrame
> echo(
3908 spdy_util_
.ConstructSpdyBodyFrame(
3909 1, msg_data
.data(), msg_data_size
, false));
3910 scoped_ptr
<SpdyFrame
> window_update(
3911 spdy_util_
.ConstructSpdyWindowUpdate(
3912 kSessionFlowControlStreamId
, msg_data_size
));
3913 MockRead reads
[] = {
3914 CreateMockRead(*resp
, 1),
3915 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3916 CreateMockRead(*echo
, 4),
3917 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
3918 CreateMockRead(*window_update
, 6),
3919 MockRead(ASYNC
, ERR_IO_PENDING
, 7),
3920 MockRead(ASYNC
, 0, 8) // EOF
3923 // Create SpdySession and SpdyStream and send the request.
3924 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3925 session_deps_
.host_resolver
->set_synchronous_mode(true);
3926 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3928 CreateNetworkSession();
3929 CreateInsecureSpdySession();
3931 base::WeakPtr
<SpdyStream
> stream
= CreateStreamSynchronously(
3932 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
3933 ASSERT_TRUE(stream
.get() != nullptr);
3934 EXPECT_EQ(0u, stream
->stream_id());
3936 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3937 stream
->SetDelegate(&delegate
);
3939 scoped_ptr
<SpdyHeaderBlock
> headers(
3940 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, msg_data_size
));
3941 EXPECT_EQ(ERR_IO_PENDING
,
3942 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3943 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3945 const int32 initial_window_size
=
3946 SpdySession::GetDefaultInitialWindowSize(GetParam());
3947 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3948 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3949 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3951 // Send request and message.
3952 base::RunLoop().RunUntilIdle();
3954 EXPECT_EQ(initial_window_size
- msg_data_size
,
3955 session_
->session_send_window_size_
);
3956 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3957 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3960 data
.CompleteRead();
3961 base::RunLoop().RunUntilIdle();
3963 EXPECT_EQ(initial_window_size
- msg_data_size
,
3964 session_
->session_send_window_size_
);
3965 EXPECT_EQ(initial_window_size
- msg_data_size
,
3966 session_
->session_recv_window_size_
);
3967 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3969 // Read window update.
3970 data
.CompleteRead();
3971 base::RunLoop().RunUntilIdle();
3973 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3974 EXPECT_EQ(initial_window_size
- msg_data_size
,
3975 session_
->session_recv_window_size_
);
3976 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3978 EXPECT_EQ(msg_data
, delegate
.TakeReceivedData());
3980 // Draining the delegate's read queue should increase the session's
3982 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3983 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3984 EXPECT_EQ(msg_data_size
, session_
->session_unacked_recv_window_bytes_
);
3987 EXPECT_FALSE(stream
);
3989 EXPECT_EQ(OK
, delegate
.WaitForClose());
3991 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3992 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3993 EXPECT_EQ(msg_data_size
, session_
->session_unacked_recv_window_bytes_
);
3995 data
.CompleteRead();
3996 base::RunLoop().RunUntilIdle();
3997 EXPECT_FALSE(session_
);
4000 // Given a stall function and an unstall function, runs a test to make
4001 // sure that a stream resumes after unstall.
4002 void SpdySessionTest::RunResumeAfterUnstallTest(
4003 const base::Callback
<void(SpdyStream
*)>& stall_function
,
4004 const base::Callback
<void(SpdyStream
*, int32
)>& unstall_function
) {
4006 session_deps_
.host_resolver
->set_synchronous_mode(true);
4008 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
4009 kDefaultURL
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4010 scoped_ptr
<SpdyFrame
> body(
4011 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
4012 MockWrite writes
[] = {
4013 CreateMockWrite(*req
, 0),
4014 CreateMockWrite(*body
, 1),
4017 scoped_ptr
<SpdyFrame
> resp(
4018 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4019 scoped_ptr
<SpdyFrame
> echo(
4020 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4021 MockRead reads
[] = {
4022 CreateMockRead(*resp
, 2), MockRead(ASYNC
, 0, 3) // EOF
4025 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4026 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4028 CreateNetworkSession();
4029 CreateInsecureSpdySession();
4030 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4031 session_
->flow_control_state());
4033 base::WeakPtr
<SpdyStream
> stream
= CreateStreamSynchronously(
4034 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4035 ASSERT_TRUE(stream
.get() != nullptr);
4037 test::StreamDelegateWithBody
delegate(stream
, kBodyDataStringPiece
);
4038 stream
->SetDelegate(&delegate
);
4040 EXPECT_FALSE(stream
->HasUrlFromHeaders());
4041 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4043 scoped_ptr
<SpdyHeaderBlock
> headers(
4044 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4045 EXPECT_EQ(ERR_IO_PENDING
,
4046 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
4047 EXPECT_TRUE(stream
->HasUrlFromHeaders());
4048 EXPECT_EQ(kDefaultURL
, stream
->GetUrlFromHeaders().spec());
4050 stall_function
.Run(stream
.get());
4052 base::RunLoop().RunUntilIdle();
4054 EXPECT_TRUE(stream
->send_stalled_by_flow_control());
4056 unstall_function
.Run(stream
.get(), kBodyDataSize
);
4058 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4060 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
4062 EXPECT_TRUE(delegate
.send_headers_completed());
4063 EXPECT_EQ("200", delegate
.GetResponseHeaderValue(":status"));
4064 EXPECT_EQ(std::string(), delegate
.TakeReceivedData());
4065 EXPECT_FALSE(session_
);
4066 EXPECT_TRUE(data
.AllWriteDataConsumed());
4069 // Run the resume-after-unstall test with all possible stall and
4070 // unstall sequences.
4072 TEST_P(SpdySessionTest
, ResumeAfterUnstallSession
) {
4073 RunResumeAfterUnstallTest(
4074 base::Bind(&SpdySessionTest::StallSessionOnly
,
4075 base::Unretained(this)),
4076 base::Bind(&SpdySessionTest::UnstallSessionOnly
,
4077 base::Unretained(this)));
4081 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4082 TEST_P(SpdySessionTest
, ResumeAfterUnstallStream
) {
4083 RunResumeAfterUnstallTest(
4084 base::Bind(&SpdySessionTest::StallStreamOnly
,
4085 base::Unretained(this)),
4086 base::Bind(&SpdySessionTest::UnstallStreamOnly
,
4087 base::Unretained(this)));
4090 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallSessionStream
) {
4091 RunResumeAfterUnstallTest(
4092 base::Bind(&SpdySessionTest::StallSessionStream
,
4093 base::Unretained(this)),
4094 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4095 base::Unretained(this)));
4098 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallSessionStream
) {
4099 RunResumeAfterUnstallTest(
4100 base::Bind(&SpdySessionTest::StallStreamSession
,
4101 base::Unretained(this)),
4102 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4103 base::Unretained(this)));
4106 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallStreamSession
) {
4107 RunResumeAfterUnstallTest(
4108 base::Bind(&SpdySessionTest::StallStreamSession
,
4109 base::Unretained(this)),
4110 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4111 base::Unretained(this)));
4114 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallStreamSession
) {
4115 RunResumeAfterUnstallTest(
4116 base::Bind(&SpdySessionTest::StallSessionStream
,
4117 base::Unretained(this)),
4118 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4119 base::Unretained(this)));
4122 // Cause a stall by reducing the flow control send window to 0. The
4123 // streams should resume in priority order when that window is then
4125 TEST_P(SpdySessionTest
, ResumeByPriorityAfterSendWindowSizeIncrease
) {
4126 session_deps_
.host_resolver
->set_synchronous_mode(true);
4128 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4129 kDefaultURL
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4130 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4131 kDefaultURL
, 3, kBodyDataSize
, MEDIUM
, nullptr, 0));
4132 scoped_ptr
<SpdyFrame
> body1(
4133 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
4134 scoped_ptr
<SpdyFrame
> body2(
4135 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4136 MockWrite writes
[] = {
4137 CreateMockWrite(*req1
, 0),
4138 CreateMockWrite(*req2
, 1),
4139 CreateMockWrite(*body2
, 2),
4140 CreateMockWrite(*body1
, 3),
4143 scoped_ptr
<SpdyFrame
> resp1(
4144 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4145 scoped_ptr
<SpdyFrame
> resp2(
4146 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
4147 MockRead reads
[] = {
4148 CreateMockRead(*resp1
, 4),
4149 CreateMockRead(*resp2
, 5),
4150 MockRead(ASYNC
, 0, 6) // EOF
4153 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4154 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4156 CreateNetworkSession();
4157 CreateInsecureSpdySession();
4158 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4159 session_
->flow_control_state());
4161 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
4162 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4163 ASSERT_TRUE(stream1
.get() != nullptr);
4165 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4166 stream1
->SetDelegate(&delegate1
);
4168 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4170 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
4171 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
4172 ASSERT_TRUE(stream2
.get() != nullptr);
4174 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4175 stream2
->SetDelegate(&delegate2
);
4177 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4179 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4180 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4184 scoped_ptr
<SpdyHeaderBlock
> headers1(
4185 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4186 EXPECT_EQ(ERR_IO_PENDING
,
4187 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4188 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4189 EXPECT_EQ(kDefaultURL
, stream1
->GetUrlFromHeaders().spec());
4191 base::RunLoop().RunUntilIdle();
4192 EXPECT_EQ(1u, stream1
->stream_id());
4193 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4195 scoped_ptr
<SpdyHeaderBlock
> headers2(
4196 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4197 EXPECT_EQ(ERR_IO_PENDING
,
4198 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4199 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4200 EXPECT_EQ(kDefaultURL
, stream2
->GetUrlFromHeaders().spec());
4202 base::RunLoop().RunUntilIdle();
4203 EXPECT_EQ(3u, stream2
->stream_id());
4204 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4206 // This should unstall only stream2.
4207 UnstallSessionSend(kBodyDataSize
);
4209 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4210 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4212 base::RunLoop().RunUntilIdle();
4214 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4215 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4217 // This should then unstall stream1.
4218 UnstallSessionSend(kBodyDataSize
);
4220 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4221 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4223 base::RunLoop().RunUntilIdle();
4225 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4226 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4228 EXPECT_TRUE(delegate1
.send_headers_completed());
4229 EXPECT_EQ("200", delegate1
.GetResponseHeaderValue(":status"));
4230 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4232 EXPECT_TRUE(delegate2
.send_headers_completed());
4233 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4234 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4236 EXPECT_FALSE(session_
);
4237 EXPECT_TRUE(data
.AllWriteDataConsumed());
4238 EXPECT_TRUE(data
.AllReadDataConsumed());
4241 // Delegate that closes a given stream after sending its body.
4242 class StreamClosingDelegate
: public test::StreamDelegateWithBody
{
4244 StreamClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
4245 base::StringPiece data
)
4246 : StreamDelegateWithBody(stream
, data
) {}
4248 ~StreamClosingDelegate() override
{}
4250 void set_stream_to_close(const base::WeakPtr
<SpdyStream
>& stream_to_close
) {
4251 stream_to_close_
= stream_to_close
;
4254 void OnDataSent() override
{
4255 test::StreamDelegateWithBody::OnDataSent();
4256 if (stream_to_close_
.get()) {
4257 stream_to_close_
->Close();
4258 EXPECT_FALSE(stream_to_close_
);
4263 base::WeakPtr
<SpdyStream
> stream_to_close_
;
4266 // Cause a stall by reducing the flow control send window to
4267 // 0. Unstalling the session should properly handle deleted streams.
4268 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedStreams
) {
4269 session_deps_
.host_resolver
->set_synchronous_mode(true);
4271 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4272 kDefaultURL
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4273 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4274 kDefaultURL
, 3, kBodyDataSize
, LOWEST
, nullptr, 0));
4275 scoped_ptr
<SpdyFrame
> req3(spdy_util_
.ConstructSpdyPost(
4276 kDefaultURL
, 5, kBodyDataSize
, LOWEST
, nullptr, 0));
4277 scoped_ptr
<SpdyFrame
> body2(
4278 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4279 MockWrite writes
[] = {
4280 CreateMockWrite(*req1
, 0),
4281 CreateMockWrite(*req2
, 1),
4282 CreateMockWrite(*req3
, 2),
4283 CreateMockWrite(*body2
, 3),
4286 scoped_ptr
<SpdyFrame
> resp2(
4287 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
4288 MockRead reads
[] = {
4289 CreateMockRead(*resp2
, 4),
4290 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4291 MockRead(ASYNC
, 0, 6) // EOF
4294 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4295 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4297 CreateNetworkSession();
4298 CreateInsecureSpdySession();
4299 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4300 session_
->flow_control_state());
4302 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
4303 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4304 ASSERT_TRUE(stream1
.get() != nullptr);
4306 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4307 stream1
->SetDelegate(&delegate1
);
4309 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4311 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
4312 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4313 ASSERT_TRUE(stream2
.get() != nullptr);
4315 StreamClosingDelegate
delegate2(stream2
, kBodyDataStringPiece
);
4316 stream2
->SetDelegate(&delegate2
);
4318 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4320 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
4321 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4322 ASSERT_TRUE(stream3
.get() != nullptr);
4324 test::StreamDelegateWithBody
delegate3(stream3
, kBodyDataStringPiece
);
4325 stream3
->SetDelegate(&delegate3
);
4327 EXPECT_FALSE(stream3
->HasUrlFromHeaders());
4329 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4330 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4331 EXPECT_FALSE(stream3
->send_stalled_by_flow_control());
4335 scoped_ptr
<SpdyHeaderBlock
> headers1(
4336 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4337 EXPECT_EQ(ERR_IO_PENDING
,
4338 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4339 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4340 EXPECT_EQ(kDefaultURL
, stream1
->GetUrlFromHeaders().spec());
4342 base::RunLoop().RunUntilIdle();
4343 EXPECT_EQ(1u, stream1
->stream_id());
4344 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4346 scoped_ptr
<SpdyHeaderBlock
> headers2(
4347 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4348 EXPECT_EQ(ERR_IO_PENDING
,
4349 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4350 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4351 EXPECT_EQ(kDefaultURL
, stream2
->GetUrlFromHeaders().spec());
4353 base::RunLoop().RunUntilIdle();
4354 EXPECT_EQ(3u, stream2
->stream_id());
4355 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4357 scoped_ptr
<SpdyHeaderBlock
> headers3(
4358 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4359 EXPECT_EQ(ERR_IO_PENDING
,
4360 stream3
->SendRequestHeaders(headers3
.Pass(), MORE_DATA_TO_SEND
));
4361 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
4362 EXPECT_EQ(kDefaultURL
, stream3
->GetUrlFromHeaders().spec());
4364 base::RunLoop().RunUntilIdle();
4365 EXPECT_EQ(5u, stream3
->stream_id());
4366 EXPECT_TRUE(stream3
->send_stalled_by_flow_control());
4368 SpdyStreamId stream_id1
= stream1
->stream_id();
4369 SpdyStreamId stream_id2
= stream2
->stream_id();
4370 SpdyStreamId stream_id3
= stream3
->stream_id();
4372 // Close stream1 preemptively.
4373 session_
->CloseActiveStream(stream_id1
, ERR_CONNECTION_CLOSED
);
4374 EXPECT_FALSE(stream1
);
4376 EXPECT_FALSE(session_
->IsStreamActive(stream_id1
));
4377 EXPECT_TRUE(session_
->IsStreamActive(stream_id2
));
4378 EXPECT_TRUE(session_
->IsStreamActive(stream_id3
));
4380 // Unstall stream2, which should then close stream3.
4381 delegate2
.set_stream_to_close(stream3
);
4382 UnstallSessionSend(kBodyDataSize
);
4384 base::RunLoop().RunUntilIdle();
4385 EXPECT_FALSE(stream3
);
4387 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4388 EXPECT_FALSE(session_
->IsStreamActive(stream_id1
));
4389 EXPECT_TRUE(session_
->IsStreamActive(stream_id2
));
4390 EXPECT_FALSE(session_
->IsStreamActive(stream_id3
));
4392 data
.CompleteRead();
4393 base::RunLoop().RunUntilIdle();
4394 EXPECT_FALSE(stream2
);
4395 EXPECT_FALSE(session_
);
4397 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4398 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4399 EXPECT_EQ(OK
, delegate3
.WaitForClose());
4401 EXPECT_TRUE(delegate1
.send_headers_completed());
4402 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4404 EXPECT_TRUE(delegate2
.send_headers_completed());
4405 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4406 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4408 EXPECT_TRUE(delegate3
.send_headers_completed());
4409 EXPECT_EQ(std::string(), delegate3
.TakeReceivedData());
4411 EXPECT_TRUE(data
.AllWriteDataConsumed());
4414 // Cause a stall by reducing the flow control send window to
4415 // 0. Unstalling the session should properly handle the session itself
4417 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedSession
) {
4418 session_deps_
.host_resolver
->set_synchronous_mode(true);
4420 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4421 kDefaultURL
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4422 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4423 kDefaultURL
, 3, kBodyDataSize
, LOWEST
, nullptr, 0));
4424 scoped_ptr
<SpdyFrame
> body1(
4425 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4426 MockWrite writes
[] = {
4427 CreateMockWrite(*req1
, 0),
4428 CreateMockWrite(*req2
, 1),
4431 MockRead reads
[] = {
4432 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
4435 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4436 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4438 CreateNetworkSession();
4439 CreateInsecureSpdySession();
4440 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4441 session_
->flow_control_state());
4443 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
4444 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4445 ASSERT_TRUE(stream1
.get() != nullptr);
4447 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4448 stream1
->SetDelegate(&delegate1
);
4450 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4452 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
4453 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4454 ASSERT_TRUE(stream2
.get() != nullptr);
4456 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4457 stream2
->SetDelegate(&delegate2
);
4459 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4461 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4462 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4466 scoped_ptr
<SpdyHeaderBlock
> headers1(
4467 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4468 EXPECT_EQ(ERR_IO_PENDING
,
4469 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4470 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4471 EXPECT_EQ(kDefaultURL
, stream1
->GetUrlFromHeaders().spec());
4473 base::RunLoop().RunUntilIdle();
4474 EXPECT_EQ(1u, stream1
->stream_id());
4475 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4477 scoped_ptr
<SpdyHeaderBlock
> headers2(
4478 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4479 EXPECT_EQ(ERR_IO_PENDING
,
4480 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4481 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4482 EXPECT_EQ(kDefaultURL
, stream2
->GetUrlFromHeaders().spec());
4484 base::RunLoop().RunUntilIdle();
4485 EXPECT_EQ(3u, stream2
->stream_id());
4486 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4488 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
4491 UnstallSessionSend(kBodyDataSize
);
4493 // Close the session (since we can't do it from within the delegate
4494 // method, since it's in the stream's loop).
4495 session_
->CloseSessionOnError(ERR_CONNECTION_CLOSED
, "Closing session");
4496 data
.CompleteRead();
4497 base::RunLoop().RunUntilIdle();
4498 EXPECT_FALSE(session_
);
4500 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
4502 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4503 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4505 EXPECT_TRUE(delegate1
.send_headers_completed());
4506 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4508 EXPECT_TRUE(delegate2
.send_headers_completed());
4509 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4511 EXPECT_TRUE(data
.AllWriteDataConsumed());
4514 TEST_P(SpdySessionTest
, GoAwayOnSessionFlowControlError
) {
4515 scoped_ptr
<SpdyFrame
> req(
4516 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4517 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
4518 0, GOAWAY_FLOW_CONTROL_ERROR
,
4519 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4520 "the receive window size of 1"));
4521 MockWrite writes
[] = {
4522 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 4),
4525 scoped_ptr
<SpdyFrame
> resp(
4526 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4527 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4528 MockRead reads
[] = {
4529 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4530 CreateMockRead(*resp
, 2),
4531 CreateMockRead(*body
, 3),
4534 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4535 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4537 CreateNetworkSession();
4538 CreateInsecureSpdySession();
4540 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
4541 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4542 ASSERT_TRUE(spdy_stream
.get() != nullptr);
4543 test::StreamDelegateDoNothing
delegate(spdy_stream
);
4544 spdy_stream
->SetDelegate(&delegate
);
4546 scoped_ptr
<SpdyHeaderBlock
> headers(
4547 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
4548 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4551 base::RunLoop().RunUntilIdle();
4553 // Put session on the edge of overflowing it's recv window.
4554 session_
->session_recv_window_size_
= 1;
4556 // Read response headers & body. Body overflows the session window, and a
4557 // goaway is written.
4558 data
.CompleteRead();
4559 base::RunLoop().RunUntilIdle();
4561 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR
, delegate
.WaitForClose());
4562 EXPECT_FALSE(session_
);
4565 TEST_P(SpdySessionTest
, SplitHeaders
) {
4566 GURL
kStreamUrl("http://www.example.org/foo.dat");
4567 SpdyHeaderBlock headers
;
4568 spdy_util_
.AddUrlToHeaderBlock(kStreamUrl
.spec(), &headers
);
4569 headers
["alpha"] = "beta";
4571 SpdyHeaderBlock request_headers
;
4572 SpdyHeaderBlock response_headers
;
4574 SplitPushedHeadersToRequestAndResponse(
4575 headers
, spdy_util_
.spdy_version(), &request_headers
, &response_headers
);
4577 SpdyHeaderBlock::const_iterator it
= response_headers
.find("alpha");
4578 std::string alpha_val
=
4579 (it
== response_headers
.end()) ? std::string() : it
->second
;
4580 EXPECT_EQ("beta", alpha_val
);
4583 GetUrlFromHeaderBlock(request_headers
, spdy_util_
.spdy_version(), true);
4584 EXPECT_EQ(kStreamUrl
, request_url
);
4587 // Regression. Sorta. Push streams and client streams were sharing a single
4588 // limit for a long time.
4589 TEST_P(SpdySessionTest
, PushedStreamShouldNotCountToClientConcurrencyLimit
) {
4590 SettingsMap new_settings
;
4591 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4592 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, 2);
4593 scoped_ptr
<SpdyFrame
> settings_frame(
4594 spdy_util_
.ConstructSpdySettings(new_settings
));
4595 scoped_ptr
<SpdyFrame
> pushed(spdy_util_
.ConstructSpdyPush(
4596 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4597 MockRead reads
[] = {
4598 CreateMockRead(*settings_frame
, 0),
4599 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4600 CreateMockRead(*pushed
, 4),
4601 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4602 MockRead(ASYNC
, 0, 6),
4605 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
4606 scoped_ptr
<SpdyFrame
> req(
4607 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4608 MockWrite writes
[] = {
4609 CreateMockWrite(*settings_ack
, 1), CreateMockWrite(*req
, 2),
4612 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4613 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4615 CreateNetworkSession();
4616 CreateInsecureSpdySession();
4618 // Read the settings frame.
4619 base::RunLoop().RunUntilIdle();
4621 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4622 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4623 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4624 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4625 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4626 spdy_stream1
->SetDelegate(&delegate1
);
4628 EXPECT_EQ(0u, session_
->num_active_streams());
4629 EXPECT_EQ(1u, session_
->num_created_streams());
4630 EXPECT_EQ(0u, session_
->num_pushed_streams());
4631 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4633 scoped_ptr
<SpdyHeaderBlock
> headers(
4634 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
4635 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4636 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4638 // Run until 1st stream is activated.
4639 EXPECT_EQ(0u, delegate1
.stream_id());
4640 base::RunLoop().RunUntilIdle();
4641 EXPECT_EQ(1u, delegate1
.stream_id());
4642 EXPECT_EQ(1u, session_
->num_active_streams());
4643 EXPECT_EQ(0u, session_
->num_created_streams());
4644 EXPECT_EQ(0u, session_
->num_pushed_streams());
4645 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4647 // Run until pushed stream is created.
4648 data
.CompleteRead();
4649 base::RunLoop().RunUntilIdle();
4650 EXPECT_EQ(2u, session_
->num_active_streams());
4651 EXPECT_EQ(0u, session_
->num_created_streams());
4652 EXPECT_EQ(1u, session_
->num_pushed_streams());
4653 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4655 // Second stream should not be stalled, although we have 2 active streams, but
4656 // one of them is push stream and should not be taken into account when we
4657 // create streams on the client.
4658 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
4659 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4660 EXPECT_TRUE(spdy_stream2
);
4661 EXPECT_EQ(2u, session_
->num_active_streams());
4662 EXPECT_EQ(1u, session_
->num_created_streams());
4663 EXPECT_EQ(1u, session_
->num_pushed_streams());
4664 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4667 data
.CompleteRead();
4668 base::RunLoop().RunUntilIdle();
4669 EXPECT_FALSE(session_
);
4672 TEST_P(SpdySessionTest
, RejectPushedStreamExceedingConcurrencyLimit
) {
4673 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4674 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4675 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
4676 nullptr, 0, 4, 1, "http://www.example.org/b.dat"));
4677 MockRead reads
[] = {
4678 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4679 CreateMockRead(*push_a
, 2),
4680 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4681 CreateMockRead(*push_b
, 4),
4682 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
4683 MockRead(ASYNC
, 0, 7),
4686 scoped_ptr
<SpdyFrame
> req(
4687 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4688 scoped_ptr
<SpdyFrame
> rst(
4689 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4690 MockWrite writes
[] = {
4691 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5),
4694 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4695 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4697 CreateNetworkSession();
4698 CreateInsecureSpdySession();
4699 session_
->set_max_concurrent_pushed_streams(1);
4701 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4702 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4703 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4704 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4705 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4706 spdy_stream1
->SetDelegate(&delegate1
);
4708 EXPECT_EQ(0u, session_
->num_active_streams());
4709 EXPECT_EQ(1u, session_
->num_created_streams());
4710 EXPECT_EQ(0u, session_
->num_pushed_streams());
4711 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4713 scoped_ptr
<SpdyHeaderBlock
> headers(
4714 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
4715 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4716 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4718 // Run until 1st stream is activated.
4719 EXPECT_EQ(0u, delegate1
.stream_id());
4720 base::RunLoop().RunUntilIdle();
4721 EXPECT_EQ(1u, delegate1
.stream_id());
4722 EXPECT_EQ(1u, session_
->num_active_streams());
4723 EXPECT_EQ(0u, session_
->num_created_streams());
4724 EXPECT_EQ(0u, session_
->num_pushed_streams());
4725 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4727 // Run until pushed stream is created.
4728 data
.CompleteRead();
4729 base::RunLoop().RunUntilIdle();
4730 EXPECT_EQ(2u, session_
->num_active_streams());
4731 EXPECT_EQ(0u, session_
->num_created_streams());
4732 EXPECT_EQ(1u, session_
->num_pushed_streams());
4733 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4735 // Reset incoming pushed stream.
4736 data
.CompleteRead();
4737 base::RunLoop().RunUntilIdle();
4738 EXPECT_EQ(2u, session_
->num_active_streams());
4739 EXPECT_EQ(0u, session_
->num_created_streams());
4740 EXPECT_EQ(1u, session_
->num_pushed_streams());
4741 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4744 data
.CompleteRead();
4745 base::RunLoop().RunUntilIdle();
4746 EXPECT_FALSE(session_
);
4749 TEST_P(SpdySessionTest
, IgnoreReservedRemoteStreamsCount
) {
4750 // Streams in reserved remote state exist only in HTTP/2.
4751 if (spdy_util_
.spdy_version() < HTTP2
)
4754 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4755 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4756 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4757 spdy_util_
.AddUrlToHeaderBlock("http://www.example.org/b.dat",
4758 push_headers
.get());
4759 scoped_ptr
<SpdyFrame
> push_b(
4760 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 4, 1));
4761 scoped_ptr
<SpdyFrame
> headers_b(
4762 spdy_util_
.ConstructSpdyPushHeaders(4, nullptr, 0));
4763 MockRead reads
[] = {
4764 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4765 CreateMockRead(*push_a
, 2),
4766 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4767 CreateMockRead(*push_b
, 4),
4768 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4769 CreateMockRead(*headers_b
, 6),
4770 MockRead(ASYNC
, ERR_IO_PENDING
, 8),
4771 MockRead(ASYNC
, 0, 9),
4774 scoped_ptr
<SpdyFrame
> req(
4775 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4776 scoped_ptr
<SpdyFrame
> rst(
4777 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4778 MockWrite writes
[] = {
4779 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 7),
4782 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4783 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4785 CreateNetworkSession();
4786 CreateInsecureSpdySession();
4787 session_
->set_max_concurrent_pushed_streams(1);
4789 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4790 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4791 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4792 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4793 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4794 spdy_stream1
->SetDelegate(&delegate1
);
4796 EXPECT_EQ(0u, session_
->num_active_streams());
4797 EXPECT_EQ(1u, session_
->num_created_streams());
4798 EXPECT_EQ(0u, session_
->num_pushed_streams());
4799 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4801 scoped_ptr
<SpdyHeaderBlock
> headers(
4802 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
4803 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4804 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4806 // Run until 1st stream is activated.
4807 EXPECT_EQ(0u, delegate1
.stream_id());
4808 base::RunLoop().RunUntilIdle();
4809 EXPECT_EQ(1u, delegate1
.stream_id());
4810 EXPECT_EQ(1u, session_
->num_active_streams());
4811 EXPECT_EQ(0u, session_
->num_created_streams());
4812 EXPECT_EQ(0u, session_
->num_pushed_streams());
4813 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4815 // Run until pushed stream is created.
4816 data
.CompleteRead();
4817 base::RunLoop().RunUntilIdle();
4818 EXPECT_EQ(2u, session_
->num_active_streams());
4819 EXPECT_EQ(0u, session_
->num_created_streams());
4820 EXPECT_EQ(1u, session_
->num_pushed_streams());
4821 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4823 // Accept promised stream. It should not count towards pushed stream limit.
4824 data
.CompleteRead();
4825 base::RunLoop().RunUntilIdle();
4826 EXPECT_EQ(3u, session_
->num_active_streams());
4827 EXPECT_EQ(0u, session_
->num_created_streams());
4828 EXPECT_EQ(2u, session_
->num_pushed_streams());
4829 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4831 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4832 // while we accept only one.
4833 data
.CompleteRead();
4834 base::RunLoop().RunUntilIdle();
4835 EXPECT_EQ(2u, session_
->num_active_streams());
4836 EXPECT_EQ(0u, session_
->num_created_streams());
4837 EXPECT_EQ(1u, session_
->num_pushed_streams());
4838 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4841 data
.CompleteRead();
4842 base::RunLoop().RunUntilIdle();
4843 EXPECT_FALSE(session_
);
4846 TEST_P(SpdySessionTest
, CancelReservedStreamOnHeadersReceived
) {
4847 // Streams in reserved remote state exist only in HTTP/2.
4848 if (spdy_util_
.spdy_version() < HTTP2
)
4851 const char kPushedUrl
[] = "http://www.example.org/a.dat";
4852 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4853 spdy_util_
.AddUrlToHeaderBlock(kPushedUrl
, push_headers
.get());
4854 scoped_ptr
<SpdyFrame
> push_promise(
4855 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 2, 1));
4856 scoped_ptr
<SpdyFrame
> headers_frame(
4857 spdy_util_
.ConstructSpdyPushHeaders(2, nullptr, 0));
4858 MockRead reads
[] = {
4859 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4860 CreateMockRead(*push_promise
, 2),
4861 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4862 CreateMockRead(*headers_frame
, 4),
4863 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
4864 MockRead(ASYNC
, 0, 7),
4867 scoped_ptr
<SpdyFrame
> req(
4868 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4869 scoped_ptr
<SpdyFrame
> rst(
4870 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
4871 MockWrite writes
[] = {
4872 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5),
4875 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4876 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4878 CreateNetworkSession();
4879 CreateInsecureSpdySession();
4881 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4882 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4883 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4884 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4885 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4886 spdy_stream1
->SetDelegate(&delegate1
);
4888 EXPECT_EQ(0u, session_
->num_active_streams());
4889 EXPECT_EQ(1u, session_
->num_created_streams());
4890 EXPECT_EQ(0u, session_
->num_pushed_streams());
4891 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4893 scoped_ptr
<SpdyHeaderBlock
> headers(
4894 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
4895 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4896 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4898 // Run until 1st stream is activated.
4899 EXPECT_EQ(0u, delegate1
.stream_id());
4900 base::RunLoop().RunUntilIdle();
4901 EXPECT_EQ(1u, delegate1
.stream_id());
4902 EXPECT_EQ(1u, session_
->num_active_streams());
4903 EXPECT_EQ(0u, session_
->num_created_streams());
4904 EXPECT_EQ(0u, session_
->num_pushed_streams());
4905 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4907 // Run until pushed stream is created.
4908 data
.CompleteRead();
4909 base::RunLoop().RunUntilIdle();
4910 EXPECT_EQ(2u, session_
->num_active_streams());
4911 EXPECT_EQ(0u, session_
->num_created_streams());
4912 EXPECT_EQ(1u, session_
->num_pushed_streams());
4913 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4915 base::WeakPtr
<SpdyStream
> pushed_stream
;
4917 session_
->GetPushStream(GURL(kPushedUrl
), &pushed_stream
, BoundNetLog());
4919 ASSERT_TRUE(pushed_stream
.get() != nullptr);
4920 test::StreamDelegateCloseOnHeaders
delegate2(pushed_stream
);
4921 pushed_stream
->SetDelegate(&delegate2
);
4923 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4924 // that all our counters are in consistent state.
4925 data
.CompleteRead();
4926 base::RunLoop().RunUntilIdle();
4927 EXPECT_EQ(1u, session_
->num_active_streams());
4928 EXPECT_EQ(0u, session_
->num_created_streams());
4929 EXPECT_EQ(0u, session_
->num_pushed_streams());
4930 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4933 data
.CompleteRead();
4934 base::RunLoop().RunUntilIdle();
4935 EXPECT_TRUE(data
.AllWriteDataConsumed());
4936 EXPECT_TRUE(data
.AllReadDataConsumed());
4939 TEST_P(SpdySessionTest
, RejectInvalidUnknownFrames
) {
4940 session_deps_
.host_resolver
->set_synchronous_mode(true);
4942 MockRead reads
[] = {
4943 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
4946 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
4947 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4949 CreateNetworkSession();
4950 CreateInsecureSpdySession();
4952 session_
->stream_hi_water_mark_
= 5;
4953 // Low client (odd) ids are fine.
4954 EXPECT_TRUE(session_
->OnUnknownFrame(3, 0));
4955 // Client id exceeding watermark.
4956 EXPECT_FALSE(session_
->OnUnknownFrame(9, 0));
4958 session_
->last_accepted_push_stream_id_
= 6;
4959 // Low server (even) ids are fine.
4960 EXPECT_TRUE(session_
->OnUnknownFrame(2, 0));
4961 // Server id exceeding last accepted id.
4962 EXPECT_FALSE(session_
->OnUnknownFrame(8, 0));
4965 TEST(MapFramerErrorToProtocolError
, MapsValues
) {
4967 SPDY_ERROR_INVALID_CONTROL_FRAME
,
4968 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4970 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS
,
4971 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
4973 SPDY_ERROR_GOAWAY_FRAME_CORRUPT
,
4974 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT
));
4975 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME
,
4976 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME
));
4979 TEST(MapFramerErrorToNetError
, MapsValue
) {
4980 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR
,
4981 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4982 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
4983 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE
));
4984 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
4985 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE
));
4987 ERR_SPDY_FRAME_SIZE_ERROR
,
4988 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
));
4991 TEST(MapRstStreamStatusToProtocolError
, MapsValues
) {
4992 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR
,
4993 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR
));
4994 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR
,
4995 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR
));
4996 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM
,
4997 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM
));
4998 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY
,
4999 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY
));
5000 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED
,
5001 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED
));
5004 TEST(MapNetErrorToGoAwayStatus
, MapsValue
) {
5005 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY
,
5006 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
));
5007 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR
,
5008 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR
));
5009 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
,
5010 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR
));
5011 CHECK_EQ(GOAWAY_COMPRESSION_ERROR
,
5012 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR
));
5013 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR
,
5014 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR
));
5015 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED
));
5018 TEST(CanPoolTest
, CanPool
) {
5019 // Load a cert that is valid for:
5024 TransportSecurityState tss
;
5026 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5027 "spdy_pooling.pem");
5029 EXPECT_TRUE(SpdySession::CanPool(
5030 &tss
, ssl_info
, "www.example.org", "www.example.org"));
5031 EXPECT_TRUE(SpdySession::CanPool(
5032 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5033 EXPECT_TRUE(SpdySession::CanPool(
5034 &tss
, ssl_info
, "www.example.org", "mail.example.com"));
5035 EXPECT_FALSE(SpdySession::CanPool(
5036 &tss
, ssl_info
, "www.example.org", "mail.google.com"));
5039 TEST(CanPoolTest
, CanNotPoolWithCertErrors
) {
5040 // Load a cert that is valid for:
5045 TransportSecurityState tss
;
5047 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5048 "spdy_pooling.pem");
5049 ssl_info
.cert_status
= CERT_STATUS_REVOKED
;
5051 EXPECT_FALSE(SpdySession::CanPool(
5052 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5055 TEST(CanPoolTest
, CanNotPoolWithClientCerts
) {
5056 // Load a cert that is valid for:
5061 TransportSecurityState tss
;
5063 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5064 "spdy_pooling.pem");
5065 ssl_info
.client_cert_sent
= true;
5067 EXPECT_FALSE(SpdySession::CanPool(
5068 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5071 TEST(CanPoolTest
, CanNotPoolAcrossETLDsWithChannelID
) {
5072 // Load a cert that is valid for:
5077 TransportSecurityState tss
;
5079 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5080 "spdy_pooling.pem");
5081 ssl_info
.channel_id_sent
= true;
5083 EXPECT_TRUE(SpdySession::CanPool(
5084 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5085 EXPECT_FALSE(SpdySession::CanPool(
5086 &tss
, ssl_info
, "www.example.org", "www.example.com"));
5089 TEST(CanPoolTest
, CanNotPoolWithBadPins
) {
5090 uint8 primary_pin
= 1;
5091 uint8 backup_pin
= 2;
5093 TransportSecurityState tss
;
5094 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5097 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5098 "spdy_pooling.pem");
5099 ssl_info
.is_issued_by_known_root
= true;
5100 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(bad_pin
));
5102 EXPECT_FALSE(SpdySession::CanPool(
5103 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5106 TEST(CanPoolTest
, CanPoolWithAcceptablePins
) {
5107 uint8 primary_pin
= 1;
5108 uint8 backup_pin
= 2;
5109 TransportSecurityState tss
;
5110 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5113 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5114 "spdy_pooling.pem");
5115 ssl_info
.is_issued_by_known_root
= true;
5116 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(primary_pin
));
5118 EXPECT_TRUE(SpdySession::CanPool(
5119 &tss
, ssl_info
, "www.example.org", "mail.example.org"));