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 static const char kTestUrl
[] = "http://www.example.org/";
39 static const char kTestHost
[] = "www.example.org";
40 static const int kTestPort
= 80;
42 const char kBodyData
[] = "Body data";
43 const size_t kBodyDataSize
= arraysize(kBodyData
);
44 const base::StringPiece
kBodyDataStringPiece(kBodyData
, kBodyDataSize
);
46 static base::TimeDelta g_time_delta
;
47 base::TimeTicks
TheNearFuture() {
48 return base::TimeTicks::Now() + g_time_delta
;
53 class SpdySessionTest
: public PlatformTest
,
54 public ::testing::WithParamInterface
<NextProto
> {
56 // Functions used with RunResumeAfterUnstallTest().
58 void StallSessionOnly(SpdySession
* session
, SpdyStream
* stream
) {
59 StallSessionSend(session
);
62 void StallStreamOnly(SpdySession
* session
, SpdyStream
* stream
) {
63 StallStreamSend(stream
);
66 void StallSessionStream(SpdySession
* session
, SpdyStream
* stream
) {
67 StallSessionSend(session
);
68 StallStreamSend(stream
);
71 void StallStreamSession(SpdySession
* session
, SpdyStream
* stream
) {
72 StallStreamSend(stream
);
73 StallSessionSend(session
);
76 void UnstallSessionOnly(SpdySession
* session
,
78 int32 delta_window_size
) {
79 UnstallSessionSend(session
, delta_window_size
);
82 void UnstallStreamOnly(SpdySession
* session
,
84 int32 delta_window_size
) {
85 UnstallStreamSend(stream
, delta_window_size
);
88 void UnstallSessionStream(SpdySession
* session
,
90 int32 delta_window_size
) {
91 UnstallSessionSend(session
, delta_window_size
);
92 UnstallStreamSend(stream
, delta_window_size
);
95 void UnstallStreamSession(SpdySession
* session
,
97 int32 delta_window_size
) {
98 UnstallStreamSend(stream
, delta_window_size
);
99 UnstallSessionSend(session
, delta_window_size
);
104 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
105 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
106 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
107 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
108 spdy_util_(GetParam()),
109 session_deps_(GetParam()),
110 spdy_session_pool_(nullptr),
112 test_host_port_pair_(kTestHost
, kTestPort
),
113 key_(test_host_port_pair_
,
114 ProxyServer::Direct(),
115 PRIVACY_MODE_DISABLED
) {}
117 virtual ~SpdySessionTest() {
118 // Important to restore the per-pool limit first, since the pool limit must
119 // always be greater than group limit, and the tests reduce both limits.
120 ClientSocketPoolManager::set_max_sockets_per_pool(
121 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
122 ClientSocketPoolManager::set_max_sockets_per_group(
123 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
126 void SetUp() override
{ g_time_delta
= base::TimeDelta(); }
128 void CreateNetworkSession() {
130 SpdySessionDependencies::SpdyCreateSession(&session_deps_
);
131 spdy_session_pool_
= http_session_
->spdy_session_pool();
134 void StallSessionSend(SpdySession
* session
) {
135 // Reduce the send window size to 0 to stall.
136 while (session
->session_send_window_size_
> 0) {
137 session
->DecreaseSendWindowSize(
138 std::min(kMaxSpdyFrameChunkSize
, session
->session_send_window_size_
));
142 void UnstallSessionSend(SpdySession
* session
, int32 delta_window_size
) {
143 session
->IncreaseSendWindowSize(delta_window_size
);
146 void StallStreamSend(SpdyStream
* stream
) {
147 // Reduce the send window size to 0 to stall.
148 while (stream
->send_window_size() > 0) {
149 stream
->DecreaseSendWindowSize(
150 std::min(kMaxSpdyFrameChunkSize
, stream
->send_window_size()));
154 void UnstallStreamSend(SpdyStream
* stream
, int32 delta_window_size
) {
155 stream
->IncreaseSendWindowSize(delta_window_size
);
158 void RunResumeAfterUnstallTest(
159 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
160 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
163 // Original socket limits. Some tests set these. Safest to always restore
164 // them once each test has been run.
165 int old_max_group_sockets_
;
166 int old_max_pool_sockets_
;
168 SpdyTestUtil spdy_util_
;
169 SpdySessionDependencies session_deps_
;
170 scoped_refptr
<HttpNetworkSession
> http_session_
;
171 SpdySessionPool
* spdy_session_pool_
;
173 HostPortPair test_host_port_pair_
;
177 INSTANTIATE_TEST_CASE_P(NextProto
,
179 testing::Values(kProtoSPDY31
,
183 // Try to create a SPDY session that will fail during
184 // initialization. Nothing should blow up.
185 TEST_P(SpdySessionTest
, InitialReadError
) {
186 CreateNetworkSession();
188 base::WeakPtr
<SpdySession
> session
= TryCreateFakeSpdySessionExpectingFailure(
189 spdy_session_pool_
, key_
, ERR_CONNECTION_CLOSED
);
190 EXPECT_TRUE(session
);
192 base::RunLoop().RunUntilIdle();
193 EXPECT_FALSE(session
);
198 // A helper class that vends a callback that, when fired, destroys a
199 // given SpdyStreamRequest.
200 class StreamRequestDestroyingCallback
: public TestCompletionCallbackBase
{
202 StreamRequestDestroyingCallback() {}
204 ~StreamRequestDestroyingCallback() override
{}
206 void SetRequestToDestroy(scoped_ptr
<SpdyStreamRequest
> request
) {
207 request_
= request
.Pass();
210 CompletionCallback
MakeCallback() {
211 return base::Bind(&StreamRequestDestroyingCallback::OnComplete
,
212 base::Unretained(this));
216 void OnComplete(int result
) {
221 scoped_ptr
<SpdyStreamRequest
> request_
;
226 // Request kInitialMaxConcurrentStreams streams. Request two more
227 // streams, but have the callback for one destroy the second stream
228 // request. Close the session. Nothing should blow up. This is a
229 // regression test for http://crbug.com/250841 .
230 TEST_P(SpdySessionTest
, PendingStreamCancellingAnother
) {
231 session_deps_
.host_resolver
->set_synchronous_mode(true);
233 MockRead reads
[] = {MockRead(ASYNC
, 0, 0), };
235 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
236 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
238 CreateNetworkSession();
240 base::WeakPtr
<SpdySession
> session
=
241 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
243 // Create the maximum number of concurrent streams.
244 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
245 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
246 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
, BoundNetLog());
247 ASSERT_TRUE(spdy_stream
!= nullptr);
250 SpdyStreamRequest request1
;
251 scoped_ptr
<SpdyStreamRequest
> request2(new SpdyStreamRequest
);
253 StreamRequestDestroyingCallback callback1
;
254 ASSERT_EQ(ERR_IO_PENDING
,
255 request1
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
,
260 callback1
.MakeCallback()));
262 // |callback2| is never called.
263 TestCompletionCallback callback2
;
264 ASSERT_EQ(ERR_IO_PENDING
,
265 request2
->StartRequest(SPDY_BIDIRECTIONAL_STREAM
,
270 callback2
.callback()));
272 callback1
.SetRequestToDestroy(request2
.Pass());
274 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
276 EXPECT_EQ(ERR_ABORTED
, callback1
.WaitForResult());
279 // A session receiving a GOAWAY frame with no active streams should close.
280 TEST_P(SpdySessionTest
, GoAwayWithNoActiveStreams
) {
281 session_deps_
.host_resolver
->set_synchronous_mode(true);
283 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
285 CreateMockRead(*goaway
, 0),
287 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
288 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
290 CreateNetworkSession();
292 base::WeakPtr
<SpdySession
> session
=
293 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
295 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
297 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
299 // Read and process the GOAWAY frame.
300 base::RunLoop().RunUntilIdle();
301 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
302 EXPECT_FALSE(session
);
305 // A session receiving a GOAWAY frame immediately with no active
306 // streams should then close.
307 TEST_P(SpdySessionTest
, GoAwayImmediatelyWithNoActiveStreams
) {
308 session_deps_
.host_resolver
->set_synchronous_mode(true);
310 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
312 CreateMockRead(*goaway
, 0, SYNCHRONOUS
), MockRead(ASYNC
, 0, 1) // EOF
314 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
315 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
317 CreateNetworkSession();
319 base::WeakPtr
<SpdySession
> session
=
320 TryCreateInsecureSpdySessionExpectingFailure(
321 http_session_
, key_
, ERR_CONNECTION_CLOSED
, BoundNetLog());
322 base::RunLoop().RunUntilIdle();
324 EXPECT_FALSE(session
);
325 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
326 EXPECT_FALSE(data
.AllReadDataConsumed());
329 // A session receiving a GOAWAY frame with active streams should close
330 // when the last active stream is closed.
331 TEST_P(SpdySessionTest
, GoAwayWithActiveStreams
) {
332 session_deps_
.host_resolver
->set_synchronous_mode(true);
334 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
336 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
337 CreateMockRead(*goaway
, 3),
338 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
339 MockRead(ASYNC
, 0, 5) // EOF
341 scoped_ptr
<SpdyFrame
> req1(
342 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
343 scoped_ptr
<SpdyFrame
> req2(
344 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
345 MockWrite writes
[] = {
346 CreateMockWrite(*req1
, 0),
347 CreateMockWrite(*req2
, 1),
349 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
350 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
352 CreateNetworkSession();
354 base::WeakPtr
<SpdySession
> session
=
355 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
357 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
359 GURL
url(kDefaultURL
);
360 base::WeakPtr
<SpdyStream
> spdy_stream1
=
361 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
362 session
, url
, MEDIUM
, BoundNetLog());
363 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
364 spdy_stream1
->SetDelegate(&delegate1
);
366 base::WeakPtr
<SpdyStream
> spdy_stream2
=
367 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
368 session
, url
, MEDIUM
, BoundNetLog());
369 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
370 spdy_stream2
->SetDelegate(&delegate2
);
372 scoped_ptr
<SpdyHeaderBlock
> headers(
373 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
374 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
376 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
377 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
378 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
379 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
381 base::RunLoop().RunUntilIdle();
383 EXPECT_EQ(1u, spdy_stream1
->stream_id());
384 EXPECT_EQ(3u, spdy_stream2
->stream_id());
386 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
388 // Read and process the GOAWAY frame.
390 base::RunLoop().RunUntilIdle();
392 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
394 EXPECT_FALSE(session
->IsStreamActive(3));
395 EXPECT_FALSE(spdy_stream2
);
396 EXPECT_TRUE(session
->IsStreamActive(1));
398 EXPECT_TRUE(session
->IsGoingAway());
400 // Should close the session.
401 spdy_stream1
->Close();
402 EXPECT_FALSE(spdy_stream1
);
404 EXPECT_TRUE(session
);
406 base::RunLoop().RunUntilIdle();
407 EXPECT_FALSE(session
);
410 // Have a session receive two GOAWAY frames, with the last one causing
411 // the last active stream to be closed. The session should then be
412 // closed after the second GOAWAY frame.
413 TEST_P(SpdySessionTest
, GoAwayTwice
) {
414 session_deps_
.host_resolver
->set_synchronous_mode(true);
416 scoped_ptr
<SpdyFrame
> goaway1(spdy_util_
.ConstructSpdyGoAway(1));
417 scoped_ptr
<SpdyFrame
> goaway2(spdy_util_
.ConstructSpdyGoAway(0));
419 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
420 CreateMockRead(*goaway1
, 3),
421 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
422 CreateMockRead(*goaway2
, 5),
423 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
424 MockRead(ASYNC
, 0, 7) // EOF
426 scoped_ptr
<SpdyFrame
> req1(
427 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
428 scoped_ptr
<SpdyFrame
> req2(
429 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
430 MockWrite writes
[] = {
431 CreateMockWrite(*req1
, 0),
432 CreateMockWrite(*req2
, 1),
434 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
435 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
437 CreateNetworkSession();
439 base::WeakPtr
<SpdySession
> session
=
440 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
442 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
444 GURL
url(kDefaultURL
);
445 base::WeakPtr
<SpdyStream
> spdy_stream1
=
446 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
447 session
, url
, MEDIUM
, BoundNetLog());
448 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
449 spdy_stream1
->SetDelegate(&delegate1
);
451 base::WeakPtr
<SpdyStream
> spdy_stream2
=
452 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
453 session
, url
, MEDIUM
, BoundNetLog());
454 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
455 spdy_stream2
->SetDelegate(&delegate2
);
457 scoped_ptr
<SpdyHeaderBlock
> headers(
458 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
459 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
461 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
462 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
463 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
464 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
466 base::RunLoop().RunUntilIdle();
468 EXPECT_EQ(1u, spdy_stream1
->stream_id());
469 EXPECT_EQ(3u, spdy_stream2
->stream_id());
471 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
473 // Read and process the first GOAWAY frame.
475 base::RunLoop().RunUntilIdle();
477 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
479 EXPECT_FALSE(session
->IsStreamActive(3));
480 EXPECT_FALSE(spdy_stream2
);
481 EXPECT_TRUE(session
->IsStreamActive(1));
482 EXPECT_TRUE(session
->IsGoingAway());
484 // Read and process the second GOAWAY frame, which should close the
487 base::RunLoop().RunUntilIdle();
488 EXPECT_FALSE(session
);
491 // Have a session with active streams receive a GOAWAY frame and then
492 // close it. It should handle the close properly (i.e., not try to
493 // make itself unavailable in its pool twice).
494 TEST_P(SpdySessionTest
, GoAwayWithActiveStreamsThenClose
) {
495 session_deps_
.host_resolver
->set_synchronous_mode(true);
497 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
499 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
500 CreateMockRead(*goaway
, 3),
501 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
502 MockRead(ASYNC
, 0, 5) // EOF
504 scoped_ptr
<SpdyFrame
> req1(
505 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
506 scoped_ptr
<SpdyFrame
> req2(
507 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
508 MockWrite writes
[] = {
509 CreateMockWrite(*req1
, 0),
510 CreateMockWrite(*req2
, 1),
512 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
513 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
515 CreateNetworkSession();
517 base::WeakPtr
<SpdySession
> session
=
518 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
520 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
522 GURL
url(kDefaultURL
);
523 base::WeakPtr
<SpdyStream
> spdy_stream1
=
524 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
525 session
, url
, MEDIUM
, BoundNetLog());
526 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
527 spdy_stream1
->SetDelegate(&delegate1
);
529 base::WeakPtr
<SpdyStream
> spdy_stream2
=
530 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
531 session
, url
, MEDIUM
, BoundNetLog());
532 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
533 spdy_stream2
->SetDelegate(&delegate2
);
535 scoped_ptr
<SpdyHeaderBlock
> headers(
536 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
537 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
539 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
540 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
541 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
542 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
544 base::RunLoop().RunUntilIdle();
546 EXPECT_EQ(1u, spdy_stream1
->stream_id());
547 EXPECT_EQ(3u, spdy_stream2
->stream_id());
549 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
551 // Read and process the GOAWAY frame.
553 base::RunLoop().RunUntilIdle();
555 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
557 EXPECT_FALSE(session
->IsStreamActive(3));
558 EXPECT_FALSE(spdy_stream2
);
559 EXPECT_TRUE(session
->IsStreamActive(1));
560 EXPECT_TRUE(session
->IsGoingAway());
562 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
563 EXPECT_FALSE(spdy_stream1
);
566 base::RunLoop().RunUntilIdle();
567 EXPECT_FALSE(session
);
570 // Process a joint read buffer which causes the session to begin draining, and
571 // then processes a GOAWAY. The session should gracefully drain. Regression test
572 // for crbug.com/379469
573 TEST_P(SpdySessionTest
, GoAwayWhileDraining
) {
574 session_deps_
.host_resolver
->set_synchronous_mode(true);
576 scoped_ptr
<SpdyFrame
> req(
577 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
578 MockWrite writes
[] = {
579 CreateMockWrite(*req
, 0),
582 scoped_ptr
<SpdyFrame
> resp(
583 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
584 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
585 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
586 size_t joint_size
= goaway
->size() * 2 + body
->size();
588 // Compose interleaved |goaway| and |body| frames into a single read.
589 scoped_ptr
<char[]> buffer(new char[joint_size
]);
592 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
593 out
+= goaway
->size();
594 memcpy(&buffer
[out
], body
->data(), body
->size());
596 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
597 out
+= goaway
->size();
598 ASSERT_EQ(out
, joint_size
);
600 SpdyFrame
joint_frames(buffer
.get(), joint_size
, false);
603 CreateMockRead(*resp
, 1), CreateMockRead(joint_frames
, 2),
604 MockRead(ASYNC
, 0, 3) // EOF
607 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
608 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
610 CreateNetworkSession();
611 base::WeakPtr
<SpdySession
> session
=
612 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
614 GURL
url(kDefaultURL
);
615 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
616 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
617 test::StreamDelegateDoNothing
delegate(spdy_stream
);
618 spdy_stream
->SetDelegate(&delegate
);
620 scoped_ptr
<SpdyHeaderBlock
> headers(
621 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
622 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
623 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
625 base::RunLoop().RunUntilIdle();
627 // Stream and session closed gracefully.
628 EXPECT_TRUE(delegate
.StreamIsClosed());
629 EXPECT_EQ(OK
, delegate
.WaitForClose());
630 EXPECT_EQ(kUploadData
, delegate
.TakeReceivedData());
631 EXPECT_FALSE(session
);
634 // Try to create a stream after receiving a GOAWAY frame. It should
636 TEST_P(SpdySessionTest
, CreateStreamAfterGoAway
) {
637 session_deps_
.host_resolver
->set_synchronous_mode(true);
639 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
641 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
642 CreateMockRead(*goaway
, 2),
643 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
644 MockRead(ASYNC
, 0, 4) // EOF
646 scoped_ptr
<SpdyFrame
> req(
647 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
648 MockWrite writes
[] = {
649 CreateMockWrite(*req
, 0),
651 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
652 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
654 CreateNetworkSession();
656 base::WeakPtr
<SpdySession
> session
=
657 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
659 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
661 GURL
url(kDefaultURL
);
662 base::WeakPtr
<SpdyStream
> spdy_stream
=
663 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
664 session
, url
, MEDIUM
, BoundNetLog());
665 test::StreamDelegateDoNothing
delegate(spdy_stream
);
666 spdy_stream
->SetDelegate(&delegate
);
668 scoped_ptr
<SpdyHeaderBlock
> headers(
669 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
670 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
671 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
673 base::RunLoop().RunUntilIdle();
675 EXPECT_EQ(1u, spdy_stream
->stream_id());
677 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
679 // Read and process the GOAWAY frame.
681 base::RunLoop().RunUntilIdle();
683 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
684 EXPECT_TRUE(session
->IsStreamActive(1));
686 SpdyStreamRequest stream_request
;
687 int rv
= stream_request
.StartRequest(
688 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog(),
689 CompletionCallback());
690 EXPECT_EQ(ERR_FAILED
, rv
);
692 EXPECT_TRUE(session
);
694 base::RunLoop().RunUntilIdle();
695 EXPECT_FALSE(session
);
698 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
699 // the stream being refused.
700 TEST_P(SpdySessionTest
, SynStreamAfterGoAway
) {
701 session_deps_
.host_resolver
->set_synchronous_mode(true);
703 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
704 scoped_ptr
<SpdyFrame
> push(
705 spdy_util_
.ConstructSpdyPush(nullptr, 0, 2, 1, kDefaultURL
));
707 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
708 CreateMockRead(*goaway
, 2),
709 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
710 CreateMockRead(*push
, 4),
711 MockRead(ASYNC
, 0, 6) // EOF
713 scoped_ptr
<SpdyFrame
> req(
714 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
715 scoped_ptr
<SpdyFrame
> rst(
716 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
717 MockWrite writes
[] = {CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5)};
718 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
719 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
721 CreateNetworkSession();
723 base::WeakPtr
<SpdySession
> session
=
724 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
726 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
728 GURL
url(kDefaultURL
);
729 base::WeakPtr
<SpdyStream
> spdy_stream
=
730 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
731 session
, url
, MEDIUM
, BoundNetLog());
732 test::StreamDelegateDoNothing
delegate(spdy_stream
);
733 spdy_stream
->SetDelegate(&delegate
);
735 scoped_ptr
<SpdyHeaderBlock
> headers(
736 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
737 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
738 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
740 base::RunLoop().RunUntilIdle();
742 EXPECT_EQ(1u, spdy_stream
->stream_id());
744 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
746 // Read and process the GOAWAY frame.
748 base::RunLoop().RunUntilIdle();
750 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
751 EXPECT_TRUE(session
->IsStreamActive(1));
753 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
756 base::RunLoop().RunUntilIdle();
757 EXPECT_FALSE(session
);
760 // A session observing a network change with active streams should close
761 // when the last active stream is closed.
762 TEST_P(SpdySessionTest
, NetworkChangeWithActiveStreams
) {
763 session_deps_
.host_resolver
->set_synchronous_mode(true);
766 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
768 scoped_ptr
<SpdyFrame
> req1(
769 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
770 MockWrite writes
[] = {
771 CreateMockWrite(*req1
, 0),
773 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
774 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
776 CreateNetworkSession();
778 base::WeakPtr
<SpdySession
> session
=
779 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
781 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
783 base::WeakPtr
<SpdyStream
> spdy_stream
=
784 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
, session
,
785 GURL(kDefaultURL
), MEDIUM
, BoundNetLog());
786 test::StreamDelegateDoNothing
delegate(spdy_stream
);
787 spdy_stream
->SetDelegate(&delegate
);
789 scoped_ptr
<SpdyHeaderBlock
> headers(
790 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
792 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
793 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
795 base::RunLoop().RunUntilIdle();
797 EXPECT_EQ(1u, spdy_stream
->stream_id());
799 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
801 spdy_session_pool_
->OnIPAddressChanged();
803 // The SpdySessionPool behavior differs based on how the OSs reacts to
804 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
805 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
806 // For OSs where the TCP connections will close upon relevant network
807 // changes, SpdySessionPool doesn't need to force them to close, so in these
808 // cases verify the session has become unavailable but remains open and the
809 // pre-existing stream is still active.
810 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
812 EXPECT_TRUE(session
->IsGoingAway());
814 EXPECT_TRUE(session
->IsStreamActive(1));
816 // Should close the session.
817 spdy_stream
->Close();
819 EXPECT_FALSE(spdy_stream
);
822 base::RunLoop().RunUntilIdle();
823 EXPECT_FALSE(session
);
826 TEST_P(SpdySessionTest
, ClientPing
) {
827 session_deps_
.enable_ping
= true;
828 session_deps_
.host_resolver
->set_synchronous_mode(true);
830 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(1, true));
832 CreateMockRead(*read_ping
, 1),
833 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
834 MockRead(ASYNC
, 0, 3) // EOF
836 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
837 MockWrite writes
[] = {
838 CreateMockWrite(*write_ping
, 0),
840 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
841 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
843 CreateNetworkSession();
845 base::WeakPtr
<SpdySession
> session
=
846 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
848 base::WeakPtr
<SpdyStream
> spdy_stream1
=
849 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
850 session
, test_url_
, MEDIUM
, BoundNetLog());
851 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
852 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
853 spdy_stream1
->SetDelegate(&delegate
);
855 base::TimeTicks before_ping_time
= base::TimeTicks::Now();
857 session
->set_connection_at_risk_of_loss_time(
858 base::TimeDelta::FromSeconds(-1));
859 session
->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
861 session
->SendPrefacePingIfNoneInFlight();
863 base::RunLoop().RunUntilIdle();
865 session
->CheckPingStatus(before_ping_time
);
867 EXPECT_EQ(0, session
->pings_in_flight());
868 EXPECT_GE(session
->next_ping_id(), 1U);
869 EXPECT_FALSE(session
->check_ping_status_pending());
870 EXPECT_GE(session
->last_activity_time(), before_ping_time
);
873 base::RunLoop().RunUntilIdle();
875 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
877 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
878 EXPECT_FALSE(session
);
881 TEST_P(SpdySessionTest
, ServerPing
) {
882 session_deps_
.host_resolver
->set_synchronous_mode(true);
884 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(2, false));
886 CreateMockRead(*read_ping
),
887 MockRead(SYNCHRONOUS
, 0, 0) // EOF
889 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(2, true));
890 MockWrite writes
[] = {
891 CreateMockWrite(*write_ping
),
893 StaticSocketDataProvider
data(
894 reads
, arraysize(reads
), writes
, arraysize(writes
));
895 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
897 CreateNetworkSession();
899 base::WeakPtr
<SpdySession
> session
=
900 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
902 base::WeakPtr
<SpdyStream
> spdy_stream1
=
903 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
904 session
, test_url_
, MEDIUM
, BoundNetLog());
905 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
906 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
907 spdy_stream1
->SetDelegate(&delegate
);
909 // Flush the read completion task.
910 base::RunLoop().RunUntilIdle();
912 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
914 EXPECT_FALSE(session
);
915 EXPECT_FALSE(spdy_stream1
);
918 // Cause a ping to be sent out while producing a write. The write loop
919 // should handle this properly, i.e. another DoWriteLoop task should
920 // not be posted. This is a regression test for
921 // http://crbug.com/261043 .
922 TEST_P(SpdySessionTest
, PingAndWriteLoop
) {
923 session_deps_
.enable_ping
= true;
924 session_deps_
.time_func
= TheNearFuture
;
926 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
927 scoped_ptr
<SpdyFrame
> req(
928 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
929 MockWrite writes
[] = {
930 CreateMockWrite(*req
, 0),
931 CreateMockWrite(*write_ping
, 1),
935 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
938 session_deps_
.host_resolver
->set_synchronous_mode(true);
940 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
941 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
943 CreateNetworkSession();
945 base::WeakPtr
<SpdySession
> session
=
946 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
948 GURL
url(kDefaultURL
);
949 base::WeakPtr
<SpdyStream
> spdy_stream
=
950 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
951 session
, url
, LOWEST
, BoundNetLog());
952 test::StreamDelegateDoNothing
delegate(spdy_stream
);
953 spdy_stream
->SetDelegate(&delegate
);
955 scoped_ptr
<SpdyHeaderBlock
> headers(
956 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
957 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
959 // Shift time so that a ping will be sent out.
960 g_time_delta
= base::TimeDelta::FromSeconds(11);
962 base::RunLoop().RunUntilIdle();
963 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting");
966 base::RunLoop().RunUntilIdle();
967 EXPECT_FALSE(session
);
970 TEST_P(SpdySessionTest
, StreamIdSpaceExhausted
) {
971 const SpdyStreamId kLastStreamId
= 0x7fffffff;
972 session_deps_
.host_resolver
->set_synchronous_mode(true);
974 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
975 // fixed to allow for two stream ID assignments, and three concurrent
976 // streams. Four streams are started, and two are activated. Verify the
977 // session goes away, and that the created (but not activated) and
978 // stalled streams are aborted. Also verify the activated streams complete,
979 // at which point the session closes.
981 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyGet(
982 nullptr, 0, false, kLastStreamId
- 2, MEDIUM
, true));
983 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyGet(
984 nullptr, 0, false, kLastStreamId
, MEDIUM
, true));
986 MockWrite writes
[] = {
987 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
990 scoped_ptr
<SpdyFrame
> resp1(
991 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId
- 2));
992 scoped_ptr
<SpdyFrame
> resp2(
993 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId
));
995 scoped_ptr
<SpdyFrame
> body1(
996 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
- 2, true));
997 scoped_ptr
<SpdyFrame
> body2(
998 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
, true));
1000 MockRead reads
[] = {
1001 CreateMockRead(*resp1
, 2),
1002 CreateMockRead(*resp2
, 3),
1003 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
1004 CreateMockRead(*body1
, 5),
1005 CreateMockRead(*body2
, 6),
1006 MockRead(ASYNC
, 0, 7) // EOF
1009 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1010 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1012 CreateNetworkSession();
1013 base::WeakPtr
<SpdySession
> session
=
1014 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1016 // Fix stream_hi_water_mark_ to allow for two stream activations.
1017 session
->stream_hi_water_mark_
= kLastStreamId
- 2;
1018 // Fix max_concurrent_streams to allow for three stream creations.
1019 session
->max_concurrent_streams_
= 3;
1021 // Create three streams synchronously, and begin a fourth (which is stalled).
1022 GURL
url(kDefaultURL
);
1023 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
1024 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1025 test::StreamDelegateDoNothing
delegate1(stream1
);
1026 stream1
->SetDelegate(&delegate1
);
1028 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
1029 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1030 test::StreamDelegateDoNothing
delegate2(stream2
);
1031 stream2
->SetDelegate(&delegate2
);
1033 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
1034 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1035 test::StreamDelegateDoNothing
delegate3(stream3
);
1036 stream3
->SetDelegate(&delegate3
);
1038 SpdyStreamRequest request4
;
1039 TestCompletionCallback callback4
;
1040 EXPECT_EQ(ERR_IO_PENDING
,
1041 request4
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
,
1046 callback4
.callback()));
1048 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1049 EXPECT_EQ(0u, session
->num_active_streams());
1050 EXPECT_EQ(3u, session
->num_created_streams());
1051 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1053 // Activate stream 1. One ID remains available.
1054 stream1
->SendRequestHeaders(
1055 scoped_ptr
<SpdyHeaderBlock
>(
1056 spdy_util_
.ConstructGetHeaderBlock(url
.spec())),
1057 NO_MORE_DATA_TO_SEND
);
1058 base::RunLoop().RunUntilIdle();
1060 EXPECT_EQ(kLastStreamId
- 2u, stream1
->stream_id());
1061 EXPECT_EQ(1u, session
->num_active_streams());
1062 EXPECT_EQ(2u, session
->num_created_streams());
1063 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1065 // Activate stream 2. ID space is exhausted.
1066 stream2
->SendRequestHeaders(
1067 scoped_ptr
<SpdyHeaderBlock
>(
1068 spdy_util_
.ConstructGetHeaderBlock(url
.spec())),
1069 NO_MORE_DATA_TO_SEND
);
1070 base::RunLoop().RunUntilIdle();
1072 // Active streams remain active.
1073 EXPECT_EQ(kLastStreamId
, stream2
->stream_id());
1074 EXPECT_EQ(2u, session
->num_active_streams());
1076 // Session is going away. Created and stalled streams were aborted.
1077 EXPECT_EQ(SpdySession::STATE_GOING_AWAY
, session
->availability_state_
);
1078 EXPECT_EQ(ERR_ABORTED
, delegate3
.WaitForClose());
1079 EXPECT_EQ(ERR_ABORTED
, callback4
.WaitForResult());
1080 EXPECT_EQ(0u, session
->num_created_streams());
1081 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1083 // Read responses on remaining active streams.
1084 data
.CompleteRead();
1085 base::RunLoop().RunUntilIdle();
1086 EXPECT_EQ(OK
, delegate1
.WaitForClose());
1087 EXPECT_EQ(kUploadData
, delegate1
.TakeReceivedData());
1088 EXPECT_EQ(OK
, delegate2
.WaitForClose());
1089 EXPECT_EQ(kUploadData
, delegate2
.TakeReceivedData());
1091 // Session was destroyed.
1092 EXPECT_FALSE(session
);
1095 // Verifies that an unstalled pending stream creation racing with a new stream
1096 // creation doesn't violate the maximum stream concurrency. Regression test for
1097 // crbug.com/373858.
1098 TEST_P(SpdySessionTest
, UnstallRacesWithStreamCreation
) {
1099 session_deps_
.host_resolver
->set_synchronous_mode(true);
1101 MockRead reads
[] = {
1102 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1105 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1106 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1108 CreateNetworkSession();
1109 base::WeakPtr
<SpdySession
> session
=
1110 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1112 // Fix max_concurrent_streams to allow for one open stream.
1113 session
->max_concurrent_streams_
= 1;
1115 // Create two streams: one synchronously, and one which stalls.
1116 GURL
url(kDefaultURL
);
1117 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
1118 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1120 SpdyStreamRequest request2
;
1121 TestCompletionCallback callback2
;
1122 EXPECT_EQ(ERR_IO_PENDING
,
1123 request2
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
,
1128 callback2
.callback()));
1130 EXPECT_EQ(1u, session
->num_created_streams());
1131 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1133 // Cancel the first stream. A callback to unstall the second stream was
1134 // posted. Don't run it yet.
1137 EXPECT_EQ(0u, session
->num_created_streams());
1138 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1140 // Create a third stream prior to the second stream's callback.
1141 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
1142 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1144 EXPECT_EQ(1u, session
->num_created_streams());
1145 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1147 // Now run the message loop. The unstalled stream will re-stall itself.
1148 base::RunLoop().RunUntilIdle();
1149 EXPECT_EQ(1u, session
->num_created_streams());
1150 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1152 // Cancel the third stream and run the message loop. Verify that the second
1153 // stream creation now completes.
1155 base::RunLoop().RunUntilIdle();
1157 EXPECT_EQ(1u, session
->num_created_streams());
1158 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1159 EXPECT_EQ(OK
, callback2
.WaitForResult());
1162 TEST_P(SpdySessionTest
, DeleteExpiredPushStreams
) {
1163 session_deps_
.host_resolver
->set_synchronous_mode(true);
1164 session_deps_
.time_func
= TheNearFuture
;
1166 scoped_ptr
<SpdyFrame
> req(
1167 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
1168 scoped_ptr
<SpdyFrame
> rst(
1169 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
1170 MockWrite writes
[] = {CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5)};
1172 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
1173 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
1174 scoped_ptr
<SpdyFrame
> push_a_body(
1175 spdy_util_
.ConstructSpdyBodyFrame(2, false));
1176 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1177 // iterators inside. See http://crbug.com/443490
1178 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
1179 nullptr, 0, 4, 1, "http://www.example.org/0.dat"));
1180 MockRead reads
[] = {
1181 CreateMockRead(*push_a
, 1),
1182 CreateMockRead(*push_a_body
, 2),
1183 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
1184 CreateMockRead(*push_b
, 4),
1185 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
1186 MockRead(ASYNC
, 0, 7) // EOF
1189 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1190 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1192 CreateNetworkSession();
1193 base::WeakPtr
<SpdySession
> session
=
1194 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1196 // Process the principal request, and the first push stream request & body.
1197 GURL
url(kDefaultURL
);
1198 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1199 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1200 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1201 spdy_stream
->SetDelegate(&delegate
);
1203 scoped_ptr
<SpdyHeaderBlock
> headers(
1204 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1205 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1207 base::RunLoop().RunUntilIdle();
1209 // Verify that there is one unclaimed push stream.
1210 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
1211 SpdySession::PushedStreamMap::iterator iter
=
1212 session
->unclaimed_pushed_streams_
.find(
1213 GURL("http://www.example.org/a.dat"));
1214 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
1216 if (session
->flow_control_state_
==
1217 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1218 // Unclaimed push body consumed bytes from the session window.
1220 SpdySession::GetDefaultInitialWindowSize(GetParam()) - kUploadDataSize
,
1221 session
->session_recv_window_size_
);
1222 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
1225 // Shift time to expire the push stream. Read the second SYN_STREAM,
1226 // and verify a RST_STREAM was written.
1227 g_time_delta
= base::TimeDelta::FromSeconds(301);
1228 data
.CompleteRead();
1229 base::RunLoop().RunUntilIdle();
1231 // Verify that the second pushed stream evicted the first pushed stream.
1232 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
1233 iter
= session
->unclaimed_pushed_streams_
.find(
1234 GURL("http://www.example.org/0.dat"));
1235 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
1237 if (session
->flow_control_state_
==
1238 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1239 // Verify that the session window reclaimed the evicted stream body.
1240 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
1241 session
->session_recv_window_size_
);
1242 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
1245 // Read and process EOF.
1246 EXPECT_TRUE(session
);
1247 data
.CompleteRead();
1248 base::RunLoop().RunUntilIdle();
1249 EXPECT_FALSE(session
);
1252 TEST_P(SpdySessionTest
, FailedPing
) {
1253 session_deps_
.host_resolver
->set_synchronous_mode(true);
1255 MockRead reads
[] = {
1256 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1258 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
1259 scoped_ptr
<SpdyFrame
> goaway(
1260 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Failed ping."));
1261 MockWrite writes
[] = {CreateMockWrite(*write_ping
), CreateMockWrite(*goaway
)};
1263 StaticSocketDataProvider
data(
1264 reads
, arraysize(reads
), writes
, arraysize(writes
));
1265 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1267 CreateNetworkSession();
1269 base::WeakPtr
<SpdySession
> session
=
1270 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1272 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1273 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1274 session
, test_url_
, MEDIUM
, BoundNetLog());
1275 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1276 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
1277 spdy_stream1
->SetDelegate(&delegate
);
1279 session
->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1280 session
->set_hung_interval(base::TimeDelta::FromSeconds(0));
1282 // Send a PING frame.
1283 session
->WritePingFrame(1, false);
1284 EXPECT_LT(0, session
->pings_in_flight());
1285 EXPECT_GE(session
->next_ping_id(), 1U);
1286 EXPECT_TRUE(session
->check_ping_status_pending());
1288 // Assert session is not closed.
1289 EXPECT_TRUE(session
->IsAvailable());
1290 EXPECT_LT(0u, session
->num_active_streams() + session
->num_created_streams());
1291 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1293 // We set last time we have received any data in 1 sec less than now.
1294 // CheckPingStatus will trigger timeout because hung interval is zero.
1295 base::TimeTicks now
= base::TimeTicks::Now();
1296 session
->last_activity_time_
= now
- base::TimeDelta::FromSeconds(1);
1297 session
->CheckPingStatus(now
);
1298 base::RunLoop().RunUntilIdle();
1300 EXPECT_FALSE(session
);
1301 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1302 EXPECT_FALSE(spdy_stream1
);
1305 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1306 // settings frame increasing the max concurrent streams by 1. Make
1307 // sure nothing blows up. This is a regression test for
1308 // http://crbug.com/57331 .
1309 TEST_P(SpdySessionTest
, OnSettings
) {
1310 session_deps_
.host_resolver
->set_synchronous_mode(true);
1312 const SpdySettingsIds kSpdySettingsIds
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1315 std::vector
<MockWrite
> writes
;
1316 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1317 if (GetParam() >= kProtoHTTP2MinimumVersion
) {
1318 writes
.push_back(CreateMockWrite(*settings_ack
, ++seq
));
1321 SettingsMap new_settings
;
1322 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1323 new_settings
[kSpdySettingsIds
] =
1324 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1325 scoped_ptr
<SpdyFrame
> settings_frame(
1326 spdy_util_
.ConstructSpdySettings(new_settings
));
1327 MockRead reads
[] = {
1328 CreateMockRead(*settings_frame
, 0),
1329 MockRead(ASYNC
, ERR_IO_PENDING
, ++seq
),
1330 MockRead(ASYNC
, 0, ++seq
),
1333 SequencedSocketData
data(reads
, arraysize(reads
), vector_as_array(&writes
),
1335 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1337 CreateNetworkSession();
1339 base::WeakPtr
<SpdySession
> session
=
1340 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1342 // Create the maximum number of concurrent streams.
1343 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1344 base::WeakPtr
<SpdyStream
> spdy_stream
=
1345 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1346 session
, test_url_
, MEDIUM
, BoundNetLog());
1347 ASSERT_TRUE(spdy_stream
!= nullptr);
1350 StreamReleaserCallback stream_releaser
;
1351 SpdyStreamRequest request
;
1352 ASSERT_EQ(ERR_IO_PENDING
,
1353 request
.StartRequest(
1354 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1356 stream_releaser
.MakeCallback(&request
)));
1358 base::RunLoop().RunUntilIdle();
1360 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1362 data
.CompleteRead();
1363 base::RunLoop().RunUntilIdle();
1364 EXPECT_FALSE(session
);
1366 EXPECT_TRUE(data
.AllWriteDataConsumed());
1367 EXPECT_TRUE(data
.AllReadDataConsumed());
1370 // Start with a persisted value for max concurrent streams. Receive a
1371 // settings frame increasing the max concurrent streams by 1 and which
1372 // also clears the persisted data. Verify that persisted data is
1374 TEST_P(SpdySessionTest
, ClearSettings
) {
1375 if (spdy_util_
.spdy_version() >= HTTP2
) {
1376 // HTTP/2 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1377 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in HTTP/2.
1380 session_deps_
.host_resolver
->set_synchronous_mode(true);
1382 SettingsMap new_settings
;
1383 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1384 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1385 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1386 scoped_ptr
<SpdyFrame
> settings_frame(
1387 spdy_util_
.ConstructSpdySettings(new_settings
));
1388 uint8 flags
= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
1389 test::SetFrameFlags(settings_frame
.get(), flags
, spdy_util_
.spdy_version());
1390 MockRead reads
[] = {
1391 CreateMockRead(*settings_frame
, 0),
1392 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
1393 MockRead(ASYNC
, 0, 2),
1396 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
1397 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1399 CreateNetworkSession();
1401 // Initialize the SpdySetting with the default.
1402 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1403 test_host_port_pair_
,
1404 SETTINGS_MAX_CONCURRENT_STREAMS
,
1405 SETTINGS_FLAG_PLEASE_PERSIST
,
1406 kInitialMaxConcurrentStreams
);
1409 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1410 test_host_port_pair_
).empty());
1412 base::WeakPtr
<SpdySession
> session
=
1413 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1415 // Create the maximum number of concurrent streams.
1416 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1417 base::WeakPtr
<SpdyStream
> spdy_stream
=
1418 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1419 session
, test_url_
, MEDIUM
, BoundNetLog());
1420 ASSERT_TRUE(spdy_stream
!= nullptr);
1423 StreamReleaserCallback stream_releaser
;
1425 SpdyStreamRequest request
;
1426 ASSERT_EQ(ERR_IO_PENDING
,
1427 request
.StartRequest(
1428 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1430 stream_releaser
.MakeCallback(&request
)));
1432 base::RunLoop().RunUntilIdle();
1434 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1436 // Make sure that persisted data is cleared.
1438 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1439 test_host_port_pair_
).empty());
1441 // Make sure session's max_concurrent_streams is correct.
1442 EXPECT_EQ(kInitialMaxConcurrentStreams
+ 1,
1443 session
->max_concurrent_streams());
1445 data
.CompleteRead();
1446 base::RunLoop().RunUntilIdle();
1447 EXPECT_FALSE(session
);
1450 // Start with max concurrent streams set to 1. Request two streams.
1451 // When the first completes, have the callback close its stream, which
1452 // should trigger the second stream creation. Then cancel that one
1453 // immediately. Don't crash. This is a regression test for
1454 // http://crbug.com/63532 .
1455 TEST_P(SpdySessionTest
, CancelPendingCreateStream
) {
1456 session_deps_
.host_resolver
->set_synchronous_mode(true);
1458 MockRead reads
[] = {
1459 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1462 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1463 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1465 CreateNetworkSession();
1467 // Initialize the SpdySetting with 1 max concurrent streams.
1468 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1469 test_host_port_pair_
,
1470 SETTINGS_MAX_CONCURRENT_STREAMS
,
1471 SETTINGS_FLAG_PLEASE_PERSIST
,
1474 base::WeakPtr
<SpdySession
> session
=
1475 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1477 // Leave room for only one more stream to be created.
1478 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
1479 base::WeakPtr
<SpdyStream
> spdy_stream
=
1480 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1481 session
, test_url_
, MEDIUM
, BoundNetLog());
1482 ASSERT_TRUE(spdy_stream
!= nullptr);
1485 // Create 2 more streams. First will succeed. Second will be pending.
1486 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1487 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1488 session
, test_url_
, MEDIUM
, BoundNetLog());
1489 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1491 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1492 // a valgrind error if the callback is invoked when it's not supposed to be.
1493 scoped_ptr
<TestCompletionCallback
> callback(new TestCompletionCallback
);
1495 SpdyStreamRequest request
;
1496 ASSERT_EQ(ERR_IO_PENDING
,
1497 request
.StartRequest(
1498 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1500 callback
->callback()));
1502 // Release the first one, this will allow the second to be created.
1503 spdy_stream1
->Cancel();
1504 EXPECT_FALSE(spdy_stream1
);
1506 request
.CancelRequest();
1509 // Should not crash when running the pending callback.
1510 base::RunLoop().RunUntilIdle();
1513 TEST_P(SpdySessionTest
, SendInitialDataOnNewSession
) {
1514 session_deps_
.host_resolver
->set_synchronous_mode(true);
1516 MockRead reads
[] = {
1517 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1520 SettingsMap settings
;
1521 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1522 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
1523 scoped_ptr
<SpdyFrame
> settings_frame(
1524 spdy_util_
.ConstructSpdySettings(settings
));
1525 std::vector
<MockWrite
> writes
;
1526 if ((GetParam() >= kProtoHTTP2MinimumVersion
) &&
1527 (GetParam() <= kProtoHTTP2MaximumVersion
)) {
1530 kHttp2ConnectionHeaderPrefix
,
1531 kHttp2ConnectionHeaderPrefixSize
));
1533 writes
.push_back(CreateMockWrite(*settings_frame
));
1535 SettingsMap server_settings
;
1536 const uint32 initial_max_concurrent_streams
= 1;
1537 server_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1538 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED
,
1539 initial_max_concurrent_streams
);
1540 scoped_ptr
<SpdyFrame
> server_settings_frame(
1541 spdy_util_
.ConstructSpdySettings(server_settings
));
1542 if (GetParam() <= kProtoSPDY31
) {
1543 writes
.push_back(CreateMockWrite(*server_settings_frame
));
1546 StaticSocketDataProvider
data(reads
, arraysize(reads
),
1547 vector_as_array(&writes
), writes
.size());
1548 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1550 CreateNetworkSession();
1552 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1553 test_host_port_pair_
,
1554 SETTINGS_MAX_CONCURRENT_STREAMS
,
1555 SETTINGS_FLAG_PLEASE_PERSIST
,
1556 initial_max_concurrent_streams
);
1558 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
1559 pool_peer
.SetEnableSendingInitialData(true);
1561 base::WeakPtr
<SpdySession
> session
=
1562 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1564 base::RunLoop().RunUntilIdle();
1565 EXPECT_TRUE(data
.AllWriteDataConsumed());
1568 TEST_P(SpdySessionTest
, ClearSettingsStorageOnIPAddressChanged
) {
1569 CreateNetworkSession();
1571 base::WeakPtr
<HttpServerProperties
> test_http_server_properties
=
1572 spdy_session_pool_
->http_server_properties();
1573 SettingsFlagsAndValue
flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST
, 2);
1574 test_http_server_properties
->SetSpdySetting(
1575 test_host_port_pair_
,
1576 SETTINGS_MAX_CONCURRENT_STREAMS
,
1577 SETTINGS_FLAG_PLEASE_PERSIST
,
1579 EXPECT_NE(0u, test_http_server_properties
->GetSpdySettings(
1580 test_host_port_pair_
).size());
1581 spdy_session_pool_
->OnIPAddressChanged();
1582 EXPECT_EQ(0u, test_http_server_properties
->GetSpdySettings(
1583 test_host_port_pair_
).size());
1586 TEST_P(SpdySessionTest
, Initialize
) {
1587 BoundTestNetLog log
;
1588 session_deps_
.net_log
= log
.bound().net_log();
1589 session_deps_
.host_resolver
->set_synchronous_mode(true);
1591 MockRead reads
[] = {
1592 MockRead(ASYNC
, 0, 0) // EOF
1595 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1596 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1598 CreateNetworkSession();
1600 base::WeakPtr
<SpdySession
> session
=
1601 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1602 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1604 // Flush the read completion task.
1605 base::RunLoop().RunUntilIdle();
1607 TestNetLogEntry::List entries
;
1608 log
.GetEntries(&entries
);
1609 EXPECT_LT(0u, entries
.size());
1611 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1612 int pos
= ExpectLogContainsSomewhere(
1613 entries
, 0, NetLog::TYPE_HTTP2_SESSION_INITIALIZED
, NetLog::PHASE_NONE
);
1616 TestNetLogEntry entry
= entries
[pos
];
1617 NetLog::Source socket_source
;
1618 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry
.params
.get(),
1620 EXPECT_TRUE(socket_source
.IsValid());
1621 EXPECT_NE(log
.bound().source().id
, socket_source
.id
);
1624 TEST_P(SpdySessionTest
, NetLogOnSessionGoaway
) {
1625 session_deps_
.host_resolver
->set_synchronous_mode(true);
1627 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
1628 MockRead reads
[] = {
1629 CreateMockRead(*goaway
),
1630 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1633 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1634 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1636 CreateNetworkSession();
1638 BoundTestNetLog log
;
1639 base::WeakPtr
<SpdySession
> session
=
1640 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1641 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1643 // Flush the read completion task.
1644 base::RunLoop().RunUntilIdle();
1646 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1647 EXPECT_FALSE(session
);
1649 // Check that the NetLog was filled reasonably.
1650 TestNetLogEntry::List entries
;
1651 log
.GetEntries(&entries
);
1652 EXPECT_LT(0u, entries
.size());
1654 // Check that we logged SPDY_SESSION_CLOSE correctly.
1655 int pos
= ExpectLogContainsSomewhere(
1656 entries
, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE
, NetLog::PHASE_NONE
);
1658 if (pos
< static_cast<int>(entries
.size())) {
1659 TestNetLogEntry entry
= entries
[pos
];
1661 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1662 EXPECT_EQ(OK
, error_code
);
1668 TEST_P(SpdySessionTest
, NetLogOnSessionEOF
) {
1669 session_deps_
.host_resolver
->set_synchronous_mode(true);
1671 MockRead reads
[] = {
1672 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1675 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1676 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1678 CreateNetworkSession();
1680 BoundTestNetLog log
;
1681 base::WeakPtr
<SpdySession
> session
=
1682 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1683 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1685 // Flush the read completion task.
1686 base::RunLoop().RunUntilIdle();
1688 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1689 EXPECT_FALSE(session
);
1691 // Check that the NetLog was filled reasonably.
1692 TestNetLogEntry::List entries
;
1693 log
.GetEntries(&entries
);
1694 EXPECT_LT(0u, entries
.size());
1696 // Check that we logged SPDY_SESSION_CLOSE correctly.
1697 int pos
= ExpectLogContainsSomewhere(
1698 entries
, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE
, NetLog::PHASE_NONE
);
1700 if (pos
< static_cast<int>(entries
.size())) {
1701 TestNetLogEntry entry
= entries
[pos
];
1703 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1704 EXPECT_EQ(ERR_CONNECTION_CLOSED
, error_code
);
1710 TEST_P(SpdySessionTest
, SynCompressionHistograms
) {
1711 session_deps_
.enable_compression
= true;
1713 scoped_ptr
<SpdyFrame
> req(
1714 spdy_util_
.ConstructSpdyGet(nullptr, 0, true, 1, MEDIUM
, true));
1715 MockWrite writes
[] = {
1716 CreateMockWrite(*req
, 0),
1718 MockRead reads
[] = {
1719 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
1721 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1722 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1724 CreateNetworkSession();
1725 base::WeakPtr
<SpdySession
> session
=
1726 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1728 GURL
url(kDefaultURL
);
1729 base::WeakPtr
<SpdyStream
> spdy_stream
=
1730 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1731 session
, url
, MEDIUM
, BoundNetLog());
1732 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1733 spdy_stream
->SetDelegate(&delegate
);
1735 scoped_ptr
<SpdyHeaderBlock
> headers(
1736 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1737 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1738 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
1740 // Write request headers & capture resulting histogram update.
1741 base::HistogramTester histogram_tester
;
1743 base::RunLoop().RunUntilIdle();
1744 // Regression test of compression performance under the request fixture.
1745 switch (spdy_util_
.spdy_version()) {
1747 histogram_tester
.ExpectBucketCount(
1748 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1751 histogram_tester
.ExpectBucketCount(
1752 "Net.SpdySynStreamCompressionPercentage", 81, 1);
1758 // Read and process EOF.
1759 EXPECT_TRUE(session
);
1760 data
.CompleteRead();
1761 base::RunLoop().RunUntilIdle();
1762 EXPECT_FALSE(session
);
1765 // Queue up a low-priority SYN_STREAM followed by a high-priority
1766 // one. The high priority one should still send first and receive
1768 TEST_P(SpdySessionTest
, OutOfOrderSynStreams
) {
1769 // Construct the request.
1770 scoped_ptr
<SpdyFrame
> req_highest(
1771 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, HIGHEST
, true));
1772 scoped_ptr
<SpdyFrame
> req_lowest(
1773 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST
, true));
1774 MockWrite writes
[] = {
1775 CreateMockWrite(*req_highest
, 0),
1776 CreateMockWrite(*req_lowest
, 1),
1779 scoped_ptr
<SpdyFrame
> resp_highest(
1780 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
1781 scoped_ptr
<SpdyFrame
> body_highest(
1782 spdy_util_
.ConstructSpdyBodyFrame(1, true));
1783 scoped_ptr
<SpdyFrame
> resp_lowest(
1784 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
1785 scoped_ptr
<SpdyFrame
> body_lowest(
1786 spdy_util_
.ConstructSpdyBodyFrame(3, true));
1787 MockRead reads
[] = {
1788 CreateMockRead(*resp_highest
, 2),
1789 CreateMockRead(*body_highest
, 3),
1790 CreateMockRead(*resp_lowest
, 4),
1791 CreateMockRead(*body_lowest
, 5),
1792 MockRead(ASYNC
, 0, 6) // EOF
1795 session_deps_
.host_resolver
->set_synchronous_mode(true);
1797 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1798 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1800 CreateNetworkSession();
1802 base::WeakPtr
<SpdySession
> session
=
1803 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1805 GURL
url(kDefaultURL
);
1807 base::WeakPtr
<SpdyStream
> spdy_stream_lowest
=
1808 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1809 session
, url
, LOWEST
, BoundNetLog());
1810 ASSERT_TRUE(spdy_stream_lowest
);
1811 EXPECT_EQ(0u, spdy_stream_lowest
->stream_id());
1812 test::StreamDelegateDoNothing
delegate_lowest(spdy_stream_lowest
);
1813 spdy_stream_lowest
->SetDelegate(&delegate_lowest
);
1815 base::WeakPtr
<SpdyStream
> spdy_stream_highest
=
1816 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1817 session
, url
, HIGHEST
, BoundNetLog());
1818 ASSERT_TRUE(spdy_stream_highest
);
1819 EXPECT_EQ(0u, spdy_stream_highest
->stream_id());
1820 test::StreamDelegateDoNothing
delegate_highest(spdy_stream_highest
);
1821 spdy_stream_highest
->SetDelegate(&delegate_highest
);
1823 // Queue the lower priority one first.
1825 scoped_ptr
<SpdyHeaderBlock
> headers_lowest(
1826 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1827 spdy_stream_lowest
->SendRequestHeaders(
1828 headers_lowest
.Pass(), NO_MORE_DATA_TO_SEND
);
1829 EXPECT_TRUE(spdy_stream_lowest
->HasUrlFromHeaders());
1831 scoped_ptr
<SpdyHeaderBlock
> headers_highest(
1832 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1833 spdy_stream_highest
->SendRequestHeaders(
1834 headers_highest
.Pass(), NO_MORE_DATA_TO_SEND
);
1835 EXPECT_TRUE(spdy_stream_highest
->HasUrlFromHeaders());
1837 base::RunLoop().RunUntilIdle();
1839 EXPECT_FALSE(spdy_stream_lowest
);
1840 EXPECT_FALSE(spdy_stream_highest
);
1841 EXPECT_EQ(3u, delegate_lowest
.stream_id());
1842 EXPECT_EQ(1u, delegate_highest
.stream_id());
1845 TEST_P(SpdySessionTest
, CancelStream
) {
1846 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1847 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1848 scoped_ptr
<SpdyFrame
> req2(
1849 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
1850 MockWrite writes
[] = {
1851 CreateMockWrite(*req2
, 0),
1854 scoped_ptr
<SpdyFrame
> resp2(
1855 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
1856 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1857 MockRead reads
[] = {
1858 CreateMockRead(*resp2
, 1),
1859 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
1860 CreateMockRead(*body2
, 3),
1861 MockRead(ASYNC
, 0, 4) // EOF
1864 session_deps_
.host_resolver
->set_synchronous_mode(true);
1866 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1867 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1869 CreateNetworkSession();
1871 base::WeakPtr
<SpdySession
> session
=
1872 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1874 GURL
url1(kDefaultURL
);
1875 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1876 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1877 session
, url1
, HIGHEST
, BoundNetLog());
1878 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1879 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1880 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
1881 spdy_stream1
->SetDelegate(&delegate1
);
1883 GURL
url2(kDefaultURL
);
1884 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1885 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1886 session
, url2
, LOWEST
, BoundNetLog());
1887 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
1888 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1889 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
1890 spdy_stream2
->SetDelegate(&delegate2
);
1892 scoped_ptr
<SpdyHeaderBlock
> headers(
1893 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1894 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1895 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1897 scoped_ptr
<SpdyHeaderBlock
> headers2(
1898 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1899 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1900 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1902 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1904 spdy_stream1
->Cancel();
1905 EXPECT_FALSE(spdy_stream1
);
1907 EXPECT_EQ(0u, delegate1
.stream_id());
1909 base::RunLoop().RunUntilIdle();
1911 EXPECT_EQ(0u, delegate1
.stream_id());
1912 EXPECT_EQ(1u, delegate2
.stream_id());
1914 spdy_stream2
->Cancel();
1915 EXPECT_FALSE(spdy_stream2
);
1918 // Create two streams that are set to re-close themselves on close,
1919 // and then close the session. Nothing should blow up. Also a
1920 // regression test for http://crbug.com/139518 .
1921 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedSelfClosingStreams
) {
1922 session_deps_
.host_resolver
->set_synchronous_mode(true);
1925 // No actual data will be sent.
1926 MockWrite writes
[] = {
1927 MockWrite(ASYNC
, 0, 1) // EOF
1930 MockRead reads
[] = {
1931 MockRead(ASYNC
, 0, 0) // EOF
1933 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1934 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1936 CreateNetworkSession();
1938 base::WeakPtr
<SpdySession
> session
=
1939 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1941 GURL
url1(kDefaultURL
);
1942 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1943 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1944 session
, url1
, HIGHEST
, BoundNetLog());
1945 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1946 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1948 GURL
url2(kDefaultURL
);
1949 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1950 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1951 session
, url2
, LOWEST
, BoundNetLog());
1952 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
1953 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1955 test::ClosingDelegate
delegate1(spdy_stream1
);
1956 spdy_stream1
->SetDelegate(&delegate1
);
1958 test::ClosingDelegate
delegate2(spdy_stream2
);
1959 spdy_stream2
->SetDelegate(&delegate2
);
1961 scoped_ptr
<SpdyHeaderBlock
> headers(
1962 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1963 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1964 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1966 scoped_ptr
<SpdyHeaderBlock
> headers2(
1967 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1968 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1969 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1971 // Ensure that the streams have not yet been activated and assigned an id.
1972 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1973 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1975 // Ensure we don't crash while closing the session.
1976 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
1978 EXPECT_FALSE(spdy_stream1
);
1979 EXPECT_FALSE(spdy_stream2
);
1981 EXPECT_TRUE(delegate1
.StreamIsClosed());
1982 EXPECT_TRUE(delegate2
.StreamIsClosed());
1984 base::RunLoop().RunUntilIdle();
1985 EXPECT_FALSE(session
);
1988 // Create two streams that are set to close each other on close, and
1989 // then close the session. Nothing should blow up.
1990 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedMutuallyClosingStreams
) {
1991 session_deps_
.host_resolver
->set_synchronous_mode(true);
1993 SequencedSocketData
data(nullptr, 0, nullptr, 0);
1994 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1996 CreateNetworkSession();
1998 base::WeakPtr
<SpdySession
> session
=
1999 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2001 GURL
url1(kDefaultURL
);
2002 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2003 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2004 session
, url1
, HIGHEST
, BoundNetLog());
2005 ASSERT_TRUE(spdy_stream1
);
2006 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2008 GURL
url2(kDefaultURL
);
2009 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2010 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2011 session
, url2
, LOWEST
, BoundNetLog());
2012 ASSERT_TRUE(spdy_stream2
);
2013 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2015 // Make |spdy_stream1| close |spdy_stream2|.
2016 test::ClosingDelegate
delegate1(spdy_stream2
);
2017 spdy_stream1
->SetDelegate(&delegate1
);
2019 // Make |spdy_stream2| close |spdy_stream1|.
2020 test::ClosingDelegate
delegate2(spdy_stream1
);
2021 spdy_stream2
->SetDelegate(&delegate2
);
2023 scoped_ptr
<SpdyHeaderBlock
> headers(
2024 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2025 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2026 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2028 scoped_ptr
<SpdyHeaderBlock
> headers2(
2029 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2030 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2031 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2033 // Ensure that the streams have not yet been activated and assigned an id.
2034 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2035 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2037 // Ensure we don't crash while closing the session.
2038 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2040 EXPECT_FALSE(spdy_stream1
);
2041 EXPECT_FALSE(spdy_stream2
);
2043 EXPECT_TRUE(delegate1
.StreamIsClosed());
2044 EXPECT_TRUE(delegate2
.StreamIsClosed());
2046 base::RunLoop().RunUntilIdle();
2047 EXPECT_FALSE(session
);
2050 // Create two streams that are set to re-close themselves on close,
2051 // activate them, and then close the session. Nothing should blow up.
2052 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedSelfClosingStreams
) {
2053 session_deps_
.host_resolver
->set_synchronous_mode(true);
2055 scoped_ptr
<SpdyFrame
> req1(
2056 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2057 scoped_ptr
<SpdyFrame
> req2(
2058 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
2059 MockWrite writes
[] = {
2060 CreateMockWrite(*req1
, 0),
2061 CreateMockWrite(*req2
, 1),
2064 MockRead reads
[] = {
2065 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
2068 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2069 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2071 CreateNetworkSession();
2073 base::WeakPtr
<SpdySession
> session
=
2074 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2076 GURL
url1(kDefaultURL
);
2077 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2078 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2079 session
, url1
, MEDIUM
, BoundNetLog());
2080 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2081 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2083 GURL
url2(kDefaultURL
);
2084 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2085 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2086 session
, url2
, MEDIUM
, BoundNetLog());
2087 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
2088 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2090 test::ClosingDelegate
delegate1(spdy_stream1
);
2091 spdy_stream1
->SetDelegate(&delegate1
);
2093 test::ClosingDelegate
delegate2(spdy_stream2
);
2094 spdy_stream2
->SetDelegate(&delegate2
);
2096 scoped_ptr
<SpdyHeaderBlock
> headers(
2097 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2098 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2099 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2101 scoped_ptr
<SpdyHeaderBlock
> headers2(
2102 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2103 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2104 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2106 // Ensure that the streams have not yet been activated and assigned an id.
2107 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2108 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2110 base::RunLoop().RunUntilIdle();
2112 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2113 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2115 // Ensure we don't crash while closing the session.
2116 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2118 EXPECT_FALSE(spdy_stream1
);
2119 EXPECT_FALSE(spdy_stream2
);
2121 EXPECT_TRUE(delegate1
.StreamIsClosed());
2122 EXPECT_TRUE(delegate2
.StreamIsClosed());
2124 EXPECT_TRUE(session
);
2125 data
.CompleteRead();
2126 base::RunLoop().RunUntilIdle();
2127 EXPECT_FALSE(session
);
2130 // Create two streams that are set to close each other on close,
2131 // activate them, and then close the session. Nothing should blow up.
2132 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedMutuallyClosingStreams
) {
2133 session_deps_
.host_resolver
->set_synchronous_mode(true);
2135 scoped_ptr
<SpdyFrame
> req1(
2136 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2137 scoped_ptr
<SpdyFrame
> req2(
2138 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
2139 MockWrite writes
[] = {
2140 CreateMockWrite(*req1
, 0),
2141 CreateMockWrite(*req2
, 1),
2144 MockRead reads
[] = {
2145 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
2148 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2149 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2151 CreateNetworkSession();
2153 base::WeakPtr
<SpdySession
> session
=
2154 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2156 GURL
url1(kDefaultURL
);
2157 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2158 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2159 session
, url1
, MEDIUM
, BoundNetLog());
2160 ASSERT_TRUE(spdy_stream1
);
2161 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2163 GURL
url2(kDefaultURL
);
2164 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2165 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2166 session
, url2
, MEDIUM
, BoundNetLog());
2167 ASSERT_TRUE(spdy_stream2
);
2168 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2170 // Make |spdy_stream1| close |spdy_stream2|.
2171 test::ClosingDelegate
delegate1(spdy_stream2
);
2172 spdy_stream1
->SetDelegate(&delegate1
);
2174 // Make |spdy_stream2| close |spdy_stream1|.
2175 test::ClosingDelegate
delegate2(spdy_stream1
);
2176 spdy_stream2
->SetDelegate(&delegate2
);
2178 scoped_ptr
<SpdyHeaderBlock
> headers(
2179 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2180 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2181 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2183 scoped_ptr
<SpdyHeaderBlock
> headers2(
2184 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2185 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2186 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2188 // Ensure that the streams have not yet been activated and assigned an id.
2189 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2190 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2192 base::RunLoop().RunUntilIdle();
2194 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2195 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2197 // Ensure we don't crash while closing the session.
2198 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2200 EXPECT_FALSE(spdy_stream1
);
2201 EXPECT_FALSE(spdy_stream2
);
2203 EXPECT_TRUE(delegate1
.StreamIsClosed());
2204 EXPECT_TRUE(delegate2
.StreamIsClosed());
2206 EXPECT_TRUE(session
);
2207 data
.CompleteRead();
2208 base::RunLoop().RunUntilIdle();
2209 EXPECT_FALSE(session
);
2212 // Delegate that closes a given session when the stream is closed.
2213 class SessionClosingDelegate
: public test::StreamDelegateDoNothing
{
2215 SessionClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
2216 const base::WeakPtr
<SpdySession
>& session_to_close
)
2217 : StreamDelegateDoNothing(stream
),
2218 session_to_close_(session_to_close
) {}
2220 ~SessionClosingDelegate() override
{}
2222 void OnClose(int status
) override
{
2223 session_to_close_
->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR
, "Error");
2227 base::WeakPtr
<SpdySession
> session_to_close_
;
2230 // Close an activated stream that closes its session. Nothing should
2231 // blow up. This is a regression test for https://crbug.com/263691.
2232 TEST_P(SpdySessionTest
, CloseActivatedStreamThatClosesSession
) {
2233 session_deps_
.host_resolver
->set_synchronous_mode(true);
2235 scoped_ptr
<SpdyFrame
> req(
2236 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2237 scoped_ptr
<SpdyFrame
> rst(
2238 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2239 scoped_ptr
<SpdyFrame
> goaway(
2240 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Error"));
2241 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2242 // despite being queued second.
2243 MockWrite writes
[] = {
2244 CreateMockWrite(*req
, 0),
2245 CreateMockWrite(*goaway
, 1),
2246 CreateMockWrite(*rst
, 3),
2249 MockRead reads
[] = {
2250 MockRead(ASYNC
, 0, 2) // EOF
2252 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2253 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2255 CreateNetworkSession();
2257 base::WeakPtr
<SpdySession
> session
=
2258 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2260 GURL
url(kDefaultURL
);
2261 base::WeakPtr
<SpdyStream
> spdy_stream
=
2262 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2263 session
, url
, MEDIUM
, BoundNetLog());
2264 ASSERT_TRUE(spdy_stream
.get() != nullptr);
2265 EXPECT_EQ(0u, spdy_stream
->stream_id());
2267 SessionClosingDelegate
delegate(spdy_stream
, session
);
2268 spdy_stream
->SetDelegate(&delegate
);
2270 scoped_ptr
<SpdyHeaderBlock
> headers(
2271 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
2272 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2273 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
2275 EXPECT_EQ(0u, spdy_stream
->stream_id());
2277 base::RunLoop().RunUntilIdle();
2279 EXPECT_EQ(1u, spdy_stream
->stream_id());
2281 // Ensure we don't crash while closing the stream (which closes the
2283 spdy_stream
->Cancel();
2285 EXPECT_FALSE(spdy_stream
);
2286 EXPECT_TRUE(delegate
.StreamIsClosed());
2288 // Write the RST_STREAM & GOAWAY.
2289 base::RunLoop().RunUntilIdle();
2290 EXPECT_TRUE(data
.AllWriteDataConsumed());
2291 EXPECT_TRUE(data
.AllReadDataConsumed());
2294 TEST_P(SpdySessionTest
, VerifyDomainAuthentication
) {
2295 session_deps_
.host_resolver
->set_synchronous_mode(true);
2297 SequencedSocketData
data(nullptr, 0, nullptr, 0);
2298 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2300 // Load a cert that is valid for:
2304 base::FilePath certs_dir
= GetTestCertsDirectory();
2305 scoped_refptr
<X509Certificate
> test_cert(
2306 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2307 ASSERT_NE(static_cast<X509Certificate
*>(nullptr), test_cert
.get());
2309 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2310 ssl
.cert
= test_cert
;
2311 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2313 CreateNetworkSession();
2315 base::WeakPtr
<SpdySession
> session
=
2316 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2318 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2319 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2320 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.com"));
2321 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2324 TEST_P(SpdySessionTest
, ConnectionPooledWithTlsChannelId
) {
2325 session_deps_
.host_resolver
->set_synchronous_mode(true);
2327 SequencedSocketData
data(nullptr, 0, nullptr, 0);
2328 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2330 // Load a cert that is valid for:
2334 base::FilePath certs_dir
= GetTestCertsDirectory();
2335 scoped_refptr
<X509Certificate
> test_cert(
2336 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2337 ASSERT_NE(static_cast<X509Certificate
*>(nullptr), test_cert
.get());
2339 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2340 ssl
.channel_id_sent
= true;
2341 ssl
.cert
= test_cert
;
2342 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2344 CreateNetworkSession();
2346 base::WeakPtr
<SpdySession
> session
=
2347 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2349 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2350 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2351 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.example.com"));
2352 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2355 TEST_P(SpdySessionTest
, CloseTwoStalledCreateStream
) {
2356 // TODO(rtenneti): Define a helper class/methods and move the common code in
2358 SettingsMap new_settings
;
2359 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
2360 const uint32 max_concurrent_streams
= 1;
2361 new_settings
[kSpdySettingsIds1
] =
2362 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
2364 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
2365 scoped_ptr
<SpdyFrame
> req1(
2366 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
2367 scoped_ptr
<SpdyFrame
> req2(
2368 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST
, true));
2369 scoped_ptr
<SpdyFrame
> req3(
2370 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 5, LOWEST
, true));
2371 MockWrite writes
[] = {
2372 CreateMockWrite(*settings_ack
, 1),
2373 CreateMockWrite(*req1
, 2),
2374 CreateMockWrite(*req2
, 5),
2375 CreateMockWrite(*req3
, 8),
2378 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2380 scoped_ptr
<SpdyFrame
> settings_frame(
2381 spdy_util_
.ConstructSpdySettings(new_settings
));
2383 scoped_ptr
<SpdyFrame
> resp1(
2384 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2385 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2387 scoped_ptr
<SpdyFrame
> resp2(
2388 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
2389 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
2391 scoped_ptr
<SpdyFrame
> resp3(
2392 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 5));
2393 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
2395 MockRead reads
[] = {
2396 CreateMockRead(*settings_frame
, 0),
2397 CreateMockRead(*resp1
, 3),
2398 CreateMockRead(*body1
, 4),
2399 CreateMockRead(*resp2
, 6),
2400 CreateMockRead(*body2
, 7),
2401 CreateMockRead(*resp3
, 9),
2402 CreateMockRead(*body3
, 10),
2403 MockRead(ASYNC
, ERR_IO_PENDING
, 11),
2404 MockRead(ASYNC
, 0, 12) // EOF
2407 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2408 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2410 CreateNetworkSession();
2412 base::WeakPtr
<SpdySession
> session
=
2413 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2415 // Read the settings frame.
2416 base::RunLoop().RunUntilIdle();
2418 GURL
url1(kDefaultURL
);
2419 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2420 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2421 session
, url1
, LOWEST
, BoundNetLog());
2422 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2423 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2424 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2425 spdy_stream1
->SetDelegate(&delegate1
);
2427 TestCompletionCallback callback2
;
2428 GURL
url2(kDefaultURL
);
2429 SpdyStreamRequest request2
;
2430 ASSERT_EQ(ERR_IO_PENDING
,
2431 request2
.StartRequest(
2432 SPDY_REQUEST_RESPONSE_STREAM
,
2433 session
, url2
, LOWEST
, BoundNetLog(), callback2
.callback()));
2435 TestCompletionCallback callback3
;
2436 GURL
url3(kDefaultURL
);
2437 SpdyStreamRequest request3
;
2438 ASSERT_EQ(ERR_IO_PENDING
,
2439 request3
.StartRequest(
2440 SPDY_REQUEST_RESPONSE_STREAM
,
2441 session
, url3
, LOWEST
, BoundNetLog(), callback3
.callback()));
2443 EXPECT_EQ(0u, session
->num_active_streams());
2444 EXPECT_EQ(1u, session
->num_created_streams());
2445 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2447 scoped_ptr
<SpdyHeaderBlock
> headers(
2448 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2449 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2450 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2452 // Run until 1st stream is activated and then closed.
2453 EXPECT_EQ(0u, delegate1
.stream_id());
2454 base::RunLoop().RunUntilIdle();
2455 EXPECT_FALSE(spdy_stream1
);
2456 EXPECT_EQ(1u, delegate1
.stream_id());
2458 EXPECT_EQ(0u, session
->num_active_streams());
2459 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2461 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2462 // create the 2nd stream.
2463 base::RunLoop().RunUntilIdle();
2465 EXPECT_EQ(0u, session
->num_active_streams());
2466 EXPECT_EQ(1u, session
->num_created_streams());
2467 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2469 base::WeakPtr
<SpdyStream
> stream2
= request2
.ReleaseStream();
2470 test::StreamDelegateDoNothing
delegate2(stream2
);
2471 stream2
->SetDelegate(&delegate2
);
2472 scoped_ptr
<SpdyHeaderBlock
> headers2(
2473 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2474 stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2475 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
2477 // Run until 2nd stream is activated and then closed.
2478 EXPECT_EQ(0u, delegate2
.stream_id());
2479 base::RunLoop().RunUntilIdle();
2480 EXPECT_FALSE(stream2
);
2481 EXPECT_EQ(3u, delegate2
.stream_id());
2483 EXPECT_EQ(0u, session
->num_active_streams());
2484 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2486 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2487 // create the 3rd stream.
2488 base::RunLoop().RunUntilIdle();
2490 EXPECT_EQ(0u, session
->num_active_streams());
2491 EXPECT_EQ(1u, session
->num_created_streams());
2492 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2494 base::WeakPtr
<SpdyStream
> stream3
= request3
.ReleaseStream();
2495 test::StreamDelegateDoNothing
delegate3(stream3
);
2496 stream3
->SetDelegate(&delegate3
);
2497 scoped_ptr
<SpdyHeaderBlock
> headers3(
2498 spdy_util_
.ConstructGetHeaderBlock(url3
.spec()));
2499 stream3
->SendRequestHeaders(headers3
.Pass(), NO_MORE_DATA_TO_SEND
);
2500 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
2502 // Run until 2nd stream is activated and then closed.
2503 EXPECT_EQ(0u, delegate3
.stream_id());
2504 base::RunLoop().RunUntilIdle();
2505 EXPECT_FALSE(stream3
);
2506 EXPECT_EQ(5u, delegate3
.stream_id());
2508 EXPECT_EQ(0u, session
->num_active_streams());
2509 EXPECT_EQ(0u, session
->num_created_streams());
2510 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2512 data
.CompleteRead();
2513 base::RunLoop().RunUntilIdle();
2516 TEST_P(SpdySessionTest
, CancelTwoStalledCreateStream
) {
2517 session_deps_
.host_resolver
->set_synchronous_mode(true);
2519 MockRead reads
[] = {
2520 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2523 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2524 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2526 CreateNetworkSession();
2528 base::WeakPtr
<SpdySession
> session
=
2529 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2531 // Leave room for only one more stream to be created.
2532 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
2533 base::WeakPtr
<SpdyStream
> spdy_stream
=
2534 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2535 session
, test_url_
, MEDIUM
, BoundNetLog());
2536 ASSERT_TRUE(spdy_stream
!= nullptr);
2539 GURL
url1(kDefaultURL
);
2540 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2541 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2542 session
, url1
, LOWEST
, BoundNetLog());
2543 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2544 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2546 TestCompletionCallback callback2
;
2547 GURL
url2(kDefaultURL
);
2548 SpdyStreamRequest request2
;
2549 ASSERT_EQ(ERR_IO_PENDING
,
2550 request2
.StartRequest(
2551 SPDY_BIDIRECTIONAL_STREAM
, session
, url2
, LOWEST
, BoundNetLog(),
2552 callback2
.callback()));
2554 TestCompletionCallback callback3
;
2555 GURL
url3(kDefaultURL
);
2556 SpdyStreamRequest request3
;
2557 ASSERT_EQ(ERR_IO_PENDING
,
2558 request3
.StartRequest(
2559 SPDY_BIDIRECTIONAL_STREAM
, session
, url3
, LOWEST
, BoundNetLog(),
2560 callback3
.callback()));
2562 EXPECT_EQ(0u, session
->num_active_streams());
2563 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2564 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2566 // Cancel the first stream; this will allow the second stream to be created.
2567 EXPECT_TRUE(spdy_stream1
);
2568 spdy_stream1
->Cancel();
2569 EXPECT_FALSE(spdy_stream1
);
2571 EXPECT_EQ(OK
, callback2
.WaitForResult());
2572 EXPECT_EQ(0u, session
->num_active_streams());
2573 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2574 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2576 // Cancel the second stream; this will allow the third stream to be created.
2577 base::WeakPtr
<SpdyStream
> spdy_stream2
= request2
.ReleaseStream();
2578 spdy_stream2
->Cancel();
2579 EXPECT_FALSE(spdy_stream2
);
2581 EXPECT_EQ(OK
, callback3
.WaitForResult());
2582 EXPECT_EQ(0u, session
->num_active_streams());
2583 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2584 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2586 // Cancel the third stream.
2587 base::WeakPtr
<SpdyStream
> spdy_stream3
= request3
.ReleaseStream();
2588 spdy_stream3
->Cancel();
2589 EXPECT_FALSE(spdy_stream3
);
2590 EXPECT_EQ(0u, session
->num_active_streams());
2591 EXPECT_EQ(kInitialMaxConcurrentStreams
- 1, session
->num_created_streams());
2592 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2595 // Test that SpdySession::DoReadLoop reads data from the socket
2596 // without yielding. This test makes 32k - 1 bytes of data available
2597 // on the socket for reading. It then verifies that it has read all
2598 // the available data without yielding.
2599 TEST_P(SpdySessionTest
, ReadDataWithoutYielding
) {
2600 session_deps_
.host_resolver
->set_synchronous_mode(true);
2602 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2604 scoped_ptr
<SpdyFrame
> req1(
2605 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2606 MockWrite writes
[] = {
2607 CreateMockWrite(*req1
, 0),
2610 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2611 // (-spdy_data_frame_size).
2612 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2613 const int kPayloadSize
=
2614 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2615 TestDataStream test_stream
;
2616 scoped_refptr
<IOBuffer
> payload(new IOBuffer(kPayloadSize
));
2617 char* payload_data
= payload
->data();
2618 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2620 scoped_ptr
<SpdyFrame
> partial_data_frame(
2621 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2622 scoped_ptr
<SpdyFrame
> finish_data_frame(
2623 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
- 1, DATA_FLAG_FIN
));
2625 scoped_ptr
<SpdyFrame
> resp1(
2626 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2628 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2630 MockRead reads
[] = {
2631 CreateMockRead(*resp1
, 1),
2632 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2633 CreateMockRead(*partial_data_frame
, 3),
2634 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2635 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2636 CreateMockRead(*finish_data_frame
, 6, SYNCHRONOUS
),
2637 MockRead(ASYNC
, 0, 7) // EOF
2640 // Create SpdySession and SpdyStream and send the request.
2641 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2642 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2644 CreateNetworkSession();
2646 base::WeakPtr
<SpdySession
> session
=
2647 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2649 GURL
url1(kDefaultURL
);
2650 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2651 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2652 session
, url1
, MEDIUM
, BoundNetLog());
2653 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2654 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2655 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2656 spdy_stream1
->SetDelegate(&delegate1
);
2658 scoped_ptr
<SpdyHeaderBlock
> headers1(
2659 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2660 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2661 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2663 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2665 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2667 // Run until 1st read.
2668 EXPECT_EQ(0u, delegate1
.stream_id());
2669 base::RunLoop().RunUntilIdle();
2670 EXPECT_EQ(1u, delegate1
.stream_id());
2671 EXPECT_EQ(0u, observer
.executed_count());
2673 // Read all the data and verify SpdySession::DoReadLoop has not
2675 data
.CompleteRead();
2676 base::RunLoop().RunUntilIdle();
2677 EXPECT_FALSE(spdy_stream1
);
2679 // Verify task observer's executed_count is zero, which indicates DoRead read
2680 // all the available data.
2681 EXPECT_EQ(0u, observer
.executed_count());
2682 EXPECT_TRUE(data
.AllWriteDataConsumed());
2683 EXPECT_TRUE(data
.AllReadDataConsumed());
2686 // Test that SpdySession::DoReadLoop yields while reading the
2687 // data. This test makes 32k + 1 bytes of data available on the socket
2688 // for reading. It then verifies that DoRead has yielded even though
2689 // there is data available for it to read (i.e, socket()->Read didn't
2690 // return ERR_IO_PENDING during socket reads).
2691 TEST_P(SpdySessionTest
, TestYieldingDuringReadData
) {
2692 session_deps_
.host_resolver
->set_synchronous_mode(true);
2694 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2696 scoped_ptr
<SpdyFrame
> req1(
2697 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2698 MockWrite writes
[] = {
2699 CreateMockWrite(*req1
, 0),
2702 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2703 // (-spdy_data_frame_size).
2704 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2705 const int kPayloadSize
=
2706 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2707 TestDataStream test_stream
;
2708 scoped_refptr
<IOBuffer
> payload(new IOBuffer(kPayloadSize
));
2709 char* payload_data
= payload
->data();
2710 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2712 scoped_ptr
<SpdyFrame
> partial_data_frame(
2713 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2714 scoped_ptr
<SpdyFrame
> finish_data_frame(
2715 framer
.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN
));
2717 scoped_ptr
<SpdyFrame
> resp1(
2718 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2720 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2721 MockRead reads
[] = {
2722 CreateMockRead(*resp1
, 1),
2723 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2724 CreateMockRead(*partial_data_frame
, 3),
2725 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2726 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2727 CreateMockRead(*partial_data_frame
, 6, SYNCHRONOUS
),
2728 CreateMockRead(*finish_data_frame
, 7, SYNCHRONOUS
),
2729 MockRead(ASYNC
, 0, 8) // EOF
2732 // Create SpdySession and SpdyStream and send the request.
2733 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2734 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2736 CreateNetworkSession();
2738 base::WeakPtr
<SpdySession
> session
=
2739 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2741 GURL
url1(kDefaultURL
);
2742 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2743 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2744 session
, url1
, MEDIUM
, BoundNetLog());
2745 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2746 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2747 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2748 spdy_stream1
->SetDelegate(&delegate1
);
2750 scoped_ptr
<SpdyHeaderBlock
> headers1(
2751 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2752 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2753 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2755 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2757 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2759 // Run until 1st read.
2760 EXPECT_EQ(0u, delegate1
.stream_id());
2761 base::RunLoop().RunUntilIdle();
2762 EXPECT_EQ(1u, delegate1
.stream_id());
2763 EXPECT_EQ(0u, observer
.executed_count());
2765 // Read all the data and verify SpdySession::DoReadLoop has posted a
2767 data
.CompleteRead();
2768 base::RunLoop().RunUntilIdle();
2769 EXPECT_FALSE(spdy_stream1
);
2771 // Verify task observer's executed_count is 1, which indicates DoRead has
2772 // posted only one task and thus yielded though there is data available for it
2774 EXPECT_EQ(1u, observer
.executed_count());
2775 EXPECT_TRUE(data
.AllWriteDataConsumed());
2776 EXPECT_TRUE(data
.AllReadDataConsumed());
2779 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2780 // + async, by doing the following MockReads.
2782 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2783 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2785 // The above reads 26K synchronously. Since that is less that 32K, we
2786 // will attempt to read again. However, that DoRead() will return
2787 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2788 // yield. When we come back, DoRead() will read the results from the
2789 // async read, and rest of the data synchronously.
2790 TEST_P(SpdySessionTest
, TestYieldingDuringAsyncReadData
) {
2791 session_deps_
.host_resolver
->set_synchronous_mode(true);
2793 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2795 scoped_ptr
<SpdyFrame
> req1(
2796 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2797 MockWrite writes
[] = {
2798 CreateMockWrite(*req1
, 0),
2801 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2802 // (-spdy_data_frame_size).
2803 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2804 TestDataStream test_stream
;
2805 const int kEightKPayloadSize
=
2806 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2807 scoped_refptr
<IOBuffer
> eightk_payload(new IOBuffer(kEightKPayloadSize
));
2808 char* eightk_payload_data
= eightk_payload
->data();
2809 test_stream
.GetBytes(eightk_payload_data
, kEightKPayloadSize
);
2811 // Build buffer of 2k size.
2812 TestDataStream test_stream2
;
2813 const int kTwoKPayloadSize
= kEightKPayloadSize
- 6 * 1024;
2814 scoped_refptr
<IOBuffer
> twok_payload(new IOBuffer(kTwoKPayloadSize
));
2815 char* twok_payload_data
= twok_payload
->data();
2816 test_stream2
.GetBytes(twok_payload_data
, kTwoKPayloadSize
);
2818 scoped_ptr
<SpdyFrame
> eightk_data_frame(framer
.CreateDataFrame(
2819 1, eightk_payload_data
, kEightKPayloadSize
, DATA_FLAG_NONE
));
2820 scoped_ptr
<SpdyFrame
> twok_data_frame(framer
.CreateDataFrame(
2821 1, twok_payload_data
, kTwoKPayloadSize
, DATA_FLAG_NONE
));
2822 scoped_ptr
<SpdyFrame
> finish_data_frame(framer
.CreateDataFrame(
2823 1, "h", 1, DATA_FLAG_FIN
));
2825 scoped_ptr
<SpdyFrame
> resp1(
2826 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2828 MockRead reads
[] = {
2829 CreateMockRead(*resp1
, 1),
2830 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2831 CreateMockRead(*eightk_data_frame
, 3),
2832 CreateMockRead(*eightk_data_frame
, 4, SYNCHRONOUS
),
2833 CreateMockRead(*eightk_data_frame
, 5, SYNCHRONOUS
),
2834 CreateMockRead(*twok_data_frame
, 6, SYNCHRONOUS
),
2835 CreateMockRead(*eightk_data_frame
, 7, ASYNC
),
2836 CreateMockRead(*eightk_data_frame
, 8, SYNCHRONOUS
),
2837 CreateMockRead(*eightk_data_frame
, 9, SYNCHRONOUS
),
2838 CreateMockRead(*eightk_data_frame
, 10, SYNCHRONOUS
),
2839 CreateMockRead(*twok_data_frame
, 11, SYNCHRONOUS
),
2840 CreateMockRead(*finish_data_frame
, 12, SYNCHRONOUS
),
2841 MockRead(ASYNC
, 0, 13) // EOF
2844 // Create SpdySession and SpdyStream and send the request.
2845 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2846 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2848 CreateNetworkSession();
2850 base::WeakPtr
<SpdySession
> session
=
2851 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2853 GURL
url1(kDefaultURL
);
2854 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2855 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2856 session
, url1
, MEDIUM
, BoundNetLog());
2857 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2858 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2859 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2860 spdy_stream1
->SetDelegate(&delegate1
);
2862 scoped_ptr
<SpdyHeaderBlock
> headers1(
2863 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2864 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2865 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2867 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2868 // posting of tasks.
2869 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2871 // Run until 1st read.
2872 EXPECT_EQ(0u, delegate1
.stream_id());
2873 base::RunLoop().RunUntilIdle();
2874 EXPECT_EQ(1u, delegate1
.stream_id());
2875 EXPECT_EQ(0u, observer
.executed_count());
2877 // Read all the data and verify SpdySession::DoReadLoop has posted a
2879 data
.CompleteRead();
2880 base::RunLoop().RunUntilIdle();
2881 EXPECT_FALSE(spdy_stream1
);
2883 // Verify task observer's executed_count is 1, which indicates DoRead has
2884 // posted only one task and thus yielded though there is data available for
2886 EXPECT_EQ(1u, observer
.executed_count());
2887 EXPECT_TRUE(data
.AllWriteDataConsumed());
2888 EXPECT_TRUE(data
.AllReadDataConsumed());
2891 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2892 // nothing blows up.
2893 TEST_P(SpdySessionTest
, GoAwayWhileInDoReadLoop
) {
2894 session_deps_
.host_resolver
->set_synchronous_mode(true);
2896 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2898 scoped_ptr
<SpdyFrame
> req1(
2899 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2900 MockWrite writes
[] = {
2901 CreateMockWrite(*req1
, 0),
2904 scoped_ptr
<SpdyFrame
> resp1(
2905 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2906 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2907 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
2909 MockRead reads
[] = {
2910 CreateMockRead(*resp1
, 1),
2911 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2912 CreateMockRead(*body1
, 3),
2913 CreateMockRead(*goaway
, 4),
2916 // Create SpdySession and SpdyStream and send the request.
2917 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2918 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2920 CreateNetworkSession();
2922 base::WeakPtr
<SpdySession
> session
=
2923 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2925 GURL
url1(kDefaultURL
);
2926 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2927 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2928 session
, url1
, MEDIUM
, BoundNetLog());
2929 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2930 spdy_stream1
->SetDelegate(&delegate1
);
2931 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2932 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2934 scoped_ptr
<SpdyHeaderBlock
> headers1(
2935 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2936 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2937 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2939 // Run until 1st read.
2940 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2941 base::RunLoop().RunUntilIdle();
2942 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2944 // Run until GoAway.
2945 data
.CompleteRead();
2946 base::RunLoop().RunUntilIdle();
2947 EXPECT_FALSE(spdy_stream1
);
2948 EXPECT_TRUE(data
.AllWriteDataConsumed());
2949 EXPECT_TRUE(data
.AllReadDataConsumed());
2950 EXPECT_FALSE(session
);
2953 // Within this framework, a SpdySession should be initialized with
2954 // flow control disabled for protocol version 2, with flow control
2955 // enabled only for streams for protocol version 3, and with flow
2956 // control enabled for streams and sessions for higher versions.
2957 TEST_P(SpdySessionTest
, ProtocolNegotiation
) {
2958 session_deps_
.host_resolver
->set_synchronous_mode(true);
2960 MockRead reads
[] = {
2961 MockRead(SYNCHRONOUS
, 0, 0) // EOF
2963 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2964 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2966 CreateNetworkSession();
2967 base::WeakPtr
<SpdySession
> session
=
2968 CreateFakeSpdySession(spdy_session_pool_
, key_
);
2970 EXPECT_EQ(spdy_util_
.spdy_version(),
2971 session
->buffered_spdy_framer_
->protocol_version());
2972 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
2973 session
->flow_control_state());
2974 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
2975 session
->session_send_window_size_
);
2976 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
2977 session
->session_recv_window_size_
);
2978 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
2981 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2982 // pointers to the idle session are currently held.
2983 TEST_P(SpdySessionTest
, CloseOneIdleConnection
) {
2984 ClientSocketPoolManager::set_max_sockets_per_group(
2985 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2986 ClientSocketPoolManager::set_max_sockets_per_pool(
2987 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2989 MockRead reads
[] = {
2990 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2992 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2993 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2994 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2996 CreateNetworkSession();
2998 TransportClientSocketPool
* pool
=
2999 http_session_
->GetTransportSocketPool(
3000 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3002 // Create an idle SPDY session.
3003 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3004 PRIVACY_MODE_DISABLED
);
3005 base::WeakPtr
<SpdySession
> session1
=
3006 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3007 EXPECT_FALSE(pool
->IsStalled());
3009 // Trying to create a new connection should cause the pool to be stalled, and
3010 // post a task asynchronously to try and close the session.
3011 TestCompletionCallback callback2
;
3012 HostPortPair
host_port2("2.com", 80);
3013 scoped_refptr
<TransportSocketParams
> params2(
3014 new TransportSocketParams(
3015 host_port2
, false, false, OnHostResolutionCallback(),
3016 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3017 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3018 EXPECT_EQ(ERR_IO_PENDING
,
3019 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3020 callback2
.callback(), pool
, BoundNetLog()));
3021 EXPECT_TRUE(pool
->IsStalled());
3023 // The socket pool should close the connection asynchronously and establish a
3025 EXPECT_EQ(OK
, callback2
.WaitForResult());
3026 EXPECT_FALSE(pool
->IsStalled());
3027 EXPECT_FALSE(session1
);
3030 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3031 // pointers to the idle session are currently held, in the case the SPDY session
3033 TEST_P(SpdySessionTest
, CloseOneIdleConnectionWithAlias
) {
3034 ClientSocketPoolManager::set_max_sockets_per_group(
3035 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3036 ClientSocketPoolManager::set_max_sockets_per_pool(
3037 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3039 MockRead reads
[] = {
3040 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3042 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
3043 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3044 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3046 session_deps_
.host_resolver
->set_synchronous_mode(true);
3047 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3048 "1.com", "192.168.0.2", std::string());
3049 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3050 "2.com", "192.168.0.2", std::string());
3051 // Not strictly needed.
3052 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3053 "3.com", "192.168.0.3", std::string());
3055 CreateNetworkSession();
3057 TransportClientSocketPool
* pool
=
3058 http_session_
->GetTransportSocketPool(
3059 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3061 // Create an idle SPDY session.
3062 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3063 PRIVACY_MODE_DISABLED
);
3064 base::WeakPtr
<SpdySession
> session1
=
3065 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3066 EXPECT_FALSE(pool
->IsStalled());
3068 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3069 SpdySessionKey
key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3070 PRIVACY_MODE_DISABLED
);
3071 HostResolver::RequestInfo
info(key2
.host_port_pair());
3072 AddressList addresses
;
3073 // Pre-populate the DNS cache, since a synchronous resolution is required in
3074 // order to create the alias.
3075 session_deps_
.host_resolver
->Resolve(info
, DEFAULT_PRIORITY
, &addresses
,
3076 CompletionCallback(), nullptr,
3078 // Get a session for |key2|, which should return the session created earlier.
3079 base::WeakPtr
<SpdySession
> session2
=
3080 spdy_session_pool_
->FindAvailableSession(key2
, BoundNetLog());
3081 ASSERT_EQ(session1
.get(), session2
.get());
3082 EXPECT_FALSE(pool
->IsStalled());
3084 // Trying to create a new connection should cause the pool to be stalled, and
3085 // post a task asynchronously to try and close the session.
3086 TestCompletionCallback callback3
;
3087 HostPortPair
host_port3("3.com", 80);
3088 scoped_refptr
<TransportSocketParams
> params3(
3089 new TransportSocketParams(
3090 host_port3
, false, false, OnHostResolutionCallback(),
3091 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3092 scoped_ptr
<ClientSocketHandle
> connection3(new ClientSocketHandle
);
3093 EXPECT_EQ(ERR_IO_PENDING
,
3094 connection3
->Init(host_port3
.ToString(), params3
, DEFAULT_PRIORITY
,
3095 callback3
.callback(), pool
, BoundNetLog()));
3096 EXPECT_TRUE(pool
->IsStalled());
3098 // The socket pool should close the connection asynchronously and establish a
3100 EXPECT_EQ(OK
, callback3
.WaitForResult());
3101 EXPECT_FALSE(pool
->IsStalled());
3102 EXPECT_FALSE(session1
);
3103 EXPECT_FALSE(session2
);
3106 // Tests that when a SPDY session becomes idle, it closes itself if there is
3107 // a lower layer pool stalled on the per-pool socket limit.
3108 TEST_P(SpdySessionTest
, CloseSessionOnIdleWhenPoolStalled
) {
3109 ClientSocketPoolManager::set_max_sockets_per_group(
3110 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3111 ClientSocketPoolManager::set_max_sockets_per_pool(
3112 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3114 MockRead reads
[] = {
3115 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3117 scoped_ptr
<SpdyFrame
> req1(
3118 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3119 scoped_ptr
<SpdyFrame
> cancel1(
3120 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3121 MockWrite writes
[] = {
3122 CreateMockWrite(*req1
, 1),
3123 CreateMockWrite(*cancel1
, 1),
3125 StaticSocketDataProvider
data(reads
, arraysize(reads
),
3126 writes
, arraysize(writes
));
3127 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3129 MockRead http_reads
[] = {
3130 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3132 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
), nullptr,
3134 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
3137 CreateNetworkSession();
3139 TransportClientSocketPool
* pool
=
3140 http_session_
->GetTransportSocketPool(
3141 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3143 // Create a SPDY session.
3144 GURL
url1(kDefaultURL
);
3145 SpdySessionKey
key1(HostPortPair(url1
.host(), 80),
3146 ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3147 base::WeakPtr
<SpdySession
> session1
=
3148 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3149 EXPECT_FALSE(pool
->IsStalled());
3151 // Create a stream using the session, and send a request.
3153 TestCompletionCallback callback1
;
3154 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3155 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3156 session1
, url1
, DEFAULT_PRIORITY
,
3158 ASSERT_TRUE(spdy_stream1
.get());
3159 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3160 spdy_stream1
->SetDelegate(&delegate1
);
3162 scoped_ptr
<SpdyHeaderBlock
> headers1(
3163 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
3164 EXPECT_EQ(ERR_IO_PENDING
,
3165 spdy_stream1
->SendRequestHeaders(
3166 headers1
.Pass(), NO_MORE_DATA_TO_SEND
));
3167 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3169 base::RunLoop().RunUntilIdle();
3171 // Trying to create a new connection should cause the pool to be stalled, and
3172 // post a task asynchronously to try and close the session.
3173 TestCompletionCallback callback2
;
3174 HostPortPair
host_port2("2.com", 80);
3175 scoped_refptr
<TransportSocketParams
> params2(
3176 new TransportSocketParams(
3177 host_port2
, false, false, OnHostResolutionCallback(),
3178 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3179 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3180 EXPECT_EQ(ERR_IO_PENDING
,
3181 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3182 callback2
.callback(), pool
, BoundNetLog()));
3183 EXPECT_TRUE(pool
->IsStalled());
3185 // Running the message loop should cause the socket pool to ask the SPDY
3186 // session to close an idle socket, but since the socket is in use, nothing
3188 base::RunLoop().RunUntilIdle();
3189 EXPECT_TRUE(pool
->IsStalled());
3190 EXPECT_FALSE(callback2
.have_result());
3192 // Cancelling the request should result in the session's socket being
3193 // closed, since the pool is stalled.
3194 ASSERT_TRUE(spdy_stream1
.get());
3195 spdy_stream1
->Cancel();
3196 base::RunLoop().RunUntilIdle();
3197 ASSERT_FALSE(pool
->IsStalled());
3198 EXPECT_EQ(OK
, callback2
.WaitForResult());
3201 // Verify that SpdySessionKey and therefore SpdySession is different when
3202 // privacy mode is enabled or disabled.
3203 TEST_P(SpdySessionTest
, SpdySessionKeyPrivacyMode
) {
3204 CreateNetworkSession();
3206 HostPortPair
host_port_pair("www.example.org", 443);
3207 SpdySessionKey
key_privacy_enabled(host_port_pair
, ProxyServer::Direct(),
3208 PRIVACY_MODE_ENABLED
);
3209 SpdySessionKey
key_privacy_disabled(host_port_pair
, ProxyServer::Direct(),
3210 PRIVACY_MODE_DISABLED
);
3212 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3213 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3215 // Add SpdySession with PrivacyMode Enabled to the pool.
3216 base::WeakPtr
<SpdySession
> session_privacy_enabled
=
3217 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_enabled
);
3219 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3220 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3222 // Add SpdySession with PrivacyMode Disabled to the pool.
3223 base::WeakPtr
<SpdySession
> session_privacy_disabled
=
3224 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_disabled
);
3226 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3227 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3229 session_privacy_enabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3230 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3231 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3233 session_privacy_disabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3234 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3235 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3238 // Delegate that creates another stream when its stream is closed.
3239 class StreamCreatingDelegate
: public test::StreamDelegateDoNothing
{
3241 StreamCreatingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3242 const base::WeakPtr
<SpdySession
>& session
)
3243 : StreamDelegateDoNothing(stream
),
3244 session_(session
) {}
3246 ~StreamCreatingDelegate() override
{}
3248 void OnClose(int status
) override
{
3249 GURL
url(kDefaultURL
);
3251 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3252 session_
, url
, MEDIUM
, BoundNetLog()));
3256 const base::WeakPtr
<SpdySession
> session_
;
3259 // Create another stream in response to a stream being reset. Nothing
3260 // should blow up. This is a regression test for
3261 // http://crbug.com/263690 .
3262 TEST_P(SpdySessionTest
, CreateStreamOnStreamReset
) {
3263 session_deps_
.host_resolver
->set_synchronous_mode(true);
3265 scoped_ptr
<SpdyFrame
> req(
3266 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
3267 MockWrite writes
[] = {
3268 CreateMockWrite(*req
, 0),
3271 scoped_ptr
<SpdyFrame
> rst(
3272 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
3273 MockRead reads
[] = {
3274 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3275 CreateMockRead(*rst
, 2),
3276 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3277 MockRead(ASYNC
, 0, 4) // EOF
3279 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3280 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3282 CreateNetworkSession();
3284 base::WeakPtr
<SpdySession
> session
=
3285 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3287 GURL
url(kDefaultURL
);
3288 base::WeakPtr
<SpdyStream
> spdy_stream
=
3289 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3290 session
, url
, MEDIUM
, BoundNetLog());
3291 ASSERT_TRUE(spdy_stream
.get() != nullptr);
3292 EXPECT_EQ(0u, spdy_stream
->stream_id());
3294 StreamCreatingDelegate
delegate(spdy_stream
, session
);
3295 spdy_stream
->SetDelegate(&delegate
);
3297 scoped_ptr
<SpdyHeaderBlock
> headers(
3298 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
3299 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
3300 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
3302 EXPECT_EQ(0u, spdy_stream
->stream_id());
3304 base::RunLoop().RunUntilIdle();
3306 EXPECT_EQ(1u, spdy_stream
->stream_id());
3308 // Cause the stream to be reset, which should cause another stream
3310 data
.CompleteRead();
3311 base::RunLoop().RunUntilIdle();
3313 EXPECT_FALSE(spdy_stream
);
3314 EXPECT_TRUE(delegate
.StreamIsClosed());
3315 EXPECT_EQ(0u, session
->num_active_streams());
3316 EXPECT_EQ(1u, session
->num_created_streams());
3318 data
.CompleteRead();
3319 base::RunLoop().RunUntilIdle();
3320 EXPECT_FALSE(session
);
3323 // The tests below are only for SPDY/3 and above.
3325 TEST_P(SpdySessionTest
, UpdateStreamsSendWindowSize
) {
3326 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3328 SettingsMap new_settings
;
3329 int32 window_size
= 1;
3330 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
3331 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, window_size
);
3333 // Set up the socket so we read a SETTINGS frame that sets
3334 // INITIAL_WINDOW_SIZE.
3335 scoped_ptr
<SpdyFrame
> settings_frame(
3336 spdy_util_
.ConstructSpdySettings(new_settings
));
3337 MockRead reads
[] = {
3338 CreateMockRead(*settings_frame
, 0),
3339 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3340 MockRead(ASYNC
, 0, 2) // EOF
3343 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
3344 MockWrite writes
[] = {
3345 CreateMockWrite(*settings_ack
, 3),
3348 session_deps_
.host_resolver
->set_synchronous_mode(true);
3350 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3351 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3353 CreateNetworkSession();
3355 base::WeakPtr
<SpdySession
> session
=
3356 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3357 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3358 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3359 session
, test_url_
, MEDIUM
, BoundNetLog());
3360 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
3361 TestCompletionCallback callback1
;
3362 EXPECT_NE(spdy_stream1
->send_window_size(), window_size
);
3364 // Process the SETTINGS frame.
3365 base::RunLoop().RunUntilIdle();
3366 EXPECT_EQ(session
->stream_initial_send_window_size(), window_size
);
3367 EXPECT_EQ(spdy_stream1
->send_window_size(), window_size
);
3369 // Release the first one, this will allow the second to be created.
3370 spdy_stream1
->Cancel();
3371 EXPECT_FALSE(spdy_stream1
);
3373 base::WeakPtr
<SpdyStream
> spdy_stream2
=
3374 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3375 session
, test_url_
, MEDIUM
, BoundNetLog());
3376 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
3377 EXPECT_EQ(spdy_stream2
->send_window_size(), window_size
);
3378 spdy_stream2
->Cancel();
3379 EXPECT_FALSE(spdy_stream2
);
3381 EXPECT_TRUE(session
);
3382 data
.CompleteRead();
3383 base::RunLoop().RunUntilIdle();
3384 EXPECT_FALSE(session
);
3387 // The tests below are only for SPDY/3.1 and above.
3389 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3390 // adjust the session receive window size. In addition,
3391 // SpdySession::IncreaseRecvWindowSize should trigger
3392 // sending a WINDOW_UPDATE frame for a large enough delta.
3393 TEST_P(SpdySessionTest
, AdjustRecvWindowSize
) {
3394 if (GetParam() < kProtoSPDY31
)
3397 session_deps_
.host_resolver
->set_synchronous_mode(true);
3399 const int32 initial_window_size
=
3400 SpdySession::GetDefaultInitialWindowSize(GetParam());
3401 const int32 delta_window_size
= 100;
3403 MockRead reads
[] = {
3404 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
3406 scoped_ptr
<SpdyFrame
> window_update(spdy_util_
.ConstructSpdyWindowUpdate(
3407 kSessionFlowControlStreamId
, initial_window_size
+ delta_window_size
));
3408 MockWrite writes
[] = {
3409 CreateMockWrite(*window_update
, 0),
3411 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3412 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3414 CreateNetworkSession();
3415 base::WeakPtr
<SpdySession
> session
=
3416 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3417 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3418 session
->flow_control_state());
3420 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3421 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3423 session
->IncreaseRecvWindowSize(delta_window_size
);
3424 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3425 session
->session_recv_window_size_
);
3426 EXPECT_EQ(delta_window_size
, session
->session_unacked_recv_window_bytes_
);
3428 // Should trigger sending a WINDOW_UPDATE frame.
3429 session
->IncreaseRecvWindowSize(initial_window_size
);
3430 EXPECT_EQ(initial_window_size
+ delta_window_size
+ initial_window_size
,
3431 session
->session_recv_window_size_
);
3432 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3434 base::RunLoop().RunUntilIdle();
3436 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3437 session
->in_io_loop_
= true;
3438 session
->DecreaseRecvWindowSize(initial_window_size
+ delta_window_size
+
3439 initial_window_size
);
3440 session
->in_io_loop_
= false;
3441 EXPECT_EQ(0, session
->session_recv_window_size_
);
3442 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3444 EXPECT_TRUE(session
);
3445 data
.CompleteRead();
3446 base::RunLoop().RunUntilIdle();
3447 EXPECT_FALSE(session
);
3450 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3451 // adjust the session send window size when the "enable_spdy_31" flag
3453 TEST_P(SpdySessionTest
, AdjustSendWindowSize
) {
3454 if (GetParam() < kProtoSPDY31
)
3457 session_deps_
.host_resolver
->set_synchronous_mode(true);
3459 MockRead reads
[] = {
3460 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3462 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
3463 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3465 CreateNetworkSession();
3466 base::WeakPtr
<SpdySession
> session
=
3467 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3468 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3469 session
->flow_control_state());
3471 const int32 initial_window_size
=
3472 SpdySession::GetDefaultInitialWindowSize(GetParam());
3473 const int32 delta_window_size
= 100;
3475 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3477 session
->IncreaseSendWindowSize(delta_window_size
);
3478 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3479 session
->session_send_window_size_
);
3481 session
->DecreaseSendWindowSize(delta_window_size
);
3482 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3485 // Incoming data for an inactive stream should not cause the session
3486 // receive window size to decrease, but it should cause the unacked
3487 // bytes to increase.
3488 TEST_P(SpdySessionTest
, SessionFlowControlInactiveStream
) {
3489 if (GetParam() < kProtoSPDY31
)
3492 session_deps_
.host_resolver
->set_synchronous_mode(true);
3494 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(1, false));
3495 MockRead reads
[] = {
3496 CreateMockRead(*resp
, 0),
3497 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3498 MockRead(ASYNC
, 0, 2) // EOF
3500 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
3501 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3503 CreateNetworkSession();
3504 base::WeakPtr
<SpdySession
> session
=
3505 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3506 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3507 session
->flow_control_state());
3509 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3510 session
->session_recv_window_size_
);
3511 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3513 base::RunLoop().RunUntilIdle();
3515 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3516 session
->session_recv_window_size_
);
3517 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
3519 EXPECT_TRUE(session
);
3520 data
.CompleteRead();
3521 base::RunLoop().RunUntilIdle();
3522 EXPECT_FALSE(session
);
3525 // The frame header is not included in flow control, but frame payload
3526 // (including optional pad length and padding) is.
3527 TEST_P(SpdySessionTest
, SessionFlowControlPadding
) {
3528 // Padding only exists in HTTP/2.
3529 if (GetParam() < kProtoHTTP2MinimumVersion
)
3532 session_deps_
.host_resolver
->set_synchronous_mode(true);
3534 const int padding_length
= 42;
3535 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(
3536 1, kUploadData
, kUploadDataSize
, false, padding_length
));
3537 MockRead reads
[] = {
3538 CreateMockRead(*resp
, 0),
3539 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3540 MockRead(ASYNC
, 0, 2) // EOF
3542 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
3543 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3545 CreateNetworkSession();
3546 base::WeakPtr
<SpdySession
> session
=
3547 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3548 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3549 session
->flow_control_state());
3551 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3552 session
->session_recv_window_size_
);
3553 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3555 base::RunLoop().RunUntilIdle();
3557 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3558 session
->session_recv_window_size_
);
3559 EXPECT_EQ(kUploadDataSize
+ padding_length
,
3560 session
->session_unacked_recv_window_bytes_
);
3562 data
.CompleteRead();
3563 base::RunLoop().RunUntilIdle();
3564 EXPECT_FALSE(session
);
3567 // Peer sends more data than stream level receiving flow control window.
3568 TEST_P(SpdySessionTest
, StreamFlowControlTooMuchData
) {
3569 const int32 stream_max_recv_window_size
= 1024;
3570 const int32 data_frame_size
= 2 * stream_max_recv_window_size
;
3572 scoped_ptr
<SpdyFrame
> req(
3573 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3574 scoped_ptr
<SpdyFrame
> rst(
3575 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
3576 MockWrite writes
[] = {
3577 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 4),
3580 scoped_ptr
<SpdyFrame
> resp(
3581 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3582 const std::string
payload(data_frame_size
, 'a');
3583 scoped_ptr
<SpdyFrame
> data_frame(spdy_util_
.ConstructSpdyBodyFrame(
3584 1, payload
.data(), data_frame_size
, false));
3585 MockRead reads
[] = {
3586 CreateMockRead(*resp
, 1),
3587 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
3588 CreateMockRead(*data_frame
, 3),
3589 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
3590 MockRead(ASYNC
, 0, 6),
3593 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3594 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3595 CreateNetworkSession();
3597 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
3598 pool_peer
.SetStreamInitialRecvWindowSize(stream_max_recv_window_size
);
3599 base::WeakPtr
<SpdySession
> session
=
3600 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3601 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM
, session
->flow_control_state());
3603 GURL
url(kDefaultURL
);
3604 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
3605 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, LOWEST
, BoundNetLog());
3606 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3608 test::StreamDelegateDoNothing
delegate(spdy_stream
);
3609 spdy_stream
->SetDelegate(&delegate
);
3611 scoped_ptr
<SpdyHeaderBlock
> headers(
3612 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
3613 EXPECT_EQ(ERR_IO_PENDING
, spdy_stream
->SendRequestHeaders(
3614 headers
.Pass(), NO_MORE_DATA_TO_SEND
));
3616 // Request and response.
3617 base::RunLoop().RunUntilIdle();
3618 EXPECT_EQ(1u, spdy_stream
->stream_id());
3620 // Too large data frame causes flow control error, should close stream.
3621 data
.CompleteRead();
3622 base::RunLoop().RunUntilIdle();
3623 EXPECT_FALSE(spdy_stream
);
3625 EXPECT_TRUE(session
);
3626 data
.CompleteRead();
3627 base::RunLoop().RunUntilIdle();
3628 EXPECT_FALSE(session
);
3631 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3632 // deltas in the receiving window size when checking incoming frames for flow
3633 // control errors at session level.
3634 TEST_P(SpdySessionTest
, SessionFlowControlTooMuchDataTwoDataFrames
) {
3635 if (GetParam() < kProtoSPDY31
)
3638 const int32 session_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(session_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(session_max_recv_window_size
, second_data_frame_size
);
3646 // But in fact, the two data frames together overflow the receiving window at
3648 ASSERT_LT(session_max_recv_window_size
,
3649 first_data_frame_size
+ second_data_frame_size
);
3651 session_deps_
.host_resolver
->set_synchronous_mode(true);
3653 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3654 0, GOAWAY_FLOW_CONTROL_ERROR
,
3655 "delta_window_size is 400 in DecreaseRecvWindowSize, which is larger "
3656 "than the receive window size of 500"));
3657 MockWrite writes
[] = {
3658 CreateMockWrite(*goaway
, 4),
3661 const std::string
first_data_frame(first_data_frame_size
, 'a');
3662 scoped_ptr
<SpdyFrame
> first(spdy_util_
.ConstructSpdyBodyFrame(
3663 1, first_data_frame
.data(), first_data_frame_size
, false));
3664 const std::string
second_data_frame(second_data_frame_size
, 'b');
3665 scoped_ptr
<SpdyFrame
> second(spdy_util_
.ConstructSpdyBodyFrame(
3666 1, second_data_frame
.data(), second_data_frame_size
, false));
3667 MockRead reads
[] = {
3668 CreateMockRead(*first
, 0),
3669 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3670 CreateMockRead(*second
, 2),
3671 MockRead(ASYNC
, 0, 3),
3673 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3674 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3676 CreateNetworkSession();
3677 base::WeakPtr
<SpdySession
> session
=
3678 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3679 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3680 session
->flow_control_state());
3681 // Setting session level receiving window size to smaller than initial is not
3682 // possible via SpdySessionPoolPeer.
3683 session
->session_recv_window_size_
= session_max_recv_window_size
;
3685 // First data frame is immediately consumed and does not trigger
3687 base::RunLoop().RunUntilIdle();
3688 EXPECT_EQ(first_data_frame_size
, session
->session_unacked_recv_window_bytes_
);
3689 EXPECT_EQ(session_max_recv_window_size
, session
->session_recv_window_size_
);
3690 EXPECT_EQ(SpdySession::STATE_AVAILABLE
, session
->availability_state_
);
3692 // Second data frame overflows receiving window, causes session to close.
3693 data
.CompleteRead();
3694 base::RunLoop().RunUntilIdle();
3695 EXPECT_EQ(SpdySession::STATE_DRAINING
, session
->availability_state_
);
3698 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3699 // deltas in the receiving window size when checking incoming data frames for
3700 // flow control errors at stream level.
3701 TEST_P(SpdySessionTest
, StreamFlowControlTooMuchDataTwoDataFrames
) {
3702 if (GetParam() < kProtoSPDY3
)
3705 const int32 stream_max_recv_window_size
= 500;
3706 const int32 first_data_frame_size
= 200;
3707 const int32 second_data_frame_size
= 400;
3709 // First data frame should not trigger a WINDOW_UPDATE.
3710 ASSERT_GT(stream_max_recv_window_size
/ 2, first_data_frame_size
);
3711 // Second data frame would be fine had there been a WINDOW_UPDATE.
3712 ASSERT_GT(stream_max_recv_window_size
, second_data_frame_size
);
3713 // But in fact, they should overflow the receiving window at stream level.
3714 ASSERT_LT(stream_max_recv_window_size
,
3715 first_data_frame_size
+ second_data_frame_size
);
3717 scoped_ptr
<SpdyFrame
> req(
3718 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3719 scoped_ptr
<SpdyFrame
> rst(
3720 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
3721 MockWrite writes
[] = {
3722 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 6),
3725 scoped_ptr
<SpdyFrame
> resp(
3726 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3727 const std::string
first_data_frame(first_data_frame_size
, 'a');
3728 scoped_ptr
<SpdyFrame
> first(spdy_util_
.ConstructSpdyBodyFrame(
3729 1, first_data_frame
.data(), first_data_frame_size
, false));
3730 const std::string
second_data_frame(second_data_frame_size
, 'b');
3731 scoped_ptr
<SpdyFrame
> second(spdy_util_
.ConstructSpdyBodyFrame(
3732 1, second_data_frame
.data(), second_data_frame_size
, false));
3733 MockRead reads
[] = {
3734 CreateMockRead(*resp
, 1),
3735 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
3736 CreateMockRead(*first
, 3),
3737 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
3738 CreateMockRead(*second
, 5),
3739 MockRead(ASYNC
, ERR_IO_PENDING
, 7),
3740 MockRead(ASYNC
, 0, 8),
3743 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3744 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3746 CreateNetworkSession();
3747 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
3748 pool_peer
.SetStreamInitialRecvWindowSize(stream_max_recv_window_size
);
3750 base::WeakPtr
<SpdySession
> session
=
3751 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3752 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM
, session
->flow_control_state());
3754 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
3755 SPDY_REQUEST_RESPONSE_STREAM
, session
, test_url_
, LOWEST
, BoundNetLog());
3756 test::StreamDelegateDoNothing
delegate(spdy_stream
);
3757 spdy_stream
->SetDelegate(&delegate
);
3759 scoped_ptr
<SpdyHeaderBlock
> headers(
3760 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
3761 EXPECT_EQ(ERR_IO_PENDING
, spdy_stream
->SendRequestHeaders(
3762 headers
.Pass(), NO_MORE_DATA_TO_SEND
));
3764 // Request and response.
3765 base::RunLoop().RunUntilIdle();
3766 EXPECT_TRUE(spdy_stream
->IsLocallyClosed());
3767 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3769 // First data frame.
3770 data
.CompleteRead();
3771 base::RunLoop().RunUntilIdle();
3772 EXPECT_TRUE(spdy_stream
->IsLocallyClosed());
3773 EXPECT_EQ(stream_max_recv_window_size
- first_data_frame_size
,
3774 spdy_stream
->recv_window_size());
3776 // Consume first data frame. This does not trigger a WINDOW_UPDATE.
3777 std::string received_data
= delegate
.TakeReceivedData();
3778 EXPECT_EQ(static_cast<size_t>(first_data_frame_size
), received_data
.size());
3779 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3781 // Second data frame overflows receiving window, causes the stream to close.
3782 data
.CompleteRead();
3783 base::RunLoop().RunUntilIdle();
3784 EXPECT_FALSE(spdy_stream
.get());
3787 EXPECT_TRUE(session
);
3788 data
.CompleteRead();
3789 base::RunLoop().RunUntilIdle();
3790 EXPECT_FALSE(session
);
3793 // A delegate that drops any received data.
3794 class DropReceivedDataDelegate
: public test::StreamDelegateSendImmediate
{
3796 DropReceivedDataDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3797 base::StringPiece data
)
3798 : StreamDelegateSendImmediate(stream
, data
) {}
3800 ~DropReceivedDataDelegate() override
{}
3802 // Drop any received data.
3803 void OnDataReceived(scoped_ptr
<SpdyBuffer
> buffer
) override
{}
3806 // Send data back and forth but use a delegate that drops its received
3807 // data. The receive window should still increase to its original
3808 // value, i.e. we shouldn't "leak" receive window bytes.
3809 TEST_P(SpdySessionTest
, SessionFlowControlNoReceiveLeaks
) {
3810 if (GetParam() < kProtoSPDY31
)
3813 const char kStreamUrl
[] = "http://www.example.org/";
3815 const int32 msg_data_size
= 100;
3816 const std::string
msg_data(msg_data_size
, 'a');
3818 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3819 kStreamUrl
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
3820 scoped_ptr
<SpdyFrame
> msg(
3821 spdy_util_
.ConstructSpdyBodyFrame(
3822 1, msg_data
.data(), msg_data_size
, false));
3823 MockWrite writes
[] = {
3824 CreateMockWrite(*req
, 0),
3825 CreateMockWrite(*msg
, 2),
3828 scoped_ptr
<SpdyFrame
> resp(
3829 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3830 scoped_ptr
<SpdyFrame
> echo(
3831 spdy_util_
.ConstructSpdyBodyFrame(
3832 1, msg_data
.data(), msg_data_size
, false));
3833 scoped_ptr
<SpdyFrame
> window_update(
3834 spdy_util_
.ConstructSpdyWindowUpdate(
3835 kSessionFlowControlStreamId
, msg_data_size
));
3836 MockRead reads
[] = {
3837 CreateMockRead(*resp
, 1),
3838 CreateMockRead(*echo
, 3),
3839 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
3840 MockRead(ASYNC
, 0, 5) // EOF
3843 // Create SpdySession and SpdyStream and send the request.
3844 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3845 session_deps_
.host_resolver
->set_synchronous_mode(true);
3846 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3848 CreateNetworkSession();
3850 base::WeakPtr
<SpdySession
> session
=
3851 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3853 GURL
url(kStreamUrl
);
3854 base::WeakPtr
<SpdyStream
> stream
=
3855 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3856 session
, url
, MEDIUM
, BoundNetLog());
3857 ASSERT_TRUE(stream
.get() != nullptr);
3858 EXPECT_EQ(0u, stream
->stream_id());
3860 DropReceivedDataDelegate
delegate(stream
, msg_data
);
3861 stream
->SetDelegate(&delegate
);
3863 scoped_ptr
<SpdyHeaderBlock
> headers(
3864 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3865 EXPECT_EQ(ERR_IO_PENDING
,
3866 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3867 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3869 const int32 initial_window_size
=
3870 SpdySession::GetDefaultInitialWindowSize(GetParam());
3871 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3872 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3874 base::RunLoop().RunUntilIdle();
3876 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3877 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3880 EXPECT_FALSE(stream
);
3882 EXPECT_EQ(OK
, delegate
.WaitForClose());
3884 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3885 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3887 data
.CompleteRead();
3888 base::RunLoop().RunUntilIdle();
3889 EXPECT_FALSE(session
);
3892 // Send data back and forth but close the stream before its data frame
3893 // can be written to the socket. The send window should then increase
3894 // to its original value, i.e. we shouldn't "leak" send window bytes.
3895 TEST_P(SpdySessionTest
, SessionFlowControlNoSendLeaks
) {
3896 if (GetParam() < kProtoSPDY31
)
3899 const char kStreamUrl
[] = "http://www.example.org/";
3901 const int32 msg_data_size
= 100;
3902 const std::string
msg_data(msg_data_size
, 'a');
3904 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3905 kStreamUrl
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
3906 MockWrite writes
[] = {
3907 CreateMockWrite(*req
, 0),
3910 scoped_ptr
<SpdyFrame
> resp(
3911 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3912 MockRead reads
[] = {
3913 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3914 CreateMockRead(*resp
, 2),
3915 MockRead(ASYNC
, 0, 3) // EOF
3918 // Create SpdySession and SpdyStream and send the request.
3919 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3920 session_deps_
.host_resolver
->set_synchronous_mode(true);
3921 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3923 CreateNetworkSession();
3925 base::WeakPtr
<SpdySession
> session
=
3926 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3928 GURL
url(kStreamUrl
);
3929 base::WeakPtr
<SpdyStream
> stream
=
3930 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3931 session
, url
, MEDIUM
, BoundNetLog());
3932 ASSERT_TRUE(stream
.get() != nullptr);
3933 EXPECT_EQ(0u, stream
->stream_id());
3935 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3936 stream
->SetDelegate(&delegate
);
3938 scoped_ptr
<SpdyHeaderBlock
> headers(
3939 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3940 EXPECT_EQ(ERR_IO_PENDING
,
3941 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3942 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3944 const int32 initial_window_size
=
3945 SpdySession::GetDefaultInitialWindowSize(GetParam());
3946 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3949 base::RunLoop().RunUntilIdle();
3951 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3953 // Read response, but do not run the message loop, so that the body is not
3954 // written to the socket.
3955 data
.CompleteRead();
3957 EXPECT_EQ(initial_window_size
- msg_data_size
,
3958 session
->session_send_window_size_
);
3960 // Closing the stream should increase the session's send window.
3962 EXPECT_FALSE(stream
);
3964 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3966 EXPECT_EQ(OK
, delegate
.WaitForClose());
3968 base::RunLoop().RunUntilIdle();
3969 EXPECT_FALSE(session
);
3971 EXPECT_TRUE(data
.AllWriteDataConsumed());
3972 EXPECT_TRUE(data
.AllReadDataConsumed());
3975 // Send data back and forth; the send and receive windows should
3976 // change appropriately.
3977 TEST_P(SpdySessionTest
, SessionFlowControlEndToEnd
) {
3978 if (GetParam() < kProtoSPDY31
)
3981 const char kStreamUrl
[] = "http://www.example.org/";
3983 const int32 msg_data_size
= 100;
3984 const std::string
msg_data(msg_data_size
, 'a');
3986 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3987 kStreamUrl
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
3988 scoped_ptr
<SpdyFrame
> msg(
3989 spdy_util_
.ConstructSpdyBodyFrame(
3990 1, msg_data
.data(), msg_data_size
, false));
3991 MockWrite writes
[] = {
3992 CreateMockWrite(*req
, 0),
3993 CreateMockWrite(*msg
, 2),
3996 scoped_ptr
<SpdyFrame
> resp(
3997 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3998 scoped_ptr
<SpdyFrame
> echo(
3999 spdy_util_
.ConstructSpdyBodyFrame(
4000 1, msg_data
.data(), msg_data_size
, false));
4001 scoped_ptr
<SpdyFrame
> window_update(
4002 spdy_util_
.ConstructSpdyWindowUpdate(
4003 kSessionFlowControlStreamId
, msg_data_size
));
4004 MockRead reads
[] = {
4005 CreateMockRead(*resp
, 1),
4006 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4007 CreateMockRead(*echo
, 4),
4008 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4009 CreateMockRead(*window_update
, 6),
4010 MockRead(ASYNC
, ERR_IO_PENDING
, 7),
4011 MockRead(ASYNC
, 0, 8) // EOF
4014 // Create SpdySession and SpdyStream and send the request.
4015 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4016 session_deps_
.host_resolver
->set_synchronous_mode(true);
4017 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4019 CreateNetworkSession();
4021 base::WeakPtr
<SpdySession
> session
=
4022 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4024 GURL
url(kStreamUrl
);
4025 base::WeakPtr
<SpdyStream
> stream
=
4026 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
4027 session
, url
, MEDIUM
, BoundNetLog());
4028 ASSERT_TRUE(stream
.get() != nullptr);
4029 EXPECT_EQ(0u, stream
->stream_id());
4031 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
4032 stream
->SetDelegate(&delegate
);
4034 scoped_ptr
<SpdyHeaderBlock
> headers(
4035 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
4036 EXPECT_EQ(ERR_IO_PENDING
,
4037 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
4038 EXPECT_TRUE(stream
->HasUrlFromHeaders());
4040 const int32 initial_window_size
=
4041 SpdySession::GetDefaultInitialWindowSize(GetParam());
4042 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
4043 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
4044 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
4046 // Send request and message.
4047 base::RunLoop().RunUntilIdle();
4049 EXPECT_EQ(initial_window_size
- msg_data_size
,
4050 session
->session_send_window_size_
);
4051 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
4052 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
4055 data
.CompleteRead();
4056 base::RunLoop().RunUntilIdle();
4058 EXPECT_EQ(initial_window_size
- msg_data_size
,
4059 session
->session_send_window_size_
);
4060 EXPECT_EQ(initial_window_size
- msg_data_size
,
4061 session
->session_recv_window_size_
);
4062 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
4064 // Read window update.
4065 data
.CompleteRead();
4066 base::RunLoop().RunUntilIdle();
4068 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
4069 EXPECT_EQ(initial_window_size
- msg_data_size
,
4070 session
->session_recv_window_size_
);
4071 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
4073 EXPECT_EQ(msg_data
, delegate
.TakeReceivedData());
4075 // Draining the delegate's read queue should increase the session's
4077 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
4078 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
4079 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
4082 EXPECT_FALSE(stream
);
4084 EXPECT_EQ(OK
, delegate
.WaitForClose());
4086 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
4087 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
4088 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
4090 data
.CompleteRead();
4091 base::RunLoop().RunUntilIdle();
4092 EXPECT_FALSE(session
);
4095 // Given a stall function and an unstall function, runs a test to make
4096 // sure that a stream resumes after unstall.
4097 void SpdySessionTest::RunResumeAfterUnstallTest(
4098 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
4099 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
4101 const char kStreamUrl
[] = "http://www.example.org/";
4102 GURL
url(kStreamUrl
);
4104 session_deps_
.host_resolver
->set_synchronous_mode(true);
4106 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
4107 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4108 scoped_ptr
<SpdyFrame
> body(
4109 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
4110 MockWrite writes
[] = {
4111 CreateMockWrite(*req
, 0),
4112 CreateMockWrite(*body
, 1),
4115 scoped_ptr
<SpdyFrame
> resp(
4116 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4117 scoped_ptr
<SpdyFrame
> echo(
4118 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4119 MockRead reads
[] = {
4120 CreateMockRead(*resp
, 2), MockRead(ASYNC
, 0, 3) // EOF
4123 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4124 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4126 CreateNetworkSession();
4127 base::WeakPtr
<SpdySession
> session
=
4128 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4129 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4130 session
->flow_control_state());
4132 base::WeakPtr
<SpdyStream
> stream
=
4133 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4134 session
, url
, LOWEST
, BoundNetLog());
4135 ASSERT_TRUE(stream
.get() != nullptr);
4137 test::StreamDelegateWithBody
delegate(stream
, kBodyDataStringPiece
);
4138 stream
->SetDelegate(&delegate
);
4140 EXPECT_FALSE(stream
->HasUrlFromHeaders());
4141 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4143 scoped_ptr
<SpdyHeaderBlock
> headers(
4144 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4145 EXPECT_EQ(ERR_IO_PENDING
,
4146 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
4147 EXPECT_TRUE(stream
->HasUrlFromHeaders());
4148 EXPECT_EQ(kStreamUrl
, stream
->GetUrlFromHeaders().spec());
4150 stall_function
.Run(session
.get(), stream
.get());
4152 base::RunLoop().RunUntilIdle();
4154 EXPECT_TRUE(stream
->send_stalled_by_flow_control());
4156 unstall_function
.Run(session
.get(), stream
.get(), kBodyDataSize
);
4158 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4160 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
4162 EXPECT_TRUE(delegate
.send_headers_completed());
4163 EXPECT_EQ("200", delegate
.GetResponseHeaderValue(":status"));
4164 EXPECT_EQ(std::string(), delegate
.TakeReceivedData());
4165 EXPECT_FALSE(session
);
4166 EXPECT_TRUE(data
.AllWriteDataConsumed());
4169 // Run the resume-after-unstall test with all possible stall and
4170 // unstall sequences.
4172 TEST_P(SpdySessionTest
, ResumeAfterUnstallSession
) {
4173 if (GetParam() < kProtoSPDY31
)
4176 RunResumeAfterUnstallTest(
4177 base::Bind(&SpdySessionTest::StallSessionOnly
,
4178 base::Unretained(this)),
4179 base::Bind(&SpdySessionTest::UnstallSessionOnly
,
4180 base::Unretained(this)));
4184 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4185 TEST_P(SpdySessionTest
, ResumeAfterUnstallStream
) {
4186 if (GetParam() < kProtoSPDY31
)
4189 RunResumeAfterUnstallTest(
4190 base::Bind(&SpdySessionTest::StallStreamOnly
,
4191 base::Unretained(this)),
4192 base::Bind(&SpdySessionTest::UnstallStreamOnly
,
4193 base::Unretained(this)));
4196 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallSessionStream
) {
4197 if (GetParam() < kProtoSPDY31
)
4200 RunResumeAfterUnstallTest(
4201 base::Bind(&SpdySessionTest::StallSessionStream
,
4202 base::Unretained(this)),
4203 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4204 base::Unretained(this)));
4207 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallSessionStream
) {
4208 if (GetParam() < kProtoSPDY31
)
4211 RunResumeAfterUnstallTest(
4212 base::Bind(&SpdySessionTest::StallStreamSession
,
4213 base::Unretained(this)),
4214 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4215 base::Unretained(this)));
4218 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallStreamSession
) {
4219 if (GetParam() < kProtoSPDY31
)
4222 RunResumeAfterUnstallTest(
4223 base::Bind(&SpdySessionTest::StallStreamSession
,
4224 base::Unretained(this)),
4225 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4226 base::Unretained(this)));
4229 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallStreamSession
) {
4230 if (GetParam() < kProtoSPDY31
)
4233 RunResumeAfterUnstallTest(
4234 base::Bind(&SpdySessionTest::StallSessionStream
,
4235 base::Unretained(this)),
4236 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4237 base::Unretained(this)));
4240 // Cause a stall by reducing the flow control send window to 0. The
4241 // streams should resume in priority order when that window is then
4243 TEST_P(SpdySessionTest
, ResumeByPriorityAfterSendWindowSizeIncrease
) {
4244 if (GetParam() < kProtoSPDY31
)
4247 const char kStreamUrl
[] = "http://www.example.org/";
4248 GURL
url(kStreamUrl
);
4250 session_deps_
.host_resolver
->set_synchronous_mode(true);
4252 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4253 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4254 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4255 kStreamUrl
, 3, kBodyDataSize
, MEDIUM
, nullptr, 0));
4256 scoped_ptr
<SpdyFrame
> body1(
4257 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
4258 scoped_ptr
<SpdyFrame
> body2(
4259 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4260 MockWrite writes
[] = {
4261 CreateMockWrite(*req1
, 0),
4262 CreateMockWrite(*req2
, 1),
4263 CreateMockWrite(*body2
, 2),
4264 CreateMockWrite(*body1
, 3),
4267 scoped_ptr
<SpdyFrame
> resp1(
4268 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4269 scoped_ptr
<SpdyFrame
> resp2(
4270 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
4271 MockRead reads
[] = {
4272 CreateMockRead(*resp1
, 4),
4273 CreateMockRead(*resp2
, 5),
4274 MockRead(ASYNC
, 0, 6) // EOF
4277 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4278 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4280 CreateNetworkSession();
4281 base::WeakPtr
<SpdySession
> session
=
4282 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4283 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4284 session
->flow_control_state());
4286 base::WeakPtr
<SpdyStream
> stream1
=
4287 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4288 session
, url
, LOWEST
, BoundNetLog());
4289 ASSERT_TRUE(stream1
.get() != nullptr);
4291 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4292 stream1
->SetDelegate(&delegate1
);
4294 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4296 base::WeakPtr
<SpdyStream
> stream2
=
4297 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4298 session
, url
, MEDIUM
, BoundNetLog());
4299 ASSERT_TRUE(stream2
.get() != nullptr);
4301 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4302 stream2
->SetDelegate(&delegate2
);
4304 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4306 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4307 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4309 StallSessionSend(session
.get());
4311 scoped_ptr
<SpdyHeaderBlock
> headers1(
4312 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4313 EXPECT_EQ(ERR_IO_PENDING
,
4314 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4315 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4316 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4318 base::RunLoop().RunUntilIdle();
4319 EXPECT_EQ(1u, stream1
->stream_id());
4320 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4322 scoped_ptr
<SpdyHeaderBlock
> headers2(
4323 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4324 EXPECT_EQ(ERR_IO_PENDING
,
4325 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4326 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4327 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4329 base::RunLoop().RunUntilIdle();
4330 EXPECT_EQ(3u, stream2
->stream_id());
4331 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4333 // This should unstall only stream2.
4334 UnstallSessionSend(session
.get(), kBodyDataSize
);
4336 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4337 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4339 base::RunLoop().RunUntilIdle();
4341 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4342 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4344 // This should then unstall stream1.
4345 UnstallSessionSend(session
.get(), kBodyDataSize
);
4347 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4348 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4350 base::RunLoop().RunUntilIdle();
4352 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4353 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4355 EXPECT_TRUE(delegate1
.send_headers_completed());
4356 EXPECT_EQ("200", delegate1
.GetResponseHeaderValue(":status"));
4357 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4359 EXPECT_TRUE(delegate2
.send_headers_completed());
4360 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4361 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4363 EXPECT_FALSE(session
);
4364 EXPECT_TRUE(data
.AllWriteDataConsumed());
4365 EXPECT_TRUE(data
.AllReadDataConsumed());
4368 // Delegate that closes a given stream after sending its body.
4369 class StreamClosingDelegate
: public test::StreamDelegateWithBody
{
4371 StreamClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
4372 base::StringPiece data
)
4373 : StreamDelegateWithBody(stream
, data
) {}
4375 ~StreamClosingDelegate() override
{}
4377 void set_stream_to_close(const base::WeakPtr
<SpdyStream
>& stream_to_close
) {
4378 stream_to_close_
= stream_to_close
;
4381 void OnDataSent() override
{
4382 test::StreamDelegateWithBody::OnDataSent();
4383 if (stream_to_close_
.get()) {
4384 stream_to_close_
->Close();
4385 EXPECT_FALSE(stream_to_close_
);
4390 base::WeakPtr
<SpdyStream
> stream_to_close_
;
4393 // Cause a stall by reducing the flow control send window to
4394 // 0. Unstalling the session should properly handle deleted streams.
4395 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedStreams
) {
4396 if (GetParam() < kProtoSPDY31
)
4399 const char kStreamUrl
[] = "http://www.example.org/";
4400 GURL
url(kStreamUrl
);
4402 session_deps_
.host_resolver
->set_synchronous_mode(true);
4404 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4405 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4406 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4407 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, nullptr, 0));
4408 scoped_ptr
<SpdyFrame
> req3(spdy_util_
.ConstructSpdyPost(
4409 kStreamUrl
, 5, kBodyDataSize
, LOWEST
, nullptr, 0));
4410 scoped_ptr
<SpdyFrame
> body2(
4411 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4412 MockWrite writes
[] = {
4413 CreateMockWrite(*req1
, 0),
4414 CreateMockWrite(*req2
, 1),
4415 CreateMockWrite(*req3
, 2),
4416 CreateMockWrite(*body2
, 3),
4419 scoped_ptr
<SpdyFrame
> resp2(
4420 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
4421 MockRead reads
[] = {
4422 CreateMockRead(*resp2
, 4),
4423 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4424 MockRead(ASYNC
, 0, 6) // EOF
4427 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4428 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4430 CreateNetworkSession();
4431 base::WeakPtr
<SpdySession
> session
=
4432 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4433 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4434 session
->flow_control_state());
4436 base::WeakPtr
<SpdyStream
> stream1
=
4437 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4438 session
, url
, LOWEST
, BoundNetLog());
4439 ASSERT_TRUE(stream1
.get() != nullptr);
4441 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4442 stream1
->SetDelegate(&delegate1
);
4444 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4446 base::WeakPtr
<SpdyStream
> stream2
=
4447 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4448 session
, url
, LOWEST
, BoundNetLog());
4449 ASSERT_TRUE(stream2
.get() != nullptr);
4451 StreamClosingDelegate
delegate2(stream2
, kBodyDataStringPiece
);
4452 stream2
->SetDelegate(&delegate2
);
4454 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4456 base::WeakPtr
<SpdyStream
> stream3
=
4457 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4458 session
, url
, LOWEST
, BoundNetLog());
4459 ASSERT_TRUE(stream3
.get() != nullptr);
4461 test::StreamDelegateWithBody
delegate3(stream3
, kBodyDataStringPiece
);
4462 stream3
->SetDelegate(&delegate3
);
4464 EXPECT_FALSE(stream3
->HasUrlFromHeaders());
4466 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4467 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4468 EXPECT_FALSE(stream3
->send_stalled_by_flow_control());
4470 StallSessionSend(session
.get());
4472 scoped_ptr
<SpdyHeaderBlock
> headers1(
4473 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4474 EXPECT_EQ(ERR_IO_PENDING
,
4475 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4476 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4477 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4479 base::RunLoop().RunUntilIdle();
4480 EXPECT_EQ(1u, stream1
->stream_id());
4481 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4483 scoped_ptr
<SpdyHeaderBlock
> headers2(
4484 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4485 EXPECT_EQ(ERR_IO_PENDING
,
4486 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4487 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4488 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4490 base::RunLoop().RunUntilIdle();
4491 EXPECT_EQ(3u, stream2
->stream_id());
4492 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4494 scoped_ptr
<SpdyHeaderBlock
> headers3(
4495 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4496 EXPECT_EQ(ERR_IO_PENDING
,
4497 stream3
->SendRequestHeaders(headers3
.Pass(), MORE_DATA_TO_SEND
));
4498 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
4499 EXPECT_EQ(kStreamUrl
, stream3
->GetUrlFromHeaders().spec());
4501 base::RunLoop().RunUntilIdle();
4502 EXPECT_EQ(5u, stream3
->stream_id());
4503 EXPECT_TRUE(stream3
->send_stalled_by_flow_control());
4505 SpdyStreamId stream_id1
= stream1
->stream_id();
4506 SpdyStreamId stream_id2
= stream2
->stream_id();
4507 SpdyStreamId stream_id3
= stream3
->stream_id();
4509 // Close stream1 preemptively.
4510 session
->CloseActiveStream(stream_id1
, ERR_CONNECTION_CLOSED
);
4511 EXPECT_FALSE(stream1
);
4513 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4514 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4515 EXPECT_TRUE(session
->IsStreamActive(stream_id3
));
4517 // Unstall stream2, which should then close stream3.
4518 delegate2
.set_stream_to_close(stream3
);
4519 UnstallSessionSend(session
.get(), kBodyDataSize
);
4521 base::RunLoop().RunUntilIdle();
4522 EXPECT_FALSE(stream3
);
4524 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4525 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4526 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4527 EXPECT_FALSE(session
->IsStreamActive(stream_id3
));
4529 data
.CompleteRead();
4530 base::RunLoop().RunUntilIdle();
4531 EXPECT_FALSE(stream2
);
4532 EXPECT_FALSE(session
);
4534 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4535 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4536 EXPECT_EQ(OK
, delegate3
.WaitForClose());
4538 EXPECT_TRUE(delegate1
.send_headers_completed());
4539 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4541 EXPECT_TRUE(delegate2
.send_headers_completed());
4542 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4543 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4545 EXPECT_TRUE(delegate3
.send_headers_completed());
4546 EXPECT_EQ(std::string(), delegate3
.TakeReceivedData());
4548 EXPECT_TRUE(data
.AllWriteDataConsumed());
4551 // Cause a stall by reducing the flow control send window to
4552 // 0. Unstalling the session should properly handle the session itself
4554 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedSession
) {
4555 if (GetParam() < kProtoSPDY31
)
4558 const char kStreamUrl
[] = "http://www.example.org/";
4559 GURL
url(kStreamUrl
);
4561 session_deps_
.host_resolver
->set_synchronous_mode(true);
4563 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4564 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4565 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4566 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, nullptr, 0));
4567 scoped_ptr
<SpdyFrame
> body1(
4568 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4569 MockWrite writes
[] = {
4570 CreateMockWrite(*req1
, 0),
4571 CreateMockWrite(*req2
, 1),
4574 MockRead reads
[] = {
4575 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
4578 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4579 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4581 CreateNetworkSession();
4582 base::WeakPtr
<SpdySession
> session
=
4583 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4584 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4585 session
->flow_control_state());
4587 base::WeakPtr
<SpdyStream
> stream1
=
4588 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4589 session
, url
, LOWEST
, BoundNetLog());
4590 ASSERT_TRUE(stream1
.get() != nullptr);
4592 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4593 stream1
->SetDelegate(&delegate1
);
4595 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4597 base::WeakPtr
<SpdyStream
> stream2
=
4598 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4599 session
, url
, LOWEST
, BoundNetLog());
4600 ASSERT_TRUE(stream2
.get() != nullptr);
4602 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4603 stream2
->SetDelegate(&delegate2
);
4605 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4607 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4608 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4610 StallSessionSend(session
.get());
4612 scoped_ptr
<SpdyHeaderBlock
> headers1(
4613 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4614 EXPECT_EQ(ERR_IO_PENDING
,
4615 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4616 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4617 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4619 base::RunLoop().RunUntilIdle();
4620 EXPECT_EQ(1u, stream1
->stream_id());
4621 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4623 scoped_ptr
<SpdyHeaderBlock
> headers2(
4624 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4625 EXPECT_EQ(ERR_IO_PENDING
,
4626 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4627 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4628 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4630 base::RunLoop().RunUntilIdle();
4631 EXPECT_EQ(3u, stream2
->stream_id());
4632 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4634 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
4637 UnstallSessionSend(session
.get(), kBodyDataSize
);
4639 // Close the session (since we can't do it from within the delegate
4640 // method, since it's in the stream's loop).
4641 session
->CloseSessionOnError(ERR_CONNECTION_CLOSED
, "Closing session");
4642 data
.CompleteRead();
4643 base::RunLoop().RunUntilIdle();
4644 EXPECT_FALSE(session
);
4646 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
4648 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4649 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4651 EXPECT_TRUE(delegate1
.send_headers_completed());
4652 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4654 EXPECT_TRUE(delegate2
.send_headers_completed());
4655 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4657 EXPECT_TRUE(data
.AllWriteDataConsumed());
4660 TEST_P(SpdySessionTest
, GoAwayOnSessionFlowControlError
) {
4661 if (GetParam() < kProtoSPDY31
)
4664 scoped_ptr
<SpdyFrame
> req(
4665 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4666 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
4667 0, GOAWAY_FLOW_CONTROL_ERROR
,
4668 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4669 "the receive window size of 1"));
4670 MockWrite writes
[] = {
4671 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 4),
4674 scoped_ptr
<SpdyFrame
> resp(
4675 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4676 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4677 MockRead reads
[] = {
4678 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4679 CreateMockRead(*resp
, 2),
4680 CreateMockRead(*body
, 3),
4683 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4684 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4686 CreateNetworkSession();
4688 base::WeakPtr
<SpdySession
> session
=
4689 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4691 GURL
url(kDefaultURL
);
4692 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
4693 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, LOWEST
, BoundNetLog());
4694 ASSERT_TRUE(spdy_stream
.get() != nullptr);
4695 test::StreamDelegateDoNothing
delegate(spdy_stream
);
4696 spdy_stream
->SetDelegate(&delegate
);
4698 scoped_ptr
<SpdyHeaderBlock
> headers(
4699 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
4700 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4703 base::RunLoop().RunUntilIdle();
4705 // Put session on the edge of overflowing it's recv window.
4706 session
->session_recv_window_size_
= 1;
4708 // Read response headers & body. Body overflows the session window, and a
4709 // goaway is written.
4710 data
.CompleteRead();
4711 base::RunLoop().RunUntilIdle();
4713 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR
, delegate
.WaitForClose());
4714 EXPECT_FALSE(session
);
4717 TEST_P(SpdySessionTest
, SplitHeaders
) {
4718 GURL
kStreamUrl("http://www.example.org/foo.dat");
4719 SpdyHeaderBlock headers
;
4720 spdy_util_
.AddUrlToHeaderBlock(kStreamUrl
.spec(), &headers
);
4721 headers
["alpha"] = "beta";
4723 SpdyHeaderBlock request_headers
;
4724 SpdyHeaderBlock response_headers
;
4726 SplitPushedHeadersToRequestAndResponse(
4727 headers
, spdy_util_
.spdy_version(), &request_headers
, &response_headers
);
4729 SpdyHeaderBlock::const_iterator it
= response_headers
.find("alpha");
4730 std::string alpha_val
=
4731 (it
== response_headers
.end()) ? std::string() : it
->second
;
4732 EXPECT_EQ("beta", alpha_val
);
4735 GetUrlFromHeaderBlock(request_headers
, spdy_util_
.spdy_version(), true);
4736 EXPECT_EQ(kStreamUrl
, request_url
);
4739 // Regression. Sorta. Push streams and client streams were sharing a single
4740 // limit for a long time.
4741 TEST_P(SpdySessionTest
, PushedStreamShouldNotCountToClientConcurrencyLimit
) {
4742 SettingsMap new_settings
;
4743 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4744 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, 2);
4745 scoped_ptr
<SpdyFrame
> settings_frame(
4746 spdy_util_
.ConstructSpdySettings(new_settings
));
4747 scoped_ptr
<SpdyFrame
> pushed(spdy_util_
.ConstructSpdyPush(
4748 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4749 MockRead reads
[] = {
4750 CreateMockRead(*settings_frame
, 0),
4751 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4752 CreateMockRead(*pushed
, 4),
4753 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4754 MockRead(ASYNC
, 0, 6),
4757 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
4758 scoped_ptr
<SpdyFrame
> req(
4759 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4760 MockWrite writes
[] = {
4761 CreateMockWrite(*settings_ack
, 1), CreateMockWrite(*req
, 2),
4764 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4765 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4767 CreateNetworkSession();
4769 base::WeakPtr
<SpdySession
> session
=
4770 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4772 // Read the settings frame.
4773 base::RunLoop().RunUntilIdle();
4775 GURL
url1(kDefaultURL
);
4776 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4777 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4778 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4779 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4780 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4781 spdy_stream1
->SetDelegate(&delegate1
);
4783 EXPECT_EQ(0u, session
->num_active_streams());
4784 EXPECT_EQ(1u, session
->num_created_streams());
4785 EXPECT_EQ(0u, session
->num_pushed_streams());
4786 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4788 scoped_ptr
<SpdyHeaderBlock
> headers(
4789 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4790 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4791 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4793 // Run until 1st stream is activated.
4794 EXPECT_EQ(0u, delegate1
.stream_id());
4795 base::RunLoop().RunUntilIdle();
4796 EXPECT_EQ(1u, delegate1
.stream_id());
4797 EXPECT_EQ(1u, session
->num_active_streams());
4798 EXPECT_EQ(0u, session
->num_created_streams());
4799 EXPECT_EQ(0u, session
->num_pushed_streams());
4800 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4802 // Run until pushed stream is created.
4803 data
.CompleteRead();
4804 base::RunLoop().RunUntilIdle();
4805 EXPECT_EQ(2u, session
->num_active_streams());
4806 EXPECT_EQ(0u, session
->num_created_streams());
4807 EXPECT_EQ(1u, session
->num_pushed_streams());
4808 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4810 // Second stream should not be stalled, although we have 2 active streams, but
4811 // one of them is push stream and should not be taken into account when we
4812 // create streams on the client.
4813 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
4814 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4815 EXPECT_TRUE(spdy_stream2
);
4816 EXPECT_EQ(2u, session
->num_active_streams());
4817 EXPECT_EQ(1u, session
->num_created_streams());
4818 EXPECT_EQ(1u, session
->num_pushed_streams());
4819 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4822 data
.CompleteRead();
4823 base::RunLoop().RunUntilIdle();
4824 EXPECT_FALSE(session
);
4827 TEST_P(SpdySessionTest
, RejectPushedStreamExceedingConcurrencyLimit
) {
4828 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4829 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4830 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
4831 nullptr, 0, 4, 1, "http://www.example.org/b.dat"));
4832 MockRead reads
[] = {
4833 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4834 CreateMockRead(*push_a
, 2),
4835 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4836 CreateMockRead(*push_b
, 4),
4837 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
4838 MockRead(ASYNC
, 0, 7),
4841 scoped_ptr
<SpdyFrame
> req(
4842 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4843 scoped_ptr
<SpdyFrame
> rst(
4844 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4845 MockWrite writes
[] = {
4846 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5),
4849 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4850 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4852 CreateNetworkSession();
4854 base::WeakPtr
<SpdySession
> session
=
4855 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4856 session
->set_max_concurrent_pushed_streams(1);
4858 GURL
url1(kDefaultURL
);
4859 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4860 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4861 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4862 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4863 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4864 spdy_stream1
->SetDelegate(&delegate1
);
4866 EXPECT_EQ(0u, session
->num_active_streams());
4867 EXPECT_EQ(1u, session
->num_created_streams());
4868 EXPECT_EQ(0u, session
->num_pushed_streams());
4869 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4871 scoped_ptr
<SpdyHeaderBlock
> headers(
4872 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4873 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4874 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4876 // Run until 1st stream is activated.
4877 EXPECT_EQ(0u, delegate1
.stream_id());
4878 base::RunLoop().RunUntilIdle();
4879 EXPECT_EQ(1u, delegate1
.stream_id());
4880 EXPECT_EQ(1u, session
->num_active_streams());
4881 EXPECT_EQ(0u, session
->num_created_streams());
4882 EXPECT_EQ(0u, session
->num_pushed_streams());
4883 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4885 // Run until pushed stream is created.
4886 data
.CompleteRead();
4887 base::RunLoop().RunUntilIdle();
4888 EXPECT_EQ(2u, session
->num_active_streams());
4889 EXPECT_EQ(0u, session
->num_created_streams());
4890 EXPECT_EQ(1u, session
->num_pushed_streams());
4891 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4893 // Reset incoming pushed stream.
4894 data
.CompleteRead();
4895 base::RunLoop().RunUntilIdle();
4896 EXPECT_EQ(2u, session
->num_active_streams());
4897 EXPECT_EQ(0u, session
->num_created_streams());
4898 EXPECT_EQ(1u, session
->num_pushed_streams());
4899 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4902 data
.CompleteRead();
4903 base::RunLoop().RunUntilIdle();
4904 EXPECT_FALSE(session
);
4907 TEST_P(SpdySessionTest
, IgnoreReservedRemoteStreamsCount
) {
4908 // Streams in reserved remote state exist only in HTTP/2.
4909 if (spdy_util_
.spdy_version() < HTTP2
)
4912 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4913 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4914 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4915 spdy_util_
.AddUrlToHeaderBlock("http://www.example.org/b.dat",
4916 push_headers
.get());
4917 scoped_ptr
<SpdyFrame
> push_b(
4918 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 4, 1));
4919 scoped_ptr
<SpdyFrame
> headers_b(
4920 spdy_util_
.ConstructSpdyPushHeaders(4, nullptr, 0));
4921 MockRead reads
[] = {
4922 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4923 CreateMockRead(*push_a
, 2),
4924 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4925 CreateMockRead(*push_b
, 4),
4926 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4927 CreateMockRead(*headers_b
, 6),
4928 MockRead(ASYNC
, ERR_IO_PENDING
, 8),
4929 MockRead(ASYNC
, 0, 9),
4932 scoped_ptr
<SpdyFrame
> req(
4933 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4934 scoped_ptr
<SpdyFrame
> rst(
4935 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4936 MockWrite writes
[] = {
4937 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 7),
4940 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4941 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4943 CreateNetworkSession();
4945 base::WeakPtr
<SpdySession
> session
=
4946 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4947 session
->set_max_concurrent_pushed_streams(1);
4949 GURL
url1(kDefaultURL
);
4950 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4951 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4952 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4953 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4954 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4955 spdy_stream1
->SetDelegate(&delegate1
);
4957 EXPECT_EQ(0u, session
->num_active_streams());
4958 EXPECT_EQ(1u, session
->num_created_streams());
4959 EXPECT_EQ(0u, session
->num_pushed_streams());
4960 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4962 scoped_ptr
<SpdyHeaderBlock
> headers(
4963 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4964 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4965 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4967 // Run until 1st stream is activated.
4968 EXPECT_EQ(0u, delegate1
.stream_id());
4969 base::RunLoop().RunUntilIdle();
4970 EXPECT_EQ(1u, delegate1
.stream_id());
4971 EXPECT_EQ(1u, session
->num_active_streams());
4972 EXPECT_EQ(0u, session
->num_created_streams());
4973 EXPECT_EQ(0u, session
->num_pushed_streams());
4974 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4976 // Run until pushed stream is created.
4977 data
.CompleteRead();
4978 base::RunLoop().RunUntilIdle();
4979 EXPECT_EQ(2u, session
->num_active_streams());
4980 EXPECT_EQ(0u, session
->num_created_streams());
4981 EXPECT_EQ(1u, session
->num_pushed_streams());
4982 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4984 // Accept promised stream. It should not count towards pushed stream limit.
4985 data
.CompleteRead();
4986 base::RunLoop().RunUntilIdle();
4987 EXPECT_EQ(3u, session
->num_active_streams());
4988 EXPECT_EQ(0u, session
->num_created_streams());
4989 EXPECT_EQ(2u, session
->num_pushed_streams());
4990 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4992 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4993 // while we accept only one.
4994 data
.CompleteRead();
4995 base::RunLoop().RunUntilIdle();
4996 EXPECT_EQ(2u, session
->num_active_streams());
4997 EXPECT_EQ(0u, session
->num_created_streams());
4998 EXPECT_EQ(1u, session
->num_pushed_streams());
4999 EXPECT_EQ(1u, session
->num_active_pushed_streams());
5002 data
.CompleteRead();
5003 base::RunLoop().RunUntilIdle();
5004 EXPECT_FALSE(session
);
5007 TEST_P(SpdySessionTest
, CancelReservedStreamOnHeadersReceived
) {
5008 // Streams in reserved remote state exist only in HTTP/2.
5009 if (spdy_util_
.spdy_version() < HTTP2
)
5012 const char kPushedUrl
[] = "http://www.example.org/a.dat";
5013 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
5014 spdy_util_
.AddUrlToHeaderBlock(kPushedUrl
, push_headers
.get());
5015 scoped_ptr
<SpdyFrame
> push_promise(
5016 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 2, 1));
5017 scoped_ptr
<SpdyFrame
> headers_frame(
5018 spdy_util_
.ConstructSpdyPushHeaders(2, nullptr, 0));
5019 MockRead reads
[] = {
5020 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
5021 CreateMockRead(*push_promise
, 2),
5022 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
5023 CreateMockRead(*headers_frame
, 4),
5024 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
5025 MockRead(ASYNC
, 0, 7),
5028 scoped_ptr
<SpdyFrame
> req(
5029 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
5030 scoped_ptr
<SpdyFrame
> rst(
5031 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
5032 MockWrite writes
[] = {
5033 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5),
5036 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
5037 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5039 CreateNetworkSession();
5041 base::WeakPtr
<SpdySession
> session
=
5042 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
5044 GURL
url1(kDefaultURL
);
5045 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
5046 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
5047 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
5048 EXPECT_EQ(0u, spdy_stream1
->stream_id());
5049 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
5050 spdy_stream1
->SetDelegate(&delegate1
);
5052 EXPECT_EQ(0u, session
->num_active_streams());
5053 EXPECT_EQ(1u, session
->num_created_streams());
5054 EXPECT_EQ(0u, session
->num_pushed_streams());
5055 EXPECT_EQ(0u, session
->num_active_pushed_streams());
5057 scoped_ptr
<SpdyHeaderBlock
> headers(
5058 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
5059 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
5060 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
5062 // Run until 1st stream is activated.
5063 EXPECT_EQ(0u, delegate1
.stream_id());
5064 base::RunLoop().RunUntilIdle();
5065 EXPECT_EQ(1u, delegate1
.stream_id());
5066 EXPECT_EQ(1u, session
->num_active_streams());
5067 EXPECT_EQ(0u, session
->num_created_streams());
5068 EXPECT_EQ(0u, session
->num_pushed_streams());
5069 EXPECT_EQ(0u, session
->num_active_pushed_streams());
5071 // Run until pushed stream is created.
5072 data
.CompleteRead();
5073 base::RunLoop().RunUntilIdle();
5074 EXPECT_EQ(2u, session
->num_active_streams());
5075 EXPECT_EQ(0u, session
->num_created_streams());
5076 EXPECT_EQ(1u, session
->num_pushed_streams());
5077 EXPECT_EQ(0u, session
->num_active_pushed_streams());
5079 base::WeakPtr
<SpdyStream
> pushed_stream
;
5081 session
->GetPushStream(GURL(kPushedUrl
), &pushed_stream
, BoundNetLog());
5083 ASSERT_TRUE(pushed_stream
.get() != nullptr);
5084 test::StreamDelegateCloseOnHeaders
delegate2(pushed_stream
);
5085 pushed_stream
->SetDelegate(&delegate2
);
5087 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
5088 // that all our counters are in consistent state.
5089 data
.CompleteRead();
5090 base::RunLoop().RunUntilIdle();
5091 EXPECT_EQ(1u, session
->num_active_streams());
5092 EXPECT_EQ(0u, session
->num_created_streams());
5093 EXPECT_EQ(0u, session
->num_pushed_streams());
5094 EXPECT_EQ(0u, session
->num_active_pushed_streams());
5097 data
.CompleteRead();
5098 base::RunLoop().RunUntilIdle();
5099 EXPECT_TRUE(data
.AllWriteDataConsumed());
5100 EXPECT_TRUE(data
.AllReadDataConsumed());
5103 TEST_P(SpdySessionTest
, RejectInvalidUnknownFrames
) {
5104 session_deps_
.host_resolver
->set_synchronous_mode(true);
5106 MockRead reads
[] = {
5107 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
5110 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
5111 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5113 CreateNetworkSession();
5114 base::WeakPtr
<SpdySession
> session
=
5115 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
5117 session
->stream_hi_water_mark_
= 5;
5118 // Low client (odd) ids are fine.
5119 EXPECT_TRUE(session
->OnUnknownFrame(3, 0));
5120 // Client id exceeding watermark.
5121 EXPECT_FALSE(session
->OnUnknownFrame(9, 0));
5123 session
->last_accepted_push_stream_id_
= 6;
5124 // Low server (even) ids are fine.
5125 EXPECT_TRUE(session
->OnUnknownFrame(2, 0));
5126 // Server id exceeding last accepted id.
5127 EXPECT_FALSE(session
->OnUnknownFrame(8, 0));
5130 TEST(MapFramerErrorToProtocolError
, MapsValues
) {
5132 SPDY_ERROR_INVALID_CONTROL_FRAME
,
5133 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
5135 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS
,
5136 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
5138 SPDY_ERROR_GOAWAY_FRAME_CORRUPT
,
5139 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT
));
5140 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME
,
5141 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME
));
5144 TEST(MapFramerErrorToNetError
, MapsValue
) {
5145 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR
,
5146 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
5147 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
5148 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE
));
5149 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
5150 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE
));
5152 ERR_SPDY_FRAME_SIZE_ERROR
,
5153 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
));
5156 TEST(MapRstStreamStatusToProtocolError
, MapsValues
) {
5157 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR
,
5158 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR
));
5159 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR
,
5160 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR
));
5161 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM
,
5162 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM
));
5163 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY
,
5164 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY
));
5165 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED
,
5166 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED
));
5169 TEST(MapNetErrorToGoAwayStatus
, MapsValue
) {
5170 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY
,
5171 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
));
5172 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR
,
5173 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR
));
5174 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
,
5175 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR
));
5176 CHECK_EQ(GOAWAY_COMPRESSION_ERROR
,
5177 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR
));
5178 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR
,
5179 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR
));
5180 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED
));
5183 TEST(CanPoolTest
, CanPool
) {
5184 // Load a cert that is valid for:
5189 TransportSecurityState tss
;
5191 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5192 "spdy_pooling.pem");
5194 EXPECT_TRUE(SpdySession::CanPool(
5195 &tss
, ssl_info
, "www.example.org", "www.example.org"));
5196 EXPECT_TRUE(SpdySession::CanPool(
5197 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5198 EXPECT_TRUE(SpdySession::CanPool(
5199 &tss
, ssl_info
, "www.example.org", "mail.example.com"));
5200 EXPECT_FALSE(SpdySession::CanPool(
5201 &tss
, ssl_info
, "www.example.org", "mail.google.com"));
5204 TEST(CanPoolTest
, CanNotPoolWithCertErrors
) {
5205 // Load a cert that is valid for:
5210 TransportSecurityState tss
;
5212 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5213 "spdy_pooling.pem");
5214 ssl_info
.cert_status
= CERT_STATUS_REVOKED
;
5216 EXPECT_FALSE(SpdySession::CanPool(
5217 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5220 TEST(CanPoolTest
, CanNotPoolWithClientCerts
) {
5221 // Load a cert that is valid for:
5226 TransportSecurityState tss
;
5228 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5229 "spdy_pooling.pem");
5230 ssl_info
.client_cert_sent
= true;
5232 EXPECT_FALSE(SpdySession::CanPool(
5233 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5236 TEST(CanPoolTest
, CanNotPoolAcrossETLDsWithChannelID
) {
5237 // Load a cert that is valid for:
5242 TransportSecurityState tss
;
5244 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5245 "spdy_pooling.pem");
5246 ssl_info
.channel_id_sent
= true;
5248 EXPECT_TRUE(SpdySession::CanPool(
5249 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5250 EXPECT_FALSE(SpdySession::CanPool(
5251 &tss
, ssl_info
, "www.example.org", "www.example.com"));
5254 TEST(CanPoolTest
, CanNotPoolWithBadPins
) {
5255 uint8 primary_pin
= 1;
5256 uint8 backup_pin
= 2;
5258 TransportSecurityState tss
;
5259 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5262 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5263 "spdy_pooling.pem");
5264 ssl_info
.is_issued_by_known_root
= true;
5265 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(bad_pin
));
5267 EXPECT_FALSE(SpdySession::CanPool(
5268 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5271 TEST(CanPoolTest
, CanPoolWithAcceptablePins
) {
5272 uint8 primary_pin
= 1;
5273 uint8 backup_pin
= 2;
5274 TransportSecurityState tss
;
5275 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5278 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5279 "spdy_pooling.pem");
5280 ssl_info
.is_issued_by_known_root
= true;
5281 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(primary_pin
));
5283 EXPECT_TRUE(SpdySession::CanPool(
5284 &tss
, ssl_info
, "www.example.org", "mail.example.org"));