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
;
51 base::TimeTicks
SlowReads() {
53 base::TimeDelta::FromMilliseconds(2 * kYieldAfterDurationMilliseconds
);
54 return base::TimeTicks::Now() + g_time_delta
;
59 class SpdySessionTest
: public PlatformTest
,
60 public ::testing::WithParamInterface
<NextProto
> {
62 // Functions used with RunResumeAfterUnstallTest().
64 void StallSessionOnly(SpdySession
* session
, SpdyStream
* stream
) {
65 StallSessionSend(session
);
68 void StallStreamOnly(SpdySession
* session
, SpdyStream
* stream
) {
69 StallStreamSend(stream
);
72 void StallSessionStream(SpdySession
* session
, SpdyStream
* stream
) {
73 StallSessionSend(session
);
74 StallStreamSend(stream
);
77 void StallStreamSession(SpdySession
* session
, SpdyStream
* stream
) {
78 StallStreamSend(stream
);
79 StallSessionSend(session
);
82 void UnstallSessionOnly(SpdySession
* session
,
84 int32 delta_window_size
) {
85 UnstallSessionSend(session
, delta_window_size
);
88 void UnstallStreamOnly(SpdySession
* session
,
90 int32 delta_window_size
) {
91 UnstallStreamSend(stream
, delta_window_size
);
94 void UnstallSessionStream(SpdySession
* session
,
96 int32 delta_window_size
) {
97 UnstallSessionSend(session
, delta_window_size
);
98 UnstallStreamSend(stream
, delta_window_size
);
101 void UnstallStreamSession(SpdySession
* session
,
103 int32 delta_window_size
) {
104 UnstallStreamSend(stream
, delta_window_size
);
105 UnstallSessionSend(session
, delta_window_size
);
110 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
111 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
112 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
113 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
114 spdy_util_(GetParam()),
115 session_deps_(GetParam()),
116 spdy_session_pool_(nullptr),
118 test_host_port_pair_(kTestHost
, kTestPort
),
119 key_(test_host_port_pair_
,
120 ProxyServer::Direct(),
121 PRIVACY_MODE_DISABLED
) {}
123 virtual ~SpdySessionTest() {
124 // Important to restore the per-pool limit first, since the pool limit must
125 // always be greater than group limit, and the tests reduce both limits.
126 ClientSocketPoolManager::set_max_sockets_per_pool(
127 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
128 ClientSocketPoolManager::set_max_sockets_per_group(
129 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
132 void SetUp() override
{ g_time_delta
= base::TimeDelta(); }
134 void CreateNetworkSession() {
136 SpdySessionDependencies::SpdyCreateSession(&session_deps_
);
137 spdy_session_pool_
= http_session_
->spdy_session_pool();
140 void StallSessionSend(SpdySession
* session
) {
141 // Reduce the send window size to 0 to stall.
142 while (session
->session_send_window_size_
> 0) {
143 session
->DecreaseSendWindowSize(
144 std::min(kMaxSpdyFrameChunkSize
, session
->session_send_window_size_
));
148 void UnstallSessionSend(SpdySession
* session
, int32 delta_window_size
) {
149 session
->IncreaseSendWindowSize(delta_window_size
);
152 void StallStreamSend(SpdyStream
* stream
) {
153 // Reduce the send window size to 0 to stall.
154 while (stream
->send_window_size() > 0) {
155 stream
->DecreaseSendWindowSize(
156 std::min(kMaxSpdyFrameChunkSize
, stream
->send_window_size()));
160 void UnstallStreamSend(SpdyStream
* stream
, int32 delta_window_size
) {
161 stream
->IncreaseSendWindowSize(delta_window_size
);
164 void RunResumeAfterUnstallTest(
165 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
166 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
169 // Original socket limits. Some tests set these. Safest to always restore
170 // them once each test has been run.
171 int old_max_group_sockets_
;
172 int old_max_pool_sockets_
;
174 SpdyTestUtil spdy_util_
;
175 SpdySessionDependencies session_deps_
;
176 scoped_refptr
<HttpNetworkSession
> http_session_
;
177 SpdySessionPool
* spdy_session_pool_
;
179 HostPortPair test_host_port_pair_
;
183 INSTANTIATE_TEST_CASE_P(NextProto
,
185 testing::Values(kProtoSPDY31
,
189 // Try to create a SPDY session that will fail during
190 // initialization. Nothing should blow up.
191 TEST_P(SpdySessionTest
, InitialReadError
) {
192 CreateNetworkSession();
194 base::WeakPtr
<SpdySession
> session
= TryCreateFakeSpdySessionExpectingFailure(
195 spdy_session_pool_
, key_
, ERR_CONNECTION_CLOSED
);
196 EXPECT_TRUE(session
);
198 base::RunLoop().RunUntilIdle();
199 EXPECT_FALSE(session
);
204 // A helper class that vends a callback that, when fired, destroys a
205 // given SpdyStreamRequest.
206 class StreamRequestDestroyingCallback
: public TestCompletionCallbackBase
{
208 StreamRequestDestroyingCallback() {}
210 ~StreamRequestDestroyingCallback() override
{}
212 void SetRequestToDestroy(scoped_ptr
<SpdyStreamRequest
> request
) {
213 request_
= request
.Pass();
216 CompletionCallback
MakeCallback() {
217 return base::Bind(&StreamRequestDestroyingCallback::OnComplete
,
218 base::Unretained(this));
222 void OnComplete(int result
) {
227 scoped_ptr
<SpdyStreamRequest
> request_
;
232 // Request kInitialMaxConcurrentStreams streams. Request two more
233 // streams, but have the callback for one destroy the second stream
234 // request. Close the session. Nothing should blow up. This is a
235 // regression test for http://crbug.com/250841 .
236 TEST_P(SpdySessionTest
, PendingStreamCancellingAnother
) {
237 session_deps_
.host_resolver
->set_synchronous_mode(true);
239 MockRead reads
[] = {MockRead(ASYNC
, 0, 0), };
241 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
242 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
244 CreateNetworkSession();
246 base::WeakPtr
<SpdySession
> session
=
247 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
249 // Create the maximum number of concurrent streams.
250 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
251 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
252 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
, BoundNetLog());
253 ASSERT_TRUE(spdy_stream
!= nullptr);
256 SpdyStreamRequest request1
;
257 scoped_ptr
<SpdyStreamRequest
> request2(new SpdyStreamRequest
);
259 StreamRequestDestroyingCallback callback1
;
260 ASSERT_EQ(ERR_IO_PENDING
,
261 request1
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
,
266 callback1
.MakeCallback()));
268 // |callback2| is never called.
269 TestCompletionCallback callback2
;
270 ASSERT_EQ(ERR_IO_PENDING
,
271 request2
->StartRequest(SPDY_BIDIRECTIONAL_STREAM
,
276 callback2
.callback()));
278 callback1
.SetRequestToDestroy(request2
.Pass());
280 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
282 EXPECT_EQ(ERR_ABORTED
, callback1
.WaitForResult());
285 // A session receiving a GOAWAY frame with no active streams should close.
286 TEST_P(SpdySessionTest
, GoAwayWithNoActiveStreams
) {
287 session_deps_
.host_resolver
->set_synchronous_mode(true);
289 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
291 CreateMockRead(*goaway
, 0),
293 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
294 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
296 CreateNetworkSession();
298 base::WeakPtr
<SpdySession
> session
=
299 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
301 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
303 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
305 // Read and process the GOAWAY frame.
306 base::RunLoop().RunUntilIdle();
307 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
308 EXPECT_FALSE(session
);
311 // A session receiving a GOAWAY frame immediately with no active
312 // streams should then close.
313 TEST_P(SpdySessionTest
, GoAwayImmediatelyWithNoActiveStreams
) {
314 session_deps_
.host_resolver
->set_synchronous_mode(true);
316 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
318 CreateMockRead(*goaway
, 0, SYNCHRONOUS
), MockRead(ASYNC
, 0, 1) // EOF
320 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
321 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
323 CreateNetworkSession();
325 base::WeakPtr
<SpdySession
> session
=
326 TryCreateInsecureSpdySessionExpectingFailure(
327 http_session_
, key_
, ERR_CONNECTION_CLOSED
, BoundNetLog());
328 base::RunLoop().RunUntilIdle();
330 EXPECT_FALSE(session
);
331 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
332 EXPECT_FALSE(data
.AllReadDataConsumed());
335 // A session receiving a GOAWAY frame with active streams should close
336 // when the last active stream is closed.
337 TEST_P(SpdySessionTest
, GoAwayWithActiveStreams
) {
338 session_deps_
.host_resolver
->set_synchronous_mode(true);
340 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
342 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
343 CreateMockRead(*goaway
, 3),
344 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
345 MockRead(ASYNC
, 0, 5) // EOF
347 scoped_ptr
<SpdyFrame
> req1(
348 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
349 scoped_ptr
<SpdyFrame
> req2(
350 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
351 MockWrite writes
[] = {
352 CreateMockWrite(*req1
, 0),
353 CreateMockWrite(*req2
, 1),
355 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
356 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
358 CreateNetworkSession();
360 base::WeakPtr
<SpdySession
> session
=
361 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
363 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
365 GURL
url(kDefaultURL
);
366 base::WeakPtr
<SpdyStream
> spdy_stream1
=
367 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
368 session
, url
, MEDIUM
, BoundNetLog());
369 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
370 spdy_stream1
->SetDelegate(&delegate1
);
372 base::WeakPtr
<SpdyStream
> spdy_stream2
=
373 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
374 session
, url
, MEDIUM
, BoundNetLog());
375 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
376 spdy_stream2
->SetDelegate(&delegate2
);
378 scoped_ptr
<SpdyHeaderBlock
> headers(
379 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
380 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
382 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
383 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
384 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
385 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
387 base::RunLoop().RunUntilIdle();
389 EXPECT_EQ(1u, spdy_stream1
->stream_id());
390 EXPECT_EQ(3u, spdy_stream2
->stream_id());
392 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
394 // Read and process the GOAWAY frame.
396 base::RunLoop().RunUntilIdle();
398 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
400 EXPECT_FALSE(session
->IsStreamActive(3));
401 EXPECT_FALSE(spdy_stream2
);
402 EXPECT_TRUE(session
->IsStreamActive(1));
404 EXPECT_TRUE(session
->IsGoingAway());
406 // Should close the session.
407 spdy_stream1
->Close();
408 EXPECT_FALSE(spdy_stream1
);
410 EXPECT_TRUE(session
);
412 base::RunLoop().RunUntilIdle();
413 EXPECT_FALSE(session
);
416 // Have a session receive two GOAWAY frames, with the last one causing
417 // the last active stream to be closed. The session should then be
418 // closed after the second GOAWAY frame.
419 TEST_P(SpdySessionTest
, GoAwayTwice
) {
420 session_deps_
.host_resolver
->set_synchronous_mode(true);
422 scoped_ptr
<SpdyFrame
> goaway1(spdy_util_
.ConstructSpdyGoAway(1));
423 scoped_ptr
<SpdyFrame
> goaway2(spdy_util_
.ConstructSpdyGoAway(0));
425 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
426 CreateMockRead(*goaway1
, 3),
427 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
428 CreateMockRead(*goaway2
, 5),
429 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
430 MockRead(ASYNC
, 0, 7) // EOF
432 scoped_ptr
<SpdyFrame
> req1(
433 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
434 scoped_ptr
<SpdyFrame
> req2(
435 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
436 MockWrite writes
[] = {
437 CreateMockWrite(*req1
, 0),
438 CreateMockWrite(*req2
, 1),
440 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
441 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
443 CreateNetworkSession();
445 base::WeakPtr
<SpdySession
> session
=
446 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
448 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
450 GURL
url(kDefaultURL
);
451 base::WeakPtr
<SpdyStream
> spdy_stream1
=
452 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
453 session
, url
, MEDIUM
, BoundNetLog());
454 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
455 spdy_stream1
->SetDelegate(&delegate1
);
457 base::WeakPtr
<SpdyStream
> spdy_stream2
=
458 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
459 session
, url
, MEDIUM
, BoundNetLog());
460 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
461 spdy_stream2
->SetDelegate(&delegate2
);
463 scoped_ptr
<SpdyHeaderBlock
> headers(
464 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
465 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
467 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
468 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
469 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
470 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
472 base::RunLoop().RunUntilIdle();
474 EXPECT_EQ(1u, spdy_stream1
->stream_id());
475 EXPECT_EQ(3u, spdy_stream2
->stream_id());
477 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
479 // Read and process the first GOAWAY frame.
481 base::RunLoop().RunUntilIdle();
483 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
485 EXPECT_FALSE(session
->IsStreamActive(3));
486 EXPECT_FALSE(spdy_stream2
);
487 EXPECT_TRUE(session
->IsStreamActive(1));
488 EXPECT_TRUE(session
->IsGoingAway());
490 // Read and process the second GOAWAY frame, which should close the
493 base::RunLoop().RunUntilIdle();
494 EXPECT_FALSE(session
);
497 // Have a session with active streams receive a GOAWAY frame and then
498 // close it. It should handle the close properly (i.e., not try to
499 // make itself unavailable in its pool twice).
500 TEST_P(SpdySessionTest
, GoAwayWithActiveStreamsThenClose
) {
501 session_deps_
.host_resolver
->set_synchronous_mode(true);
503 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
505 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
506 CreateMockRead(*goaway
, 3),
507 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
508 MockRead(ASYNC
, 0, 5) // EOF
510 scoped_ptr
<SpdyFrame
> req1(
511 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
512 scoped_ptr
<SpdyFrame
> req2(
513 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
514 MockWrite writes
[] = {
515 CreateMockWrite(*req1
, 0),
516 CreateMockWrite(*req2
, 1),
518 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
519 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
521 CreateNetworkSession();
523 base::WeakPtr
<SpdySession
> session
=
524 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
526 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
528 GURL
url(kDefaultURL
);
529 base::WeakPtr
<SpdyStream
> spdy_stream1
=
530 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
531 session
, url
, MEDIUM
, BoundNetLog());
532 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
533 spdy_stream1
->SetDelegate(&delegate1
);
535 base::WeakPtr
<SpdyStream
> spdy_stream2
=
536 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
537 session
, url
, MEDIUM
, BoundNetLog());
538 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
539 spdy_stream2
->SetDelegate(&delegate2
);
541 scoped_ptr
<SpdyHeaderBlock
> headers(
542 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
543 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
545 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
546 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
547 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
548 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
550 base::RunLoop().RunUntilIdle();
552 EXPECT_EQ(1u, spdy_stream1
->stream_id());
553 EXPECT_EQ(3u, spdy_stream2
->stream_id());
555 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
557 // Read and process the GOAWAY frame.
559 base::RunLoop().RunUntilIdle();
561 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
563 EXPECT_FALSE(session
->IsStreamActive(3));
564 EXPECT_FALSE(spdy_stream2
);
565 EXPECT_TRUE(session
->IsStreamActive(1));
566 EXPECT_TRUE(session
->IsGoingAway());
568 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
569 EXPECT_FALSE(spdy_stream1
);
572 base::RunLoop().RunUntilIdle();
573 EXPECT_FALSE(session
);
576 // Process a joint read buffer which causes the session to begin draining, and
577 // then processes a GOAWAY. The session should gracefully drain. Regression test
578 // for crbug.com/379469
579 TEST_P(SpdySessionTest
, GoAwayWhileDraining
) {
580 session_deps_
.host_resolver
->set_synchronous_mode(true);
582 scoped_ptr
<SpdyFrame
> req(
583 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
584 MockWrite writes
[] = {
585 CreateMockWrite(*req
, 0),
588 scoped_ptr
<SpdyFrame
> resp(
589 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
590 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
591 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
592 size_t joint_size
= goaway
->size() * 2 + body
->size();
594 // Compose interleaved |goaway| and |body| frames into a single read.
595 scoped_ptr
<char[]> buffer(new char[joint_size
]);
598 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
599 out
+= goaway
->size();
600 memcpy(&buffer
[out
], body
->data(), body
->size());
602 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
603 out
+= goaway
->size();
604 ASSERT_EQ(out
, joint_size
);
606 SpdyFrame
joint_frames(buffer
.get(), joint_size
, false);
609 CreateMockRead(*resp
, 1), CreateMockRead(joint_frames
, 2),
610 MockRead(ASYNC
, 0, 3) // EOF
613 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
614 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
616 CreateNetworkSession();
617 base::WeakPtr
<SpdySession
> session
=
618 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
620 GURL
url(kDefaultURL
);
621 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
622 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
623 test::StreamDelegateDoNothing
delegate(spdy_stream
);
624 spdy_stream
->SetDelegate(&delegate
);
626 scoped_ptr
<SpdyHeaderBlock
> headers(
627 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
628 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
629 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
631 base::RunLoop().RunUntilIdle();
633 // Stream and session closed gracefully.
634 EXPECT_TRUE(delegate
.StreamIsClosed());
635 EXPECT_EQ(OK
, delegate
.WaitForClose());
636 EXPECT_EQ(kUploadData
, delegate
.TakeReceivedData());
637 EXPECT_FALSE(session
);
640 // Try to create a stream after receiving a GOAWAY frame. It should
642 TEST_P(SpdySessionTest
, CreateStreamAfterGoAway
) {
643 session_deps_
.host_resolver
->set_synchronous_mode(true);
645 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
647 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
648 CreateMockRead(*goaway
, 2),
649 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
650 MockRead(ASYNC
, 0, 4) // EOF
652 scoped_ptr
<SpdyFrame
> req(
653 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
654 MockWrite writes
[] = {
655 CreateMockWrite(*req
, 0),
657 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
658 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
660 CreateNetworkSession();
662 base::WeakPtr
<SpdySession
> session
=
663 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
665 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
667 GURL
url(kDefaultURL
);
668 base::WeakPtr
<SpdyStream
> spdy_stream
=
669 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
670 session
, url
, MEDIUM
, BoundNetLog());
671 test::StreamDelegateDoNothing
delegate(spdy_stream
);
672 spdy_stream
->SetDelegate(&delegate
);
674 scoped_ptr
<SpdyHeaderBlock
> headers(
675 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
676 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
677 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
679 base::RunLoop().RunUntilIdle();
681 EXPECT_EQ(1u, spdy_stream
->stream_id());
683 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
685 // Read and process the GOAWAY frame.
687 base::RunLoop().RunUntilIdle();
689 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
690 EXPECT_TRUE(session
->IsStreamActive(1));
692 SpdyStreamRequest stream_request
;
693 int rv
= stream_request
.StartRequest(
694 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog(),
695 CompletionCallback());
696 EXPECT_EQ(ERR_FAILED
, rv
);
698 EXPECT_TRUE(session
);
700 base::RunLoop().RunUntilIdle();
701 EXPECT_FALSE(session
);
704 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
705 // the stream being refused.
706 TEST_P(SpdySessionTest
, SynStreamAfterGoAway
) {
707 session_deps_
.host_resolver
->set_synchronous_mode(true);
709 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
710 scoped_ptr
<SpdyFrame
> push(
711 spdy_util_
.ConstructSpdyPush(nullptr, 0, 2, 1, kDefaultURL
));
713 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
714 CreateMockRead(*goaway
, 2),
715 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
716 CreateMockRead(*push
, 4),
717 MockRead(ASYNC
, 0, 6) // EOF
719 scoped_ptr
<SpdyFrame
> req(
720 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
721 scoped_ptr
<SpdyFrame
> rst(
722 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
723 MockWrite writes
[] = {CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5)};
724 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
725 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
727 CreateNetworkSession();
729 base::WeakPtr
<SpdySession
> session
=
730 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
732 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
734 GURL
url(kDefaultURL
);
735 base::WeakPtr
<SpdyStream
> spdy_stream
=
736 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
737 session
, url
, MEDIUM
, BoundNetLog());
738 test::StreamDelegateDoNothing
delegate(spdy_stream
);
739 spdy_stream
->SetDelegate(&delegate
);
741 scoped_ptr
<SpdyHeaderBlock
> headers(
742 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
743 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
744 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
746 base::RunLoop().RunUntilIdle();
748 EXPECT_EQ(1u, spdy_stream
->stream_id());
750 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
752 // Read and process the GOAWAY frame.
754 base::RunLoop().RunUntilIdle();
756 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
757 EXPECT_TRUE(session
->IsStreamActive(1));
759 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
762 base::RunLoop().RunUntilIdle();
763 EXPECT_FALSE(session
);
766 // A session observing a network change with active streams should close
767 // when the last active stream is closed.
768 TEST_P(SpdySessionTest
, NetworkChangeWithActiveStreams
) {
769 session_deps_
.host_resolver
->set_synchronous_mode(true);
772 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
774 scoped_ptr
<SpdyFrame
> req1(
775 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
776 MockWrite writes
[] = {
777 CreateMockWrite(*req1
, 0),
779 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
780 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
782 CreateNetworkSession();
784 base::WeakPtr
<SpdySession
> session
=
785 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
787 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
789 base::WeakPtr
<SpdyStream
> spdy_stream
=
790 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
, session
,
791 GURL(kDefaultURL
), MEDIUM
, BoundNetLog());
792 test::StreamDelegateDoNothing
delegate(spdy_stream
);
793 spdy_stream
->SetDelegate(&delegate
);
795 scoped_ptr
<SpdyHeaderBlock
> headers(
796 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
798 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
799 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
801 base::RunLoop().RunUntilIdle();
803 EXPECT_EQ(1u, spdy_stream
->stream_id());
805 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
807 spdy_session_pool_
->OnIPAddressChanged();
809 // The SpdySessionPool behavior differs based on how the OSs reacts to
810 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
811 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
812 // For OSs where the TCP connections will close upon relevant network
813 // changes, SpdySessionPool doesn't need to force them to close, so in these
814 // cases verify the session has become unavailable but remains open and the
815 // pre-existing stream is still active.
816 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
818 EXPECT_TRUE(session
->IsGoingAway());
820 EXPECT_TRUE(session
->IsStreamActive(1));
822 // Should close the session.
823 spdy_stream
->Close();
825 EXPECT_FALSE(spdy_stream
);
828 base::RunLoop().RunUntilIdle();
829 EXPECT_FALSE(session
);
832 TEST_P(SpdySessionTest
, ClientPing
) {
833 session_deps_
.enable_ping
= true;
834 session_deps_
.host_resolver
->set_synchronous_mode(true);
836 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(1, true));
838 CreateMockRead(*read_ping
, 1),
839 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
840 MockRead(ASYNC
, 0, 3) // EOF
842 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
843 MockWrite writes
[] = {
844 CreateMockWrite(*write_ping
, 0),
846 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
847 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
849 CreateNetworkSession();
851 base::WeakPtr
<SpdySession
> session
=
852 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
854 base::WeakPtr
<SpdyStream
> spdy_stream1
=
855 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
856 session
, test_url_
, MEDIUM
, BoundNetLog());
857 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
858 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
859 spdy_stream1
->SetDelegate(&delegate
);
861 base::TimeTicks before_ping_time
= base::TimeTicks::Now();
863 session
->set_connection_at_risk_of_loss_time(
864 base::TimeDelta::FromSeconds(-1));
865 session
->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
867 session
->SendPrefacePingIfNoneInFlight();
869 base::RunLoop().RunUntilIdle();
871 session
->CheckPingStatus(before_ping_time
);
873 EXPECT_EQ(0, session
->pings_in_flight());
874 EXPECT_GE(session
->next_ping_id(), 1U);
875 EXPECT_FALSE(session
->check_ping_status_pending());
876 EXPECT_GE(session
->last_activity_time(), before_ping_time
);
879 base::RunLoop().RunUntilIdle();
881 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
883 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
884 EXPECT_FALSE(session
);
887 TEST_P(SpdySessionTest
, ServerPing
) {
888 session_deps_
.host_resolver
->set_synchronous_mode(true);
890 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(2, false));
892 CreateMockRead(*read_ping
),
893 MockRead(SYNCHRONOUS
, 0, 0) // EOF
895 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(2, true));
896 MockWrite writes
[] = {
897 CreateMockWrite(*write_ping
),
899 StaticSocketDataProvider
data(
900 reads
, arraysize(reads
), writes
, arraysize(writes
));
901 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
903 CreateNetworkSession();
905 base::WeakPtr
<SpdySession
> session
=
906 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
908 base::WeakPtr
<SpdyStream
> spdy_stream1
=
909 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
910 session
, test_url_
, MEDIUM
, BoundNetLog());
911 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
912 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
913 spdy_stream1
->SetDelegate(&delegate
);
915 // Flush the read completion task.
916 base::RunLoop().RunUntilIdle();
918 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
920 EXPECT_FALSE(session
);
921 EXPECT_FALSE(spdy_stream1
);
924 // Cause a ping to be sent out while producing a write. The write loop
925 // should handle this properly, i.e. another DoWriteLoop task should
926 // not be posted. This is a regression test for
927 // http://crbug.com/261043 .
928 TEST_P(SpdySessionTest
, PingAndWriteLoop
) {
929 session_deps_
.enable_ping
= true;
930 session_deps_
.time_func
= TheNearFuture
;
932 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
933 scoped_ptr
<SpdyFrame
> req(
934 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
935 MockWrite writes
[] = {
936 CreateMockWrite(*req
, 0),
937 CreateMockWrite(*write_ping
, 1),
941 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
944 session_deps_
.host_resolver
->set_synchronous_mode(true);
946 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
947 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
949 CreateNetworkSession();
951 base::WeakPtr
<SpdySession
> session
=
952 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
954 GURL
url(kDefaultURL
);
955 base::WeakPtr
<SpdyStream
> spdy_stream
=
956 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
957 session
, url
, LOWEST
, BoundNetLog());
958 test::StreamDelegateDoNothing
delegate(spdy_stream
);
959 spdy_stream
->SetDelegate(&delegate
);
961 scoped_ptr
<SpdyHeaderBlock
> headers(
962 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
963 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
965 // Shift time so that a ping will be sent out.
966 g_time_delta
= base::TimeDelta::FromSeconds(11);
968 base::RunLoop().RunUntilIdle();
969 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting");
972 base::RunLoop().RunUntilIdle();
973 EXPECT_FALSE(session
);
976 TEST_P(SpdySessionTest
, StreamIdSpaceExhausted
) {
977 const SpdyStreamId kLastStreamId
= 0x7fffffff;
978 session_deps_
.host_resolver
->set_synchronous_mode(true);
980 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
981 // fixed to allow for two stream ID assignments, and three concurrent
982 // streams. Four streams are started, and two are activated. Verify the
983 // session goes away, and that the created (but not activated) and
984 // stalled streams are aborted. Also verify the activated streams complete,
985 // at which point the session closes.
987 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyGet(
988 nullptr, 0, false, kLastStreamId
- 2, MEDIUM
, true));
989 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyGet(
990 nullptr, 0, false, kLastStreamId
, MEDIUM
, true));
992 MockWrite writes
[] = {
993 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
996 scoped_ptr
<SpdyFrame
> resp1(
997 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId
- 2));
998 scoped_ptr
<SpdyFrame
> resp2(
999 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId
));
1001 scoped_ptr
<SpdyFrame
> body1(
1002 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
- 2, true));
1003 scoped_ptr
<SpdyFrame
> body2(
1004 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
, true));
1006 MockRead reads
[] = {
1007 CreateMockRead(*resp1
, 2),
1008 CreateMockRead(*resp2
, 3),
1009 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
1010 CreateMockRead(*body1
, 5),
1011 CreateMockRead(*body2
, 6),
1012 MockRead(ASYNC
, 0, 7) // EOF
1015 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1016 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1018 CreateNetworkSession();
1019 base::WeakPtr
<SpdySession
> session
=
1020 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1022 // Fix stream_hi_water_mark_ to allow for two stream activations.
1023 session
->stream_hi_water_mark_
= kLastStreamId
- 2;
1024 // Fix max_concurrent_streams to allow for three stream creations.
1025 session
->max_concurrent_streams_
= 3;
1027 // Create three streams synchronously, and begin a fourth (which is stalled).
1028 GURL
url(kDefaultURL
);
1029 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
1030 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1031 test::StreamDelegateDoNothing
delegate1(stream1
);
1032 stream1
->SetDelegate(&delegate1
);
1034 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
1035 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1036 test::StreamDelegateDoNothing
delegate2(stream2
);
1037 stream2
->SetDelegate(&delegate2
);
1039 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
1040 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1041 test::StreamDelegateDoNothing
delegate3(stream3
);
1042 stream3
->SetDelegate(&delegate3
);
1044 SpdyStreamRequest request4
;
1045 TestCompletionCallback callback4
;
1046 EXPECT_EQ(ERR_IO_PENDING
,
1047 request4
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
,
1052 callback4
.callback()));
1054 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1055 EXPECT_EQ(0u, session
->num_active_streams());
1056 EXPECT_EQ(3u, session
->num_created_streams());
1057 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1059 // Activate stream 1. One ID remains available.
1060 stream1
->SendRequestHeaders(
1061 scoped_ptr
<SpdyHeaderBlock
>(
1062 spdy_util_
.ConstructGetHeaderBlock(url
.spec())),
1063 NO_MORE_DATA_TO_SEND
);
1064 base::RunLoop().RunUntilIdle();
1066 EXPECT_EQ(kLastStreamId
- 2u, stream1
->stream_id());
1067 EXPECT_EQ(1u, session
->num_active_streams());
1068 EXPECT_EQ(2u, session
->num_created_streams());
1069 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1071 // Activate stream 2. ID space is exhausted.
1072 stream2
->SendRequestHeaders(
1073 scoped_ptr
<SpdyHeaderBlock
>(
1074 spdy_util_
.ConstructGetHeaderBlock(url
.spec())),
1075 NO_MORE_DATA_TO_SEND
);
1076 base::RunLoop().RunUntilIdle();
1078 // Active streams remain active.
1079 EXPECT_EQ(kLastStreamId
, stream2
->stream_id());
1080 EXPECT_EQ(2u, session
->num_active_streams());
1082 // Session is going away. Created and stalled streams were aborted.
1083 EXPECT_EQ(SpdySession::STATE_GOING_AWAY
, session
->availability_state_
);
1084 EXPECT_EQ(ERR_ABORTED
, delegate3
.WaitForClose());
1085 EXPECT_EQ(ERR_ABORTED
, callback4
.WaitForResult());
1086 EXPECT_EQ(0u, session
->num_created_streams());
1087 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1089 // Read responses on remaining active streams.
1090 data
.CompleteRead();
1091 base::RunLoop().RunUntilIdle();
1092 EXPECT_EQ(OK
, delegate1
.WaitForClose());
1093 EXPECT_EQ(kUploadData
, delegate1
.TakeReceivedData());
1094 EXPECT_EQ(OK
, delegate2
.WaitForClose());
1095 EXPECT_EQ(kUploadData
, delegate2
.TakeReceivedData());
1097 // Session was destroyed.
1098 EXPECT_FALSE(session
);
1101 // Verifies that an unstalled pending stream creation racing with a new stream
1102 // creation doesn't violate the maximum stream concurrency. Regression test for
1103 // crbug.com/373858.
1104 TEST_P(SpdySessionTest
, UnstallRacesWithStreamCreation
) {
1105 session_deps_
.host_resolver
->set_synchronous_mode(true);
1107 MockRead reads
[] = {
1108 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1111 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1112 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1114 CreateNetworkSession();
1115 base::WeakPtr
<SpdySession
> session
=
1116 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1118 // Fix max_concurrent_streams to allow for one open stream.
1119 session
->max_concurrent_streams_
= 1;
1121 // Create two streams: one synchronously, and one which stalls.
1122 GURL
url(kDefaultURL
);
1123 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
1124 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1126 SpdyStreamRequest request2
;
1127 TestCompletionCallback callback2
;
1128 EXPECT_EQ(ERR_IO_PENDING
,
1129 request2
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
,
1134 callback2
.callback()));
1136 EXPECT_EQ(1u, session
->num_created_streams());
1137 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1139 // Cancel the first stream. A callback to unstall the second stream was
1140 // posted. Don't run it yet.
1143 EXPECT_EQ(0u, session
->num_created_streams());
1144 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1146 // Create a third stream prior to the second stream's callback.
1147 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
1148 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1150 EXPECT_EQ(1u, session
->num_created_streams());
1151 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1153 // Now run the message loop. The unstalled stream will re-stall itself.
1154 base::RunLoop().RunUntilIdle();
1155 EXPECT_EQ(1u, session
->num_created_streams());
1156 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1158 // Cancel the third stream and run the message loop. Verify that the second
1159 // stream creation now completes.
1161 base::RunLoop().RunUntilIdle();
1163 EXPECT_EQ(1u, session
->num_created_streams());
1164 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1165 EXPECT_EQ(OK
, callback2
.WaitForResult());
1168 TEST_P(SpdySessionTest
, DeleteExpiredPushStreams
) {
1169 session_deps_
.host_resolver
->set_synchronous_mode(true);
1170 session_deps_
.time_func
= TheNearFuture
;
1172 scoped_ptr
<SpdyFrame
> req(
1173 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
1174 scoped_ptr
<SpdyFrame
> rst(
1175 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
1176 MockWrite writes
[] = {CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5)};
1178 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
1179 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
1180 scoped_ptr
<SpdyFrame
> push_a_body(
1181 spdy_util_
.ConstructSpdyBodyFrame(2, false));
1182 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1183 // iterators inside. See http://crbug.com/443490
1184 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
1185 nullptr, 0, 4, 1, "http://www.example.org/0.dat"));
1186 MockRead reads
[] = {
1187 CreateMockRead(*push_a
, 1),
1188 CreateMockRead(*push_a_body
, 2),
1189 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
1190 CreateMockRead(*push_b
, 4),
1191 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
1192 MockRead(ASYNC
, 0, 7) // EOF
1195 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1196 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1198 CreateNetworkSession();
1199 base::WeakPtr
<SpdySession
> session
=
1200 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1202 // Process the principal request, and the first push stream request & body.
1203 GURL
url(kDefaultURL
);
1204 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1205 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1206 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1207 spdy_stream
->SetDelegate(&delegate
);
1209 scoped_ptr
<SpdyHeaderBlock
> headers(
1210 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1211 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1213 base::RunLoop().RunUntilIdle();
1215 // Verify that there is one unclaimed push stream.
1216 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
1217 SpdySession::PushedStreamMap::iterator iter
=
1218 session
->unclaimed_pushed_streams_
.find(
1219 GURL("http://www.example.org/a.dat"));
1220 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
1222 if (session
->flow_control_state_
==
1223 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1224 // Unclaimed push body consumed bytes from the session window.
1226 SpdySession::GetDefaultInitialWindowSize(GetParam()) - kUploadDataSize
,
1227 session
->session_recv_window_size_
);
1228 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
1231 // Shift time to expire the push stream. Read the second SYN_STREAM,
1232 // and verify a RST_STREAM was written.
1233 g_time_delta
= base::TimeDelta::FromSeconds(301);
1234 data
.CompleteRead();
1235 base::RunLoop().RunUntilIdle();
1237 // Verify that the second pushed stream evicted the first pushed stream.
1238 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
1239 iter
= session
->unclaimed_pushed_streams_
.find(
1240 GURL("http://www.example.org/0.dat"));
1241 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
1243 if (session
->flow_control_state_
==
1244 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1245 // Verify that the session window reclaimed the evicted stream body.
1246 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
1247 session
->session_recv_window_size_
);
1248 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
1251 // Read and process EOF.
1252 EXPECT_TRUE(session
);
1253 data
.CompleteRead();
1254 base::RunLoop().RunUntilIdle();
1255 EXPECT_FALSE(session
);
1258 TEST_P(SpdySessionTest
, FailedPing
) {
1259 session_deps_
.host_resolver
->set_synchronous_mode(true);
1261 MockRead reads
[] = {
1262 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1264 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
1265 scoped_ptr
<SpdyFrame
> goaway(
1266 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Failed ping."));
1267 MockWrite writes
[] = {CreateMockWrite(*write_ping
), CreateMockWrite(*goaway
)};
1269 StaticSocketDataProvider
data(
1270 reads
, arraysize(reads
), writes
, arraysize(writes
));
1271 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1273 CreateNetworkSession();
1275 base::WeakPtr
<SpdySession
> session
=
1276 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1278 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1279 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1280 session
, test_url_
, MEDIUM
, BoundNetLog());
1281 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1282 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
1283 spdy_stream1
->SetDelegate(&delegate
);
1285 session
->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1286 session
->set_hung_interval(base::TimeDelta::FromSeconds(0));
1288 // Send a PING frame.
1289 session
->WritePingFrame(1, false);
1290 EXPECT_LT(0, session
->pings_in_flight());
1291 EXPECT_GE(session
->next_ping_id(), 1U);
1292 EXPECT_TRUE(session
->check_ping_status_pending());
1294 // Assert session is not closed.
1295 EXPECT_TRUE(session
->IsAvailable());
1296 EXPECT_LT(0u, session
->num_active_streams() + session
->num_created_streams());
1297 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1299 // We set last time we have received any data in 1 sec less than now.
1300 // CheckPingStatus will trigger timeout because hung interval is zero.
1301 base::TimeTicks now
= base::TimeTicks::Now();
1302 session
->last_activity_time_
= now
- base::TimeDelta::FromSeconds(1);
1303 session
->CheckPingStatus(now
);
1304 base::RunLoop().RunUntilIdle();
1306 EXPECT_FALSE(session
);
1307 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1308 EXPECT_FALSE(spdy_stream1
);
1311 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1312 // settings frame increasing the max concurrent streams by 1. Make
1313 // sure nothing blows up. This is a regression test for
1314 // http://crbug.com/57331 .
1315 TEST_P(SpdySessionTest
, OnSettings
) {
1316 session_deps_
.host_resolver
->set_synchronous_mode(true);
1318 const SpdySettingsIds kSpdySettingsIds
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1321 std::vector
<MockWrite
> writes
;
1322 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1323 if (GetParam() >= kProtoHTTP2MinimumVersion
) {
1324 writes
.push_back(CreateMockWrite(*settings_ack
, ++seq
));
1327 SettingsMap new_settings
;
1328 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1329 new_settings
[kSpdySettingsIds
] =
1330 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1331 scoped_ptr
<SpdyFrame
> settings_frame(
1332 spdy_util_
.ConstructSpdySettings(new_settings
));
1333 MockRead reads
[] = {
1334 CreateMockRead(*settings_frame
, 0),
1335 MockRead(ASYNC
, ERR_IO_PENDING
, ++seq
),
1336 MockRead(ASYNC
, 0, ++seq
),
1339 SequencedSocketData
data(reads
, arraysize(reads
), vector_as_array(&writes
),
1341 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1343 CreateNetworkSession();
1345 base::WeakPtr
<SpdySession
> session
=
1346 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1348 // Create the maximum number of concurrent streams.
1349 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1350 base::WeakPtr
<SpdyStream
> spdy_stream
=
1351 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1352 session
, test_url_
, MEDIUM
, BoundNetLog());
1353 ASSERT_TRUE(spdy_stream
!= nullptr);
1356 StreamReleaserCallback stream_releaser
;
1357 SpdyStreamRequest request
;
1358 ASSERT_EQ(ERR_IO_PENDING
,
1359 request
.StartRequest(
1360 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1362 stream_releaser
.MakeCallback(&request
)));
1364 base::RunLoop().RunUntilIdle();
1366 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1368 data
.CompleteRead();
1369 base::RunLoop().RunUntilIdle();
1370 EXPECT_FALSE(session
);
1372 EXPECT_TRUE(data
.AllWriteDataConsumed());
1373 EXPECT_TRUE(data
.AllReadDataConsumed());
1376 // Start with a persisted value for max concurrent streams. Receive a
1377 // settings frame increasing the max concurrent streams by 1 and which
1378 // also clears the persisted data. Verify that persisted data is
1380 TEST_P(SpdySessionTest
, ClearSettings
) {
1381 if (spdy_util_
.spdy_version() >= HTTP2
) {
1382 // HTTP/2 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1383 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in HTTP/2.
1386 session_deps_
.host_resolver
->set_synchronous_mode(true);
1388 SettingsMap new_settings
;
1389 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1390 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1391 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1392 scoped_ptr
<SpdyFrame
> settings_frame(
1393 spdy_util_
.ConstructSpdySettings(new_settings
));
1394 uint8 flags
= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
1395 test::SetFrameFlags(settings_frame
.get(), flags
, spdy_util_
.spdy_version());
1396 MockRead reads
[] = {
1397 CreateMockRead(*settings_frame
, 0),
1398 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
1399 MockRead(ASYNC
, 0, 2),
1402 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
1403 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1405 CreateNetworkSession();
1407 // Initialize the SpdySetting with the default.
1408 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1409 test_host_port_pair_
,
1410 SETTINGS_MAX_CONCURRENT_STREAMS
,
1411 SETTINGS_FLAG_PLEASE_PERSIST
,
1412 kInitialMaxConcurrentStreams
);
1415 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1416 test_host_port_pair_
).empty());
1418 base::WeakPtr
<SpdySession
> session
=
1419 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1421 // Create the maximum number of concurrent streams.
1422 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1423 base::WeakPtr
<SpdyStream
> spdy_stream
=
1424 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1425 session
, test_url_
, MEDIUM
, BoundNetLog());
1426 ASSERT_TRUE(spdy_stream
!= nullptr);
1429 StreamReleaserCallback stream_releaser
;
1431 SpdyStreamRequest request
;
1432 ASSERT_EQ(ERR_IO_PENDING
,
1433 request
.StartRequest(
1434 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1436 stream_releaser
.MakeCallback(&request
)));
1438 base::RunLoop().RunUntilIdle();
1440 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1442 // Make sure that persisted data is cleared.
1444 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1445 test_host_port_pair_
).empty());
1447 // Make sure session's max_concurrent_streams is correct.
1448 EXPECT_EQ(kInitialMaxConcurrentStreams
+ 1,
1449 session
->max_concurrent_streams());
1451 data
.CompleteRead();
1452 base::RunLoop().RunUntilIdle();
1453 EXPECT_FALSE(session
);
1456 // Start with max concurrent streams set to 1. Request two streams.
1457 // When the first completes, have the callback close its stream, which
1458 // should trigger the second stream creation. Then cancel that one
1459 // immediately. Don't crash. This is a regression test for
1460 // http://crbug.com/63532 .
1461 TEST_P(SpdySessionTest
, CancelPendingCreateStream
) {
1462 session_deps_
.host_resolver
->set_synchronous_mode(true);
1464 MockRead reads
[] = {
1465 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1468 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1469 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1471 CreateNetworkSession();
1473 // Initialize the SpdySetting with 1 max concurrent streams.
1474 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1475 test_host_port_pair_
,
1476 SETTINGS_MAX_CONCURRENT_STREAMS
,
1477 SETTINGS_FLAG_PLEASE_PERSIST
,
1480 base::WeakPtr
<SpdySession
> session
=
1481 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1483 // Leave room for only one more stream to be created.
1484 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
1485 base::WeakPtr
<SpdyStream
> spdy_stream
=
1486 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1487 session
, test_url_
, MEDIUM
, BoundNetLog());
1488 ASSERT_TRUE(spdy_stream
!= nullptr);
1491 // Create 2 more streams. First will succeed. Second will be pending.
1492 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1493 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1494 session
, test_url_
, MEDIUM
, BoundNetLog());
1495 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1497 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1498 // a valgrind error if the callback is invoked when it's not supposed to be.
1499 scoped_ptr
<TestCompletionCallback
> callback(new TestCompletionCallback
);
1501 SpdyStreamRequest request
;
1502 ASSERT_EQ(ERR_IO_PENDING
,
1503 request
.StartRequest(
1504 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1506 callback
->callback()));
1508 // Release the first one, this will allow the second to be created.
1509 spdy_stream1
->Cancel();
1510 EXPECT_FALSE(spdy_stream1
);
1512 request
.CancelRequest();
1515 // Should not crash when running the pending callback.
1516 base::RunLoop().RunUntilIdle();
1519 TEST_P(SpdySessionTest
, SendInitialDataOnNewSession
) {
1520 session_deps_
.host_resolver
->set_synchronous_mode(true);
1522 MockRead reads
[] = {
1523 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1526 SettingsMap settings
;
1527 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1528 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
1529 scoped_ptr
<SpdyFrame
> settings_frame(
1530 spdy_util_
.ConstructSpdySettings(settings
));
1531 std::vector
<MockWrite
> writes
;
1532 if ((GetParam() >= kProtoHTTP2MinimumVersion
) &&
1533 (GetParam() <= kProtoHTTP2MaximumVersion
)) {
1536 kHttp2ConnectionHeaderPrefix
,
1537 kHttp2ConnectionHeaderPrefixSize
));
1539 writes
.push_back(CreateMockWrite(*settings_frame
));
1541 SettingsMap server_settings
;
1542 const uint32 initial_max_concurrent_streams
= 1;
1543 server_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1544 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED
,
1545 initial_max_concurrent_streams
);
1546 scoped_ptr
<SpdyFrame
> server_settings_frame(
1547 spdy_util_
.ConstructSpdySettings(server_settings
));
1548 if (GetParam() <= kProtoSPDY31
) {
1549 writes
.push_back(CreateMockWrite(*server_settings_frame
));
1552 StaticSocketDataProvider
data(reads
, arraysize(reads
),
1553 vector_as_array(&writes
), writes
.size());
1554 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1556 CreateNetworkSession();
1558 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1559 test_host_port_pair_
,
1560 SETTINGS_MAX_CONCURRENT_STREAMS
,
1561 SETTINGS_FLAG_PLEASE_PERSIST
,
1562 initial_max_concurrent_streams
);
1564 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
1565 pool_peer
.SetEnableSendingInitialData(true);
1567 base::WeakPtr
<SpdySession
> session
=
1568 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1570 base::RunLoop().RunUntilIdle();
1571 EXPECT_TRUE(data
.AllWriteDataConsumed());
1574 TEST_P(SpdySessionTest
, ClearSettingsStorageOnIPAddressChanged
) {
1575 CreateNetworkSession();
1577 base::WeakPtr
<HttpServerProperties
> test_http_server_properties
=
1578 spdy_session_pool_
->http_server_properties();
1579 SettingsFlagsAndValue
flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST
, 2);
1580 test_http_server_properties
->SetSpdySetting(
1581 test_host_port_pair_
,
1582 SETTINGS_MAX_CONCURRENT_STREAMS
,
1583 SETTINGS_FLAG_PLEASE_PERSIST
,
1585 EXPECT_NE(0u, test_http_server_properties
->GetSpdySettings(
1586 test_host_port_pair_
).size());
1587 spdy_session_pool_
->OnIPAddressChanged();
1588 EXPECT_EQ(0u, test_http_server_properties
->GetSpdySettings(
1589 test_host_port_pair_
).size());
1592 TEST_P(SpdySessionTest
, Initialize
) {
1593 BoundTestNetLog log
;
1594 session_deps_
.net_log
= log
.bound().net_log();
1595 session_deps_
.host_resolver
->set_synchronous_mode(true);
1597 MockRead reads
[] = {
1598 MockRead(ASYNC
, 0, 0) // EOF
1601 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1602 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1604 CreateNetworkSession();
1606 base::WeakPtr
<SpdySession
> session
=
1607 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1608 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1610 // Flush the read completion task.
1611 base::RunLoop().RunUntilIdle();
1613 TestNetLogEntry::List entries
;
1614 log
.GetEntries(&entries
);
1615 EXPECT_LT(0u, entries
.size());
1617 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1618 int pos
= ExpectLogContainsSomewhere(
1619 entries
, 0, NetLog::TYPE_HTTP2_SESSION_INITIALIZED
, NetLog::PHASE_NONE
);
1622 TestNetLogEntry entry
= entries
[pos
];
1623 NetLog::Source socket_source
;
1624 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry
.params
.get(),
1626 EXPECT_TRUE(socket_source
.IsValid());
1627 EXPECT_NE(log
.bound().source().id
, socket_source
.id
);
1630 TEST_P(SpdySessionTest
, NetLogOnSessionGoaway
) {
1631 session_deps_
.host_resolver
->set_synchronous_mode(true);
1633 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
1634 MockRead reads
[] = {
1635 CreateMockRead(*goaway
),
1636 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1639 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1640 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1642 CreateNetworkSession();
1644 BoundTestNetLog log
;
1645 base::WeakPtr
<SpdySession
> session
=
1646 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1647 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1649 // Flush the read completion task.
1650 base::RunLoop().RunUntilIdle();
1652 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1653 EXPECT_FALSE(session
);
1655 // Check that the NetLog was filled reasonably.
1656 TestNetLogEntry::List entries
;
1657 log
.GetEntries(&entries
);
1658 EXPECT_LT(0u, entries
.size());
1660 // Check that we logged SPDY_SESSION_CLOSE correctly.
1661 int pos
= ExpectLogContainsSomewhere(
1662 entries
, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE
, NetLog::PHASE_NONE
);
1664 if (pos
< static_cast<int>(entries
.size())) {
1665 TestNetLogEntry entry
= entries
[pos
];
1667 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1668 EXPECT_EQ(OK
, error_code
);
1674 TEST_P(SpdySessionTest
, NetLogOnSessionEOF
) {
1675 session_deps_
.host_resolver
->set_synchronous_mode(true);
1677 MockRead reads
[] = {
1678 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1681 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1682 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1684 CreateNetworkSession();
1686 BoundTestNetLog log
;
1687 base::WeakPtr
<SpdySession
> session
=
1688 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1689 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1691 // Flush the read completion task.
1692 base::RunLoop().RunUntilIdle();
1694 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1695 EXPECT_FALSE(session
);
1697 // Check that the NetLog was filled reasonably.
1698 TestNetLogEntry::List entries
;
1699 log
.GetEntries(&entries
);
1700 EXPECT_LT(0u, entries
.size());
1702 // Check that we logged SPDY_SESSION_CLOSE correctly.
1703 int pos
= ExpectLogContainsSomewhere(
1704 entries
, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE
, NetLog::PHASE_NONE
);
1706 if (pos
< static_cast<int>(entries
.size())) {
1707 TestNetLogEntry entry
= entries
[pos
];
1709 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1710 EXPECT_EQ(ERR_CONNECTION_CLOSED
, error_code
);
1716 TEST_P(SpdySessionTest
, SynCompressionHistograms
) {
1717 session_deps_
.enable_compression
= true;
1719 scoped_ptr
<SpdyFrame
> req(
1720 spdy_util_
.ConstructSpdyGet(nullptr, 0, true, 1, MEDIUM
, true));
1721 MockWrite writes
[] = {
1722 CreateMockWrite(*req
, 0),
1724 MockRead reads
[] = {
1725 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
1727 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1728 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1730 CreateNetworkSession();
1731 base::WeakPtr
<SpdySession
> session
=
1732 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1734 GURL
url(kDefaultURL
);
1735 base::WeakPtr
<SpdyStream
> spdy_stream
=
1736 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1737 session
, url
, MEDIUM
, BoundNetLog());
1738 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1739 spdy_stream
->SetDelegate(&delegate
);
1741 scoped_ptr
<SpdyHeaderBlock
> headers(
1742 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1743 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1744 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
1746 // Write request headers & capture resulting histogram update.
1747 base::HistogramTester histogram_tester
;
1749 base::RunLoop().RunUntilIdle();
1750 // Regression test of compression performance under the request fixture.
1751 switch (spdy_util_
.spdy_version()) {
1753 histogram_tester
.ExpectBucketCount(
1754 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1757 histogram_tester
.ExpectBucketCount(
1758 "Net.SpdySynStreamCompressionPercentage", 81, 1);
1764 // Read and process EOF.
1765 EXPECT_TRUE(session
);
1766 data
.CompleteRead();
1767 base::RunLoop().RunUntilIdle();
1768 EXPECT_FALSE(session
);
1771 // Queue up a low-priority SYN_STREAM followed by a high-priority
1772 // one. The high priority one should still send first and receive
1774 TEST_P(SpdySessionTest
, OutOfOrderSynStreams
) {
1775 // Construct the request.
1776 scoped_ptr
<SpdyFrame
> req_highest(
1777 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, HIGHEST
, true));
1778 scoped_ptr
<SpdyFrame
> req_lowest(
1779 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST
, true));
1780 MockWrite writes
[] = {
1781 CreateMockWrite(*req_highest
, 0),
1782 CreateMockWrite(*req_lowest
, 1),
1785 scoped_ptr
<SpdyFrame
> resp_highest(
1786 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
1787 scoped_ptr
<SpdyFrame
> body_highest(
1788 spdy_util_
.ConstructSpdyBodyFrame(1, true));
1789 scoped_ptr
<SpdyFrame
> resp_lowest(
1790 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
1791 scoped_ptr
<SpdyFrame
> body_lowest(
1792 spdy_util_
.ConstructSpdyBodyFrame(3, true));
1793 MockRead reads
[] = {
1794 CreateMockRead(*resp_highest
, 2),
1795 CreateMockRead(*body_highest
, 3),
1796 CreateMockRead(*resp_lowest
, 4),
1797 CreateMockRead(*body_lowest
, 5),
1798 MockRead(ASYNC
, 0, 6) // EOF
1801 session_deps_
.host_resolver
->set_synchronous_mode(true);
1803 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1804 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1806 CreateNetworkSession();
1808 base::WeakPtr
<SpdySession
> session
=
1809 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1811 GURL
url(kDefaultURL
);
1813 base::WeakPtr
<SpdyStream
> spdy_stream_lowest
=
1814 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1815 session
, url
, LOWEST
, BoundNetLog());
1816 ASSERT_TRUE(spdy_stream_lowest
);
1817 EXPECT_EQ(0u, spdy_stream_lowest
->stream_id());
1818 test::StreamDelegateDoNothing
delegate_lowest(spdy_stream_lowest
);
1819 spdy_stream_lowest
->SetDelegate(&delegate_lowest
);
1821 base::WeakPtr
<SpdyStream
> spdy_stream_highest
=
1822 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1823 session
, url
, HIGHEST
, BoundNetLog());
1824 ASSERT_TRUE(spdy_stream_highest
);
1825 EXPECT_EQ(0u, spdy_stream_highest
->stream_id());
1826 test::StreamDelegateDoNothing
delegate_highest(spdy_stream_highest
);
1827 spdy_stream_highest
->SetDelegate(&delegate_highest
);
1829 // Queue the lower priority one first.
1831 scoped_ptr
<SpdyHeaderBlock
> headers_lowest(
1832 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1833 spdy_stream_lowest
->SendRequestHeaders(
1834 headers_lowest
.Pass(), NO_MORE_DATA_TO_SEND
);
1835 EXPECT_TRUE(spdy_stream_lowest
->HasUrlFromHeaders());
1837 scoped_ptr
<SpdyHeaderBlock
> headers_highest(
1838 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1839 spdy_stream_highest
->SendRequestHeaders(
1840 headers_highest
.Pass(), NO_MORE_DATA_TO_SEND
);
1841 EXPECT_TRUE(spdy_stream_highest
->HasUrlFromHeaders());
1843 base::RunLoop().RunUntilIdle();
1845 EXPECT_FALSE(spdy_stream_lowest
);
1846 EXPECT_FALSE(spdy_stream_highest
);
1847 EXPECT_EQ(3u, delegate_lowest
.stream_id());
1848 EXPECT_EQ(1u, delegate_highest
.stream_id());
1851 TEST_P(SpdySessionTest
, CancelStream
) {
1852 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1853 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1854 scoped_ptr
<SpdyFrame
> req2(
1855 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
1856 MockWrite writes
[] = {
1857 CreateMockWrite(*req2
, 0),
1860 scoped_ptr
<SpdyFrame
> resp2(
1861 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
1862 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1863 MockRead reads
[] = {
1864 CreateMockRead(*resp2
, 1),
1865 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
1866 CreateMockRead(*body2
, 3),
1867 MockRead(ASYNC
, 0, 4) // EOF
1870 session_deps_
.host_resolver
->set_synchronous_mode(true);
1872 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1873 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1875 CreateNetworkSession();
1877 base::WeakPtr
<SpdySession
> session
=
1878 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1880 GURL
url1(kDefaultURL
);
1881 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1882 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1883 session
, url1
, HIGHEST
, BoundNetLog());
1884 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1885 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1886 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
1887 spdy_stream1
->SetDelegate(&delegate1
);
1889 GURL
url2(kDefaultURL
);
1890 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1891 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1892 session
, url2
, LOWEST
, BoundNetLog());
1893 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
1894 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1895 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
1896 spdy_stream2
->SetDelegate(&delegate2
);
1898 scoped_ptr
<SpdyHeaderBlock
> headers(
1899 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1900 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1901 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1903 scoped_ptr
<SpdyHeaderBlock
> headers2(
1904 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1905 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1906 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1908 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1910 spdy_stream1
->Cancel();
1911 EXPECT_FALSE(spdy_stream1
);
1913 EXPECT_EQ(0u, delegate1
.stream_id());
1915 base::RunLoop().RunUntilIdle();
1917 EXPECT_EQ(0u, delegate1
.stream_id());
1918 EXPECT_EQ(1u, delegate2
.stream_id());
1920 spdy_stream2
->Cancel();
1921 EXPECT_FALSE(spdy_stream2
);
1924 // Create two streams that are set to re-close themselves on close,
1925 // and then close the session. Nothing should blow up. Also a
1926 // regression test for http://crbug.com/139518 .
1927 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedSelfClosingStreams
) {
1928 session_deps_
.host_resolver
->set_synchronous_mode(true);
1931 // No actual data will be sent.
1932 MockWrite writes
[] = {
1933 MockWrite(ASYNC
, 0, 1) // EOF
1936 MockRead reads
[] = {
1937 MockRead(ASYNC
, 0, 0) // EOF
1939 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1940 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1942 CreateNetworkSession();
1944 base::WeakPtr
<SpdySession
> session
=
1945 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1947 GURL
url1(kDefaultURL
);
1948 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1949 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1950 session
, url1
, HIGHEST
, BoundNetLog());
1951 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1952 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1954 GURL
url2(kDefaultURL
);
1955 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1956 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1957 session
, url2
, LOWEST
, BoundNetLog());
1958 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
1959 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1961 test::ClosingDelegate
delegate1(spdy_stream1
);
1962 spdy_stream1
->SetDelegate(&delegate1
);
1964 test::ClosingDelegate
delegate2(spdy_stream2
);
1965 spdy_stream2
->SetDelegate(&delegate2
);
1967 scoped_ptr
<SpdyHeaderBlock
> headers(
1968 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1969 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1970 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1972 scoped_ptr
<SpdyHeaderBlock
> headers2(
1973 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1974 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1975 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1977 // Ensure that the streams have not yet been activated and assigned an id.
1978 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1979 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1981 // Ensure we don't crash while closing the session.
1982 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
1984 EXPECT_FALSE(spdy_stream1
);
1985 EXPECT_FALSE(spdy_stream2
);
1987 EXPECT_TRUE(delegate1
.StreamIsClosed());
1988 EXPECT_TRUE(delegate2
.StreamIsClosed());
1990 base::RunLoop().RunUntilIdle();
1991 EXPECT_FALSE(session
);
1994 // Create two streams that are set to close each other on close, and
1995 // then close the session. Nothing should blow up.
1996 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedMutuallyClosingStreams
) {
1997 session_deps_
.host_resolver
->set_synchronous_mode(true);
1999 SequencedSocketData
data(nullptr, 0, nullptr, 0);
2000 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2002 CreateNetworkSession();
2004 base::WeakPtr
<SpdySession
> session
=
2005 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2007 GURL
url1(kDefaultURL
);
2008 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2009 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2010 session
, url1
, HIGHEST
, BoundNetLog());
2011 ASSERT_TRUE(spdy_stream1
);
2012 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2014 GURL
url2(kDefaultURL
);
2015 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2016 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2017 session
, url2
, LOWEST
, BoundNetLog());
2018 ASSERT_TRUE(spdy_stream2
);
2019 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2021 // Make |spdy_stream1| close |spdy_stream2|.
2022 test::ClosingDelegate
delegate1(spdy_stream2
);
2023 spdy_stream1
->SetDelegate(&delegate1
);
2025 // Make |spdy_stream2| close |spdy_stream1|.
2026 test::ClosingDelegate
delegate2(spdy_stream1
);
2027 spdy_stream2
->SetDelegate(&delegate2
);
2029 scoped_ptr
<SpdyHeaderBlock
> headers(
2030 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2031 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2032 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2034 scoped_ptr
<SpdyHeaderBlock
> headers2(
2035 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2036 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2037 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2039 // Ensure that the streams have not yet been activated and assigned an id.
2040 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2041 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2043 // Ensure we don't crash while closing the session.
2044 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2046 EXPECT_FALSE(spdy_stream1
);
2047 EXPECT_FALSE(spdy_stream2
);
2049 EXPECT_TRUE(delegate1
.StreamIsClosed());
2050 EXPECT_TRUE(delegate2
.StreamIsClosed());
2052 base::RunLoop().RunUntilIdle();
2053 EXPECT_FALSE(session
);
2056 // Create two streams that are set to re-close themselves on close,
2057 // activate them, and then close the session. Nothing should blow up.
2058 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedSelfClosingStreams
) {
2059 session_deps_
.host_resolver
->set_synchronous_mode(true);
2061 scoped_ptr
<SpdyFrame
> req1(
2062 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2063 scoped_ptr
<SpdyFrame
> req2(
2064 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
2065 MockWrite writes
[] = {
2066 CreateMockWrite(*req1
, 0),
2067 CreateMockWrite(*req2
, 1),
2070 MockRead reads
[] = {
2071 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
2074 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2075 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2077 CreateNetworkSession();
2079 base::WeakPtr
<SpdySession
> session
=
2080 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2082 GURL
url1(kDefaultURL
);
2083 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2084 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2085 session
, url1
, MEDIUM
, BoundNetLog());
2086 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2087 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2089 GURL
url2(kDefaultURL
);
2090 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2091 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2092 session
, url2
, MEDIUM
, BoundNetLog());
2093 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
2094 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2096 test::ClosingDelegate
delegate1(spdy_stream1
);
2097 spdy_stream1
->SetDelegate(&delegate1
);
2099 test::ClosingDelegate
delegate2(spdy_stream2
);
2100 spdy_stream2
->SetDelegate(&delegate2
);
2102 scoped_ptr
<SpdyHeaderBlock
> headers(
2103 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2104 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2105 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2107 scoped_ptr
<SpdyHeaderBlock
> headers2(
2108 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2109 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2110 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2112 // Ensure that the streams have not yet been activated and assigned an id.
2113 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2114 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2116 base::RunLoop().RunUntilIdle();
2118 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2119 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2121 // Ensure we don't crash while closing the session.
2122 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2124 EXPECT_FALSE(spdy_stream1
);
2125 EXPECT_FALSE(spdy_stream2
);
2127 EXPECT_TRUE(delegate1
.StreamIsClosed());
2128 EXPECT_TRUE(delegate2
.StreamIsClosed());
2130 EXPECT_TRUE(session
);
2131 data
.CompleteRead();
2132 base::RunLoop().RunUntilIdle();
2133 EXPECT_FALSE(session
);
2136 // Create two streams that are set to close each other on close,
2137 // activate them, and then close the session. Nothing should blow up.
2138 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedMutuallyClosingStreams
) {
2139 session_deps_
.host_resolver
->set_synchronous_mode(true);
2141 scoped_ptr
<SpdyFrame
> req1(
2142 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2143 scoped_ptr
<SpdyFrame
> req2(
2144 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
2145 MockWrite writes
[] = {
2146 CreateMockWrite(*req1
, 0),
2147 CreateMockWrite(*req2
, 1),
2150 MockRead reads
[] = {
2151 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
2154 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2155 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2157 CreateNetworkSession();
2159 base::WeakPtr
<SpdySession
> session
=
2160 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2162 GURL
url1(kDefaultURL
);
2163 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2164 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2165 session
, url1
, MEDIUM
, BoundNetLog());
2166 ASSERT_TRUE(spdy_stream1
);
2167 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2169 GURL
url2(kDefaultURL
);
2170 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2171 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2172 session
, url2
, MEDIUM
, BoundNetLog());
2173 ASSERT_TRUE(spdy_stream2
);
2174 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2176 // Make |spdy_stream1| close |spdy_stream2|.
2177 test::ClosingDelegate
delegate1(spdy_stream2
);
2178 spdy_stream1
->SetDelegate(&delegate1
);
2180 // Make |spdy_stream2| close |spdy_stream1|.
2181 test::ClosingDelegate
delegate2(spdy_stream1
);
2182 spdy_stream2
->SetDelegate(&delegate2
);
2184 scoped_ptr
<SpdyHeaderBlock
> headers(
2185 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2186 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2187 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2189 scoped_ptr
<SpdyHeaderBlock
> headers2(
2190 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2191 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2192 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2194 // Ensure that the streams have not yet been activated and assigned an id.
2195 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2196 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2198 base::RunLoop().RunUntilIdle();
2200 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2201 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2203 // Ensure we don't crash while closing the session.
2204 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2206 EXPECT_FALSE(spdy_stream1
);
2207 EXPECT_FALSE(spdy_stream2
);
2209 EXPECT_TRUE(delegate1
.StreamIsClosed());
2210 EXPECT_TRUE(delegate2
.StreamIsClosed());
2212 EXPECT_TRUE(session
);
2213 data
.CompleteRead();
2214 base::RunLoop().RunUntilIdle();
2215 EXPECT_FALSE(session
);
2218 // Delegate that closes a given session when the stream is closed.
2219 class SessionClosingDelegate
: public test::StreamDelegateDoNothing
{
2221 SessionClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
2222 const base::WeakPtr
<SpdySession
>& session_to_close
)
2223 : StreamDelegateDoNothing(stream
),
2224 session_to_close_(session_to_close
) {}
2226 ~SessionClosingDelegate() override
{}
2228 void OnClose(int status
) override
{
2229 session_to_close_
->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR
, "Error");
2233 base::WeakPtr
<SpdySession
> session_to_close_
;
2236 // Close an activated stream that closes its session. Nothing should
2237 // blow up. This is a regression test for https://crbug.com/263691.
2238 TEST_P(SpdySessionTest
, CloseActivatedStreamThatClosesSession
) {
2239 session_deps_
.host_resolver
->set_synchronous_mode(true);
2241 scoped_ptr
<SpdyFrame
> req(
2242 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2243 scoped_ptr
<SpdyFrame
> rst(
2244 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2245 scoped_ptr
<SpdyFrame
> goaway(
2246 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Error"));
2247 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2248 // despite being queued second.
2249 MockWrite writes
[] = {
2250 CreateMockWrite(*req
, 0),
2251 CreateMockWrite(*goaway
, 1),
2252 CreateMockWrite(*rst
, 3),
2255 MockRead reads
[] = {
2256 MockRead(ASYNC
, 0, 2) // EOF
2258 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2259 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2261 CreateNetworkSession();
2263 base::WeakPtr
<SpdySession
> session
=
2264 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2266 GURL
url(kDefaultURL
);
2267 base::WeakPtr
<SpdyStream
> spdy_stream
=
2268 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2269 session
, url
, MEDIUM
, BoundNetLog());
2270 ASSERT_TRUE(spdy_stream
.get() != nullptr);
2271 EXPECT_EQ(0u, spdy_stream
->stream_id());
2273 SessionClosingDelegate
delegate(spdy_stream
, session
);
2274 spdy_stream
->SetDelegate(&delegate
);
2276 scoped_ptr
<SpdyHeaderBlock
> headers(
2277 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
2278 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2279 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
2281 EXPECT_EQ(0u, spdy_stream
->stream_id());
2283 base::RunLoop().RunUntilIdle();
2285 EXPECT_EQ(1u, spdy_stream
->stream_id());
2287 // Ensure we don't crash while closing the stream (which closes the
2289 spdy_stream
->Cancel();
2291 EXPECT_FALSE(spdy_stream
);
2292 EXPECT_TRUE(delegate
.StreamIsClosed());
2294 // Write the RST_STREAM & GOAWAY.
2295 base::RunLoop().RunUntilIdle();
2296 EXPECT_TRUE(data
.AllWriteDataConsumed());
2297 EXPECT_TRUE(data
.AllReadDataConsumed());
2300 TEST_P(SpdySessionTest
, VerifyDomainAuthentication
) {
2301 session_deps_
.host_resolver
->set_synchronous_mode(true);
2303 SequencedSocketData
data(nullptr, 0, nullptr, 0);
2304 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2306 // Load a cert that is valid for:
2310 base::FilePath certs_dir
= GetTestCertsDirectory();
2311 scoped_refptr
<X509Certificate
> test_cert(
2312 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2313 ASSERT_NE(static_cast<X509Certificate
*>(nullptr), test_cert
.get());
2315 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2316 ssl
.cert
= test_cert
;
2317 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2319 CreateNetworkSession();
2321 base::WeakPtr
<SpdySession
> session
=
2322 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2324 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2325 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2326 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.com"));
2327 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2330 TEST_P(SpdySessionTest
, ConnectionPooledWithTlsChannelId
) {
2331 session_deps_
.host_resolver
->set_synchronous_mode(true);
2333 SequencedSocketData
data(nullptr, 0, nullptr, 0);
2334 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2336 // Load a cert that is valid for:
2340 base::FilePath certs_dir
= GetTestCertsDirectory();
2341 scoped_refptr
<X509Certificate
> test_cert(
2342 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2343 ASSERT_NE(static_cast<X509Certificate
*>(nullptr), test_cert
.get());
2345 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2346 ssl
.channel_id_sent
= true;
2347 ssl
.cert
= test_cert
;
2348 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2350 CreateNetworkSession();
2352 base::WeakPtr
<SpdySession
> session
=
2353 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2355 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2356 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2357 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.example.com"));
2358 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2361 TEST_P(SpdySessionTest
, CloseTwoStalledCreateStream
) {
2362 // TODO(rtenneti): Define a helper class/methods and move the common code in
2364 SettingsMap new_settings
;
2365 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
2366 const uint32 max_concurrent_streams
= 1;
2367 new_settings
[kSpdySettingsIds1
] =
2368 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
2370 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
2371 scoped_ptr
<SpdyFrame
> req1(
2372 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
2373 scoped_ptr
<SpdyFrame
> req2(
2374 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST
, true));
2375 scoped_ptr
<SpdyFrame
> req3(
2376 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 5, LOWEST
, true));
2377 MockWrite writes
[] = {
2378 CreateMockWrite(*settings_ack
, 1),
2379 CreateMockWrite(*req1
, 2),
2380 CreateMockWrite(*req2
, 5),
2381 CreateMockWrite(*req3
, 8),
2384 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2386 scoped_ptr
<SpdyFrame
> settings_frame(
2387 spdy_util_
.ConstructSpdySettings(new_settings
));
2389 scoped_ptr
<SpdyFrame
> resp1(
2390 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2391 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2393 scoped_ptr
<SpdyFrame
> resp2(
2394 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
2395 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
2397 scoped_ptr
<SpdyFrame
> resp3(
2398 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 5));
2399 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
2401 MockRead reads
[] = {
2402 CreateMockRead(*settings_frame
, 0),
2403 CreateMockRead(*resp1
, 3),
2404 CreateMockRead(*body1
, 4),
2405 CreateMockRead(*resp2
, 6),
2406 CreateMockRead(*body2
, 7),
2407 CreateMockRead(*resp3
, 9),
2408 CreateMockRead(*body3
, 10),
2409 MockRead(ASYNC
, ERR_IO_PENDING
, 11),
2410 MockRead(ASYNC
, 0, 12) // EOF
2413 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2414 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2416 CreateNetworkSession();
2418 base::WeakPtr
<SpdySession
> session
=
2419 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2421 // Read the settings frame.
2422 base::RunLoop().RunUntilIdle();
2424 GURL
url1(kDefaultURL
);
2425 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2426 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2427 session
, url1
, LOWEST
, BoundNetLog());
2428 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2429 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2430 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2431 spdy_stream1
->SetDelegate(&delegate1
);
2433 TestCompletionCallback callback2
;
2434 GURL
url2(kDefaultURL
);
2435 SpdyStreamRequest request2
;
2436 ASSERT_EQ(ERR_IO_PENDING
,
2437 request2
.StartRequest(
2438 SPDY_REQUEST_RESPONSE_STREAM
,
2439 session
, url2
, LOWEST
, BoundNetLog(), callback2
.callback()));
2441 TestCompletionCallback callback3
;
2442 GURL
url3(kDefaultURL
);
2443 SpdyStreamRequest request3
;
2444 ASSERT_EQ(ERR_IO_PENDING
,
2445 request3
.StartRequest(
2446 SPDY_REQUEST_RESPONSE_STREAM
,
2447 session
, url3
, LOWEST
, BoundNetLog(), callback3
.callback()));
2449 EXPECT_EQ(0u, session
->num_active_streams());
2450 EXPECT_EQ(1u, session
->num_created_streams());
2451 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2453 scoped_ptr
<SpdyHeaderBlock
> headers(
2454 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2455 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2456 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2458 // Run until 1st stream is activated and then closed.
2459 EXPECT_EQ(0u, delegate1
.stream_id());
2460 base::RunLoop().RunUntilIdle();
2461 EXPECT_FALSE(spdy_stream1
);
2462 EXPECT_EQ(1u, delegate1
.stream_id());
2464 EXPECT_EQ(0u, session
->num_active_streams());
2465 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2467 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2468 // create the 2nd stream.
2469 base::RunLoop().RunUntilIdle();
2471 EXPECT_EQ(0u, session
->num_active_streams());
2472 EXPECT_EQ(1u, session
->num_created_streams());
2473 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2475 base::WeakPtr
<SpdyStream
> stream2
= request2
.ReleaseStream();
2476 test::StreamDelegateDoNothing
delegate2(stream2
);
2477 stream2
->SetDelegate(&delegate2
);
2478 scoped_ptr
<SpdyHeaderBlock
> headers2(
2479 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2480 stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2481 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
2483 // Run until 2nd stream is activated and then closed.
2484 EXPECT_EQ(0u, delegate2
.stream_id());
2485 base::RunLoop().RunUntilIdle();
2486 EXPECT_FALSE(stream2
);
2487 EXPECT_EQ(3u, delegate2
.stream_id());
2489 EXPECT_EQ(0u, session
->num_active_streams());
2490 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2492 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2493 // create the 3rd stream.
2494 base::RunLoop().RunUntilIdle();
2496 EXPECT_EQ(0u, session
->num_active_streams());
2497 EXPECT_EQ(1u, session
->num_created_streams());
2498 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2500 base::WeakPtr
<SpdyStream
> stream3
= request3
.ReleaseStream();
2501 test::StreamDelegateDoNothing
delegate3(stream3
);
2502 stream3
->SetDelegate(&delegate3
);
2503 scoped_ptr
<SpdyHeaderBlock
> headers3(
2504 spdy_util_
.ConstructGetHeaderBlock(url3
.spec()));
2505 stream3
->SendRequestHeaders(headers3
.Pass(), NO_MORE_DATA_TO_SEND
);
2506 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
2508 // Run until 2nd stream is activated and then closed.
2509 EXPECT_EQ(0u, delegate3
.stream_id());
2510 base::RunLoop().RunUntilIdle();
2511 EXPECT_FALSE(stream3
);
2512 EXPECT_EQ(5u, delegate3
.stream_id());
2514 EXPECT_EQ(0u, session
->num_active_streams());
2515 EXPECT_EQ(0u, session
->num_created_streams());
2516 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2518 data
.CompleteRead();
2519 base::RunLoop().RunUntilIdle();
2522 TEST_P(SpdySessionTest
, CancelTwoStalledCreateStream
) {
2523 session_deps_
.host_resolver
->set_synchronous_mode(true);
2525 MockRead reads
[] = {
2526 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2529 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2530 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2532 CreateNetworkSession();
2534 base::WeakPtr
<SpdySession
> session
=
2535 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2537 // Leave room for only one more stream to be created.
2538 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
2539 base::WeakPtr
<SpdyStream
> spdy_stream
=
2540 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2541 session
, test_url_
, MEDIUM
, BoundNetLog());
2542 ASSERT_TRUE(spdy_stream
!= nullptr);
2545 GURL
url1(kDefaultURL
);
2546 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2547 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2548 session
, url1
, LOWEST
, BoundNetLog());
2549 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2550 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2552 TestCompletionCallback callback2
;
2553 GURL
url2(kDefaultURL
);
2554 SpdyStreamRequest request2
;
2555 ASSERT_EQ(ERR_IO_PENDING
,
2556 request2
.StartRequest(
2557 SPDY_BIDIRECTIONAL_STREAM
, session
, url2
, LOWEST
, BoundNetLog(),
2558 callback2
.callback()));
2560 TestCompletionCallback callback3
;
2561 GURL
url3(kDefaultURL
);
2562 SpdyStreamRequest request3
;
2563 ASSERT_EQ(ERR_IO_PENDING
,
2564 request3
.StartRequest(
2565 SPDY_BIDIRECTIONAL_STREAM
, session
, url3
, LOWEST
, BoundNetLog(),
2566 callback3
.callback()));
2568 EXPECT_EQ(0u, session
->num_active_streams());
2569 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2570 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2572 // Cancel the first stream; this will allow the second stream to be created.
2573 EXPECT_TRUE(spdy_stream1
);
2574 spdy_stream1
->Cancel();
2575 EXPECT_FALSE(spdy_stream1
);
2577 EXPECT_EQ(OK
, callback2
.WaitForResult());
2578 EXPECT_EQ(0u, session
->num_active_streams());
2579 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2580 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2582 // Cancel the second stream; this will allow the third stream to be created.
2583 base::WeakPtr
<SpdyStream
> spdy_stream2
= request2
.ReleaseStream();
2584 spdy_stream2
->Cancel();
2585 EXPECT_FALSE(spdy_stream2
);
2587 EXPECT_EQ(OK
, callback3
.WaitForResult());
2588 EXPECT_EQ(0u, session
->num_active_streams());
2589 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2590 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2592 // Cancel the third stream.
2593 base::WeakPtr
<SpdyStream
> spdy_stream3
= request3
.ReleaseStream();
2594 spdy_stream3
->Cancel();
2595 EXPECT_FALSE(spdy_stream3
);
2596 EXPECT_EQ(0u, session
->num_active_streams());
2597 EXPECT_EQ(kInitialMaxConcurrentStreams
- 1, session
->num_created_streams());
2598 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2601 // Test that SpdySession::DoReadLoop reads data from the socket
2602 // without yielding. This test makes 32k - 1 bytes of data available
2603 // on the socket for reading. It then verifies that it has read all
2604 // the available data without yielding.
2605 TEST_P(SpdySessionTest
, ReadDataWithoutYielding
) {
2606 session_deps_
.host_resolver
->set_synchronous_mode(true);
2608 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2610 scoped_ptr
<SpdyFrame
> req1(
2611 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2612 MockWrite writes
[] = {
2613 CreateMockWrite(*req1
, 0),
2616 // Build buffer of size kYieldAfterBytesRead / 4
2617 // (-spdy_data_frame_size).
2618 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead
);
2619 const int kPayloadSize
=
2620 kYieldAfterBytesRead
/ 4 - framer
.GetControlFrameHeaderSize();
2621 TestDataStream test_stream
;
2622 scoped_refptr
<IOBuffer
> payload(new IOBuffer(kPayloadSize
));
2623 char* payload_data
= payload
->data();
2624 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2626 scoped_ptr
<SpdyFrame
> partial_data_frame(
2627 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2628 scoped_ptr
<SpdyFrame
> finish_data_frame(
2629 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
- 1, DATA_FLAG_FIN
));
2631 scoped_ptr
<SpdyFrame
> resp1(
2632 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2634 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2636 MockRead reads
[] = {
2637 CreateMockRead(*resp1
, 1),
2638 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2639 CreateMockRead(*partial_data_frame
, 3),
2640 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2641 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2642 CreateMockRead(*finish_data_frame
, 6, SYNCHRONOUS
),
2643 MockRead(ASYNC
, 0, 7) // EOF
2646 // Create SpdySession and SpdyStream and send the request.
2647 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2648 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2650 CreateNetworkSession();
2652 base::WeakPtr
<SpdySession
> session
=
2653 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2655 GURL
url1(kDefaultURL
);
2656 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2657 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2658 session
, url1
, MEDIUM
, BoundNetLog());
2659 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2660 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2661 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2662 spdy_stream1
->SetDelegate(&delegate1
);
2664 scoped_ptr
<SpdyHeaderBlock
> headers1(
2665 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2666 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2667 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2669 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2671 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2673 // Run until 1st read.
2674 EXPECT_EQ(0u, delegate1
.stream_id());
2675 base::RunLoop().RunUntilIdle();
2676 EXPECT_EQ(1u, delegate1
.stream_id());
2677 EXPECT_EQ(0u, observer
.executed_count());
2679 // Read all the data and verify SpdySession::DoReadLoop has not
2681 data
.CompleteRead();
2682 base::RunLoop().RunUntilIdle();
2683 EXPECT_FALSE(spdy_stream1
);
2685 // Verify task observer's executed_count is zero, which indicates DoRead read
2686 // all the available data.
2687 EXPECT_EQ(0u, observer
.executed_count());
2688 EXPECT_TRUE(data
.AllWriteDataConsumed());
2689 EXPECT_TRUE(data
.AllReadDataConsumed());
2692 // Test that SpdySession::DoReadLoop yields if more than
2693 // |kYieldAfterDurationMilliseconds| has passed. This test uses a mock time
2694 // function that makes the response frame look very slow to read.
2695 TEST_P(SpdySessionTest
, TestYieldingSlowReads
) {
2696 session_deps_
.host_resolver
->set_synchronous_mode(true);
2697 session_deps_
.time_func
= SlowReads
;
2699 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2701 scoped_ptr
<SpdyFrame
> req1(
2702 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2703 MockWrite writes
[] = {
2704 CreateMockWrite(*req1
, 0),
2707 scoped_ptr
<SpdyFrame
> resp1(
2708 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2710 MockRead reads
[] = {
2711 CreateMockRead(*resp1
, 1), MockRead(ASYNC
, 0, 2) // EOF
2714 // Create SpdySession and SpdyStream and send the request.
2715 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2716 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2718 CreateNetworkSession();
2720 base::WeakPtr
<SpdySession
> session
=
2721 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2723 GURL
url1(kDefaultURL
);
2724 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2725 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, MEDIUM
, BoundNetLog());
2726 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2727 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2728 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2729 spdy_stream1
->SetDelegate(&delegate1
);
2731 scoped_ptr
<SpdyHeaderBlock
> headers1(
2732 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2733 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2734 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2736 // Set up the TaskObserver to verify that SpdySession::DoReadLoop posts a
2738 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2740 EXPECT_EQ(0u, delegate1
.stream_id());
2741 EXPECT_EQ(0u, observer
.executed_count());
2743 // Read all the data and verify that SpdySession::DoReadLoop has posted a
2745 base::RunLoop().RunUntilIdle();
2746 EXPECT_EQ(1u, delegate1
.stream_id());
2747 EXPECT_FALSE(spdy_stream1
);
2749 // Verify task that the observer's executed_count is 1, which indicates DoRead
2750 // has posted only one task and thus yielded though there is data available
2752 EXPECT_EQ(1u, observer
.executed_count());
2753 EXPECT_TRUE(data
.AllWriteDataConsumed());
2754 EXPECT_TRUE(data
.AllReadDataConsumed());
2757 // Test that SpdySession::DoReadLoop yields while reading the
2758 // data. This test makes 32k + 1 bytes of data available on the socket
2759 // for reading. It then verifies that DoRead has yielded even though
2760 // there is data available for it to read (i.e, socket()->Read didn't
2761 // return ERR_IO_PENDING during socket reads).
2762 TEST_P(SpdySessionTest
, TestYieldingDuringReadData
) {
2763 session_deps_
.host_resolver
->set_synchronous_mode(true);
2765 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2767 scoped_ptr
<SpdyFrame
> req1(
2768 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2769 MockWrite writes
[] = {
2770 CreateMockWrite(*req1
, 0),
2773 // Build buffer of size kYieldAfterBytesRead / 4
2774 // (-spdy_data_frame_size).
2775 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead
);
2776 const int kPayloadSize
=
2777 kYieldAfterBytesRead
/ 4 - framer
.GetControlFrameHeaderSize();
2778 TestDataStream test_stream
;
2779 scoped_refptr
<IOBuffer
> payload(new IOBuffer(kPayloadSize
));
2780 char* payload_data
= payload
->data();
2781 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2783 scoped_ptr
<SpdyFrame
> partial_data_frame(
2784 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2785 scoped_ptr
<SpdyFrame
> finish_data_frame(
2786 framer
.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN
));
2788 scoped_ptr
<SpdyFrame
> resp1(
2789 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2791 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2792 MockRead reads
[] = {
2793 CreateMockRead(*resp1
, 1),
2794 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2795 CreateMockRead(*partial_data_frame
, 3),
2796 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2797 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2798 CreateMockRead(*partial_data_frame
, 6, SYNCHRONOUS
),
2799 CreateMockRead(*finish_data_frame
, 7, SYNCHRONOUS
),
2800 MockRead(ASYNC
, 0, 8) // EOF
2803 // Create SpdySession and SpdyStream and send the request.
2804 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2805 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2807 CreateNetworkSession();
2809 base::WeakPtr
<SpdySession
> session
=
2810 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2812 GURL
url1(kDefaultURL
);
2813 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2814 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2815 session
, url1
, MEDIUM
, BoundNetLog());
2816 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2817 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2818 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2819 spdy_stream1
->SetDelegate(&delegate1
);
2821 scoped_ptr
<SpdyHeaderBlock
> headers1(
2822 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2823 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2824 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2826 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a task.
2827 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2829 // Run until 1st read.
2830 EXPECT_EQ(0u, delegate1
.stream_id());
2831 base::RunLoop().RunUntilIdle();
2832 EXPECT_EQ(1u, delegate1
.stream_id());
2833 EXPECT_EQ(0u, observer
.executed_count());
2835 // Read all the data and verify SpdySession::DoReadLoop has posted a task.
2836 data
.CompleteRead();
2837 base::RunLoop().RunUntilIdle();
2838 EXPECT_FALSE(spdy_stream1
);
2840 // Verify task observer's executed_count is 1, which indicates DoRead has
2841 // posted only one task and thus yielded though there is data available for it
2843 EXPECT_EQ(1u, observer
.executed_count());
2844 EXPECT_TRUE(data
.AllWriteDataConsumed());
2845 EXPECT_TRUE(data
.AllReadDataConsumed());
2848 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2849 // + async, by doing the following MockReads.
2851 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2852 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2854 // The above reads 26K synchronously. Since that is less that 32K, we
2855 // will attempt to read again. However, that DoRead() will return
2856 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2857 // yield. When we come back, DoRead() will read the results from the
2858 // async read, and rest of the data synchronously.
2859 TEST_P(SpdySessionTest
, TestYieldingDuringAsyncReadData
) {
2860 session_deps_
.host_resolver
->set_synchronous_mode(true);
2862 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2864 scoped_ptr
<SpdyFrame
> req1(
2865 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2866 MockWrite writes
[] = {
2867 CreateMockWrite(*req1
, 0),
2870 // Build buffer of size kYieldAfterBytesRead / 4
2871 // (-spdy_data_frame_size).
2872 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead
);
2873 TestDataStream test_stream
;
2874 const int kEightKPayloadSize
=
2875 kYieldAfterBytesRead
/ 4 - framer
.GetControlFrameHeaderSize();
2876 scoped_refptr
<IOBuffer
> eightk_payload(new IOBuffer(kEightKPayloadSize
));
2877 char* eightk_payload_data
= eightk_payload
->data();
2878 test_stream
.GetBytes(eightk_payload_data
, kEightKPayloadSize
);
2880 // Build buffer of 2k size.
2881 TestDataStream test_stream2
;
2882 const int kTwoKPayloadSize
= kEightKPayloadSize
- 6 * 1024;
2883 scoped_refptr
<IOBuffer
> twok_payload(new IOBuffer(kTwoKPayloadSize
));
2884 char* twok_payload_data
= twok_payload
->data();
2885 test_stream2
.GetBytes(twok_payload_data
, kTwoKPayloadSize
);
2887 scoped_ptr
<SpdyFrame
> eightk_data_frame(framer
.CreateDataFrame(
2888 1, eightk_payload_data
, kEightKPayloadSize
, DATA_FLAG_NONE
));
2889 scoped_ptr
<SpdyFrame
> twok_data_frame(framer
.CreateDataFrame(
2890 1, twok_payload_data
, kTwoKPayloadSize
, DATA_FLAG_NONE
));
2891 scoped_ptr
<SpdyFrame
> finish_data_frame(framer
.CreateDataFrame(
2892 1, "h", 1, DATA_FLAG_FIN
));
2894 scoped_ptr
<SpdyFrame
> resp1(
2895 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2897 MockRead reads
[] = {
2898 CreateMockRead(*resp1
, 1),
2899 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2900 CreateMockRead(*eightk_data_frame
, 3),
2901 CreateMockRead(*eightk_data_frame
, 4, SYNCHRONOUS
),
2902 CreateMockRead(*eightk_data_frame
, 5, SYNCHRONOUS
),
2903 CreateMockRead(*twok_data_frame
, 6, SYNCHRONOUS
),
2904 CreateMockRead(*eightk_data_frame
, 7, ASYNC
),
2905 CreateMockRead(*eightk_data_frame
, 8, SYNCHRONOUS
),
2906 CreateMockRead(*eightk_data_frame
, 9, SYNCHRONOUS
),
2907 CreateMockRead(*eightk_data_frame
, 10, SYNCHRONOUS
),
2908 CreateMockRead(*twok_data_frame
, 11, SYNCHRONOUS
),
2909 CreateMockRead(*finish_data_frame
, 12, SYNCHRONOUS
),
2910 MockRead(ASYNC
, 0, 13) // EOF
2913 // Create SpdySession and SpdyStream and send the request.
2914 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2915 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2917 CreateNetworkSession();
2919 base::WeakPtr
<SpdySession
> session
=
2920 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2922 GURL
url1(kDefaultURL
);
2923 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2924 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2925 session
, url1
, MEDIUM
, BoundNetLog());
2926 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2927 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2928 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2929 spdy_stream1
->SetDelegate(&delegate1
);
2931 scoped_ptr
<SpdyHeaderBlock
> headers1(
2932 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2933 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2934 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2936 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2937 // posting of tasks.
2938 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2940 // Run until 1st read.
2941 EXPECT_EQ(0u, delegate1
.stream_id());
2942 base::RunLoop().RunUntilIdle();
2943 EXPECT_EQ(1u, delegate1
.stream_id());
2944 EXPECT_EQ(0u, observer
.executed_count());
2946 // Read all the data and verify SpdySession::DoReadLoop has posted a
2948 data
.CompleteRead();
2949 base::RunLoop().RunUntilIdle();
2950 EXPECT_FALSE(spdy_stream1
);
2952 // Verify task observer's executed_count is 1, which indicates DoRead has
2953 // posted only one task and thus yielded though there is data available for
2955 EXPECT_EQ(1u, observer
.executed_count());
2956 EXPECT_TRUE(data
.AllWriteDataConsumed());
2957 EXPECT_TRUE(data
.AllReadDataConsumed());
2960 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2961 // nothing blows up.
2962 TEST_P(SpdySessionTest
, GoAwayWhileInDoReadLoop
) {
2963 session_deps_
.host_resolver
->set_synchronous_mode(true);
2965 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2967 scoped_ptr
<SpdyFrame
> req1(
2968 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2969 MockWrite writes
[] = {
2970 CreateMockWrite(*req1
, 0),
2973 scoped_ptr
<SpdyFrame
> resp1(
2974 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2975 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2976 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
2978 MockRead reads
[] = {
2979 CreateMockRead(*resp1
, 1),
2980 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2981 CreateMockRead(*body1
, 3),
2982 CreateMockRead(*goaway
, 4),
2985 // Create SpdySession and SpdyStream and send the request.
2986 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2987 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2989 CreateNetworkSession();
2991 base::WeakPtr
<SpdySession
> session
=
2992 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2994 GURL
url1(kDefaultURL
);
2995 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2996 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2997 session
, url1
, MEDIUM
, BoundNetLog());
2998 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2999 spdy_stream1
->SetDelegate(&delegate1
);
3000 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
3001 EXPECT_EQ(0u, spdy_stream1
->stream_id());
3003 scoped_ptr
<SpdyHeaderBlock
> headers1(
3004 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
3005 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
3006 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3008 // Run until 1st read.
3009 EXPECT_EQ(0u, spdy_stream1
->stream_id());
3010 base::RunLoop().RunUntilIdle();
3011 EXPECT_EQ(1u, spdy_stream1
->stream_id());
3013 // Run until GoAway.
3014 data
.CompleteRead();
3015 base::RunLoop().RunUntilIdle();
3016 EXPECT_FALSE(spdy_stream1
);
3017 EXPECT_TRUE(data
.AllWriteDataConsumed());
3018 EXPECT_TRUE(data
.AllReadDataConsumed());
3019 EXPECT_FALSE(session
);
3022 // Within this framework, a SpdySession should be initialized with
3023 // flow control disabled for protocol version 2, with flow control
3024 // enabled only for streams for protocol version 3, and with flow
3025 // control enabled for streams and sessions for higher versions.
3026 TEST_P(SpdySessionTest
, ProtocolNegotiation
) {
3027 session_deps_
.host_resolver
->set_synchronous_mode(true);
3029 MockRead reads
[] = {
3030 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3032 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
3033 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3035 CreateNetworkSession();
3036 base::WeakPtr
<SpdySession
> session
=
3037 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3039 EXPECT_EQ(spdy_util_
.spdy_version(),
3040 session
->buffered_spdy_framer_
->protocol_version());
3041 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3042 session
->flow_control_state());
3043 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3044 session
->session_send_window_size_
);
3045 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3046 session
->session_recv_window_size_
);
3047 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3050 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3051 // pointers to the idle session are currently held.
3052 TEST_P(SpdySessionTest
, CloseOneIdleConnection
) {
3053 ClientSocketPoolManager::set_max_sockets_per_group(
3054 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3055 ClientSocketPoolManager::set_max_sockets_per_pool(
3056 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3058 MockRead reads
[] = {
3059 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3061 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
3062 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3063 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3065 CreateNetworkSession();
3067 TransportClientSocketPool
* pool
=
3068 http_session_
->GetTransportSocketPool(
3069 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3071 // Create an idle SPDY session.
3072 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3073 PRIVACY_MODE_DISABLED
);
3074 base::WeakPtr
<SpdySession
> session1
=
3075 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3076 EXPECT_FALSE(pool
->IsStalled());
3078 // Trying to create a new connection should cause the pool to be stalled, and
3079 // post a task asynchronously to try and close the session.
3080 TestCompletionCallback callback2
;
3081 HostPortPair
host_port2("2.com", 80);
3082 scoped_refptr
<TransportSocketParams
> params2(
3083 new TransportSocketParams(
3084 host_port2
, false, false, OnHostResolutionCallback(),
3085 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3086 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3087 EXPECT_EQ(ERR_IO_PENDING
,
3088 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3089 callback2
.callback(), pool
, BoundNetLog()));
3090 EXPECT_TRUE(pool
->IsStalled());
3092 // The socket pool should close the connection asynchronously and establish a
3094 EXPECT_EQ(OK
, callback2
.WaitForResult());
3095 EXPECT_FALSE(pool
->IsStalled());
3096 EXPECT_FALSE(session1
);
3099 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3100 // pointers to the idle session are currently held, in the case the SPDY session
3102 TEST_P(SpdySessionTest
, CloseOneIdleConnectionWithAlias
) {
3103 ClientSocketPoolManager::set_max_sockets_per_group(
3104 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3105 ClientSocketPoolManager::set_max_sockets_per_pool(
3106 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3108 MockRead reads
[] = {
3109 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3111 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
3112 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3113 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3115 session_deps_
.host_resolver
->set_synchronous_mode(true);
3116 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3117 "1.com", "192.168.0.2", std::string());
3118 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3119 "2.com", "192.168.0.2", std::string());
3120 // Not strictly needed.
3121 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3122 "3.com", "192.168.0.3", std::string());
3124 CreateNetworkSession();
3126 TransportClientSocketPool
* pool
=
3127 http_session_
->GetTransportSocketPool(
3128 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3130 // Create an idle SPDY session.
3131 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3132 PRIVACY_MODE_DISABLED
);
3133 base::WeakPtr
<SpdySession
> session1
=
3134 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3135 EXPECT_FALSE(pool
->IsStalled());
3137 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3138 SpdySessionKey
key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3139 PRIVACY_MODE_DISABLED
);
3140 HostResolver::RequestInfo
info(key2
.host_port_pair());
3141 AddressList addresses
;
3142 // Pre-populate the DNS cache, since a synchronous resolution is required in
3143 // order to create the alias.
3144 session_deps_
.host_resolver
->Resolve(info
, DEFAULT_PRIORITY
, &addresses
,
3145 CompletionCallback(), nullptr,
3147 // Get a session for |key2|, which should return the session created earlier.
3148 base::WeakPtr
<SpdySession
> session2
=
3149 spdy_session_pool_
->FindAvailableSession(key2
, BoundNetLog());
3150 ASSERT_EQ(session1
.get(), session2
.get());
3151 EXPECT_FALSE(pool
->IsStalled());
3153 // Trying to create a new connection should cause the pool to be stalled, and
3154 // post a task asynchronously to try and close the session.
3155 TestCompletionCallback callback3
;
3156 HostPortPair
host_port3("3.com", 80);
3157 scoped_refptr
<TransportSocketParams
> params3(
3158 new TransportSocketParams(
3159 host_port3
, false, false, OnHostResolutionCallback(),
3160 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3161 scoped_ptr
<ClientSocketHandle
> connection3(new ClientSocketHandle
);
3162 EXPECT_EQ(ERR_IO_PENDING
,
3163 connection3
->Init(host_port3
.ToString(), params3
, DEFAULT_PRIORITY
,
3164 callback3
.callback(), pool
, BoundNetLog()));
3165 EXPECT_TRUE(pool
->IsStalled());
3167 // The socket pool should close the connection asynchronously and establish a
3169 EXPECT_EQ(OK
, callback3
.WaitForResult());
3170 EXPECT_FALSE(pool
->IsStalled());
3171 EXPECT_FALSE(session1
);
3172 EXPECT_FALSE(session2
);
3175 // Tests that when a SPDY session becomes idle, it closes itself if there is
3176 // a lower layer pool stalled on the per-pool socket limit.
3177 TEST_P(SpdySessionTest
, CloseSessionOnIdleWhenPoolStalled
) {
3178 ClientSocketPoolManager::set_max_sockets_per_group(
3179 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3180 ClientSocketPoolManager::set_max_sockets_per_pool(
3181 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3183 MockRead reads
[] = {
3184 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3186 scoped_ptr
<SpdyFrame
> req1(
3187 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3188 scoped_ptr
<SpdyFrame
> cancel1(
3189 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3190 MockWrite writes
[] = {
3191 CreateMockWrite(*req1
, 1),
3192 CreateMockWrite(*cancel1
, 1),
3194 StaticSocketDataProvider
data(reads
, arraysize(reads
),
3195 writes
, arraysize(writes
));
3196 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3198 MockRead http_reads
[] = {
3199 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3201 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
), nullptr,
3203 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
3206 CreateNetworkSession();
3208 TransportClientSocketPool
* pool
=
3209 http_session_
->GetTransportSocketPool(
3210 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3212 // Create a SPDY session.
3213 GURL
url1(kDefaultURL
);
3214 SpdySessionKey
key1(HostPortPair(url1
.host(), 80),
3215 ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3216 base::WeakPtr
<SpdySession
> session1
=
3217 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3218 EXPECT_FALSE(pool
->IsStalled());
3220 // Create a stream using the session, and send a request.
3222 TestCompletionCallback callback1
;
3223 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3224 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3225 session1
, url1
, DEFAULT_PRIORITY
,
3227 ASSERT_TRUE(spdy_stream1
.get());
3228 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3229 spdy_stream1
->SetDelegate(&delegate1
);
3231 scoped_ptr
<SpdyHeaderBlock
> headers1(
3232 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
3233 EXPECT_EQ(ERR_IO_PENDING
,
3234 spdy_stream1
->SendRequestHeaders(
3235 headers1
.Pass(), NO_MORE_DATA_TO_SEND
));
3236 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3238 base::RunLoop().RunUntilIdle();
3240 // Trying to create a new connection should cause the pool to be stalled, and
3241 // post a task asynchronously to try and close the session.
3242 TestCompletionCallback callback2
;
3243 HostPortPair
host_port2("2.com", 80);
3244 scoped_refptr
<TransportSocketParams
> params2(
3245 new TransportSocketParams(
3246 host_port2
, false, false, OnHostResolutionCallback(),
3247 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3248 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3249 EXPECT_EQ(ERR_IO_PENDING
,
3250 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3251 callback2
.callback(), pool
, BoundNetLog()));
3252 EXPECT_TRUE(pool
->IsStalled());
3254 // Running the message loop should cause the socket pool to ask the SPDY
3255 // session to close an idle socket, but since the socket is in use, nothing
3257 base::RunLoop().RunUntilIdle();
3258 EXPECT_TRUE(pool
->IsStalled());
3259 EXPECT_FALSE(callback2
.have_result());
3261 // Cancelling the request should result in the session's socket being
3262 // closed, since the pool is stalled.
3263 ASSERT_TRUE(spdy_stream1
.get());
3264 spdy_stream1
->Cancel();
3265 base::RunLoop().RunUntilIdle();
3266 ASSERT_FALSE(pool
->IsStalled());
3267 EXPECT_EQ(OK
, callback2
.WaitForResult());
3270 // Verify that SpdySessionKey and therefore SpdySession is different when
3271 // privacy mode is enabled or disabled.
3272 TEST_P(SpdySessionTest
, SpdySessionKeyPrivacyMode
) {
3273 CreateNetworkSession();
3275 HostPortPair
host_port_pair("www.example.org", 443);
3276 SpdySessionKey
key_privacy_enabled(host_port_pair
, ProxyServer::Direct(),
3277 PRIVACY_MODE_ENABLED
);
3278 SpdySessionKey
key_privacy_disabled(host_port_pair
, ProxyServer::Direct(),
3279 PRIVACY_MODE_DISABLED
);
3281 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3282 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3284 // Add SpdySession with PrivacyMode Enabled to the pool.
3285 base::WeakPtr
<SpdySession
> session_privacy_enabled
=
3286 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_enabled
);
3288 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3289 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3291 // Add SpdySession with PrivacyMode Disabled to the pool.
3292 base::WeakPtr
<SpdySession
> session_privacy_disabled
=
3293 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_disabled
);
3295 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3296 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3298 session_privacy_enabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3299 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3300 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3302 session_privacy_disabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3303 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3304 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3307 // Delegate that creates another stream when its stream is closed.
3308 class StreamCreatingDelegate
: public test::StreamDelegateDoNothing
{
3310 StreamCreatingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3311 const base::WeakPtr
<SpdySession
>& session
)
3312 : StreamDelegateDoNothing(stream
),
3313 session_(session
) {}
3315 ~StreamCreatingDelegate() override
{}
3317 void OnClose(int status
) override
{
3318 GURL
url(kDefaultURL
);
3320 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3321 session_
, url
, MEDIUM
, BoundNetLog()));
3325 const base::WeakPtr
<SpdySession
> session_
;
3328 // Create another stream in response to a stream being reset. Nothing
3329 // should blow up. This is a regression test for
3330 // http://crbug.com/263690 .
3331 TEST_P(SpdySessionTest
, CreateStreamOnStreamReset
) {
3332 session_deps_
.host_resolver
->set_synchronous_mode(true);
3334 scoped_ptr
<SpdyFrame
> req(
3335 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
3336 MockWrite writes
[] = {
3337 CreateMockWrite(*req
, 0),
3340 scoped_ptr
<SpdyFrame
> rst(
3341 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
3342 MockRead reads
[] = {
3343 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3344 CreateMockRead(*rst
, 2),
3345 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3346 MockRead(ASYNC
, 0, 4) // EOF
3348 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3349 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3351 CreateNetworkSession();
3353 base::WeakPtr
<SpdySession
> session
=
3354 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3356 GURL
url(kDefaultURL
);
3357 base::WeakPtr
<SpdyStream
> spdy_stream
=
3358 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3359 session
, url
, MEDIUM
, BoundNetLog());
3360 ASSERT_TRUE(spdy_stream
.get() != nullptr);
3361 EXPECT_EQ(0u, spdy_stream
->stream_id());
3363 StreamCreatingDelegate
delegate(spdy_stream
, session
);
3364 spdy_stream
->SetDelegate(&delegate
);
3366 scoped_ptr
<SpdyHeaderBlock
> headers(
3367 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
3368 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
3369 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
3371 EXPECT_EQ(0u, spdy_stream
->stream_id());
3373 base::RunLoop().RunUntilIdle();
3375 EXPECT_EQ(1u, spdy_stream
->stream_id());
3377 // Cause the stream to be reset, which should cause another stream
3379 data
.CompleteRead();
3380 base::RunLoop().RunUntilIdle();
3382 EXPECT_FALSE(spdy_stream
);
3383 EXPECT_TRUE(delegate
.StreamIsClosed());
3384 EXPECT_EQ(0u, session
->num_active_streams());
3385 EXPECT_EQ(1u, session
->num_created_streams());
3387 data
.CompleteRead();
3388 base::RunLoop().RunUntilIdle();
3389 EXPECT_FALSE(session
);
3392 TEST_P(SpdySessionTest
, UpdateStreamsSendWindowSize
) {
3393 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3395 SettingsMap new_settings
;
3396 int32 window_size
= 1;
3397 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
3398 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, window_size
);
3400 // Set up the socket so we read a SETTINGS frame that sets
3401 // INITIAL_WINDOW_SIZE.
3402 scoped_ptr
<SpdyFrame
> settings_frame(
3403 spdy_util_
.ConstructSpdySettings(new_settings
));
3404 MockRead reads
[] = {
3405 CreateMockRead(*settings_frame
, 0),
3406 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3407 MockRead(ASYNC
, 0, 2) // EOF
3410 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
3411 MockWrite writes
[] = {
3412 CreateMockWrite(*settings_ack
, 3),
3415 session_deps_
.host_resolver
->set_synchronous_mode(true);
3417 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3418 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3420 CreateNetworkSession();
3422 base::WeakPtr
<SpdySession
> session
=
3423 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3424 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3425 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3426 session
, test_url_
, MEDIUM
, BoundNetLog());
3427 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
3428 TestCompletionCallback callback1
;
3429 EXPECT_NE(spdy_stream1
->send_window_size(), window_size
);
3431 // Process the SETTINGS frame.
3432 base::RunLoop().RunUntilIdle();
3433 EXPECT_EQ(session
->stream_initial_send_window_size(), window_size
);
3434 EXPECT_EQ(spdy_stream1
->send_window_size(), window_size
);
3436 // Release the first one, this will allow the second to be created.
3437 spdy_stream1
->Cancel();
3438 EXPECT_FALSE(spdy_stream1
);
3440 base::WeakPtr
<SpdyStream
> spdy_stream2
=
3441 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3442 session
, test_url_
, MEDIUM
, BoundNetLog());
3443 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
3444 EXPECT_EQ(spdy_stream2
->send_window_size(), window_size
);
3445 spdy_stream2
->Cancel();
3446 EXPECT_FALSE(spdy_stream2
);
3448 EXPECT_TRUE(session
);
3449 data
.CompleteRead();
3450 base::RunLoop().RunUntilIdle();
3451 EXPECT_FALSE(session
);
3454 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3455 // adjust the session receive window size. In addition,
3456 // SpdySession::IncreaseRecvWindowSize should trigger
3457 // sending a WINDOW_UPDATE frame for a large enough delta.
3458 TEST_P(SpdySessionTest
, AdjustRecvWindowSize
) {
3459 session_deps_
.host_resolver
->set_synchronous_mode(true);
3461 const int32 initial_window_size
=
3462 SpdySession::GetDefaultInitialWindowSize(GetParam());
3463 const int32 delta_window_size
= 100;
3465 MockRead reads
[] = {
3466 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
3468 scoped_ptr
<SpdyFrame
> window_update(spdy_util_
.ConstructSpdyWindowUpdate(
3469 kSessionFlowControlStreamId
, initial_window_size
+ delta_window_size
));
3470 MockWrite writes
[] = {
3471 CreateMockWrite(*window_update
, 0),
3473 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3474 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3476 CreateNetworkSession();
3477 base::WeakPtr
<SpdySession
> session
=
3478 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3479 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3480 session
->flow_control_state());
3482 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3483 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3485 session
->IncreaseRecvWindowSize(delta_window_size
);
3486 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3487 session
->session_recv_window_size_
);
3488 EXPECT_EQ(delta_window_size
, session
->session_unacked_recv_window_bytes_
);
3490 // Should trigger sending a WINDOW_UPDATE frame.
3491 session
->IncreaseRecvWindowSize(initial_window_size
);
3492 EXPECT_EQ(initial_window_size
+ delta_window_size
+ initial_window_size
,
3493 session
->session_recv_window_size_
);
3494 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3496 base::RunLoop().RunUntilIdle();
3498 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3499 session
->in_io_loop_
= true;
3500 session
->DecreaseRecvWindowSize(initial_window_size
+ delta_window_size
+
3501 initial_window_size
);
3502 session
->in_io_loop_
= false;
3503 EXPECT_EQ(0, session
->session_recv_window_size_
);
3504 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3506 EXPECT_TRUE(session
);
3507 data
.CompleteRead();
3508 base::RunLoop().RunUntilIdle();
3509 EXPECT_FALSE(session
);
3512 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3513 // adjust the session send window size when the "enable_spdy_31" flag
3515 TEST_P(SpdySessionTest
, AdjustSendWindowSize
) {
3516 session_deps_
.host_resolver
->set_synchronous_mode(true);
3518 MockRead reads
[] = {
3519 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3521 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
3522 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3524 CreateNetworkSession();
3525 base::WeakPtr
<SpdySession
> session
=
3526 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3527 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3528 session
->flow_control_state());
3530 const int32 initial_window_size
=
3531 SpdySession::GetDefaultInitialWindowSize(GetParam());
3532 const int32 delta_window_size
= 100;
3534 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3536 session
->IncreaseSendWindowSize(delta_window_size
);
3537 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3538 session
->session_send_window_size_
);
3540 session
->DecreaseSendWindowSize(delta_window_size
);
3541 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3544 // Incoming data for an inactive stream should not cause the session
3545 // receive window size to decrease, but it should cause the unacked
3546 // bytes to increase.
3547 TEST_P(SpdySessionTest
, SessionFlowControlInactiveStream
) {
3548 session_deps_
.host_resolver
->set_synchronous_mode(true);
3550 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(1, false));
3551 MockRead reads
[] = {
3552 CreateMockRead(*resp
, 0),
3553 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3554 MockRead(ASYNC
, 0, 2) // EOF
3556 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
3557 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3559 CreateNetworkSession();
3560 base::WeakPtr
<SpdySession
> session
=
3561 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3562 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3563 session
->flow_control_state());
3565 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3566 session
->session_recv_window_size_
);
3567 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3569 base::RunLoop().RunUntilIdle();
3571 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3572 session
->session_recv_window_size_
);
3573 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
3575 EXPECT_TRUE(session
);
3576 data
.CompleteRead();
3577 base::RunLoop().RunUntilIdle();
3578 EXPECT_FALSE(session
);
3581 // The frame header is not included in flow control, but frame payload
3582 // (including optional pad length and padding) is.
3583 TEST_P(SpdySessionTest
, SessionFlowControlPadding
) {
3584 // Padding only exists in HTTP/2.
3585 if (GetParam() < kProtoHTTP2MinimumVersion
)
3588 session_deps_
.host_resolver
->set_synchronous_mode(true);
3590 const int padding_length
= 42;
3591 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(
3592 1, kUploadData
, kUploadDataSize
, false, padding_length
));
3593 MockRead reads
[] = {
3594 CreateMockRead(*resp
, 0),
3595 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3596 MockRead(ASYNC
, 0, 2) // EOF
3598 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
3599 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3601 CreateNetworkSession();
3602 base::WeakPtr
<SpdySession
> session
=
3603 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3604 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3605 session
->flow_control_state());
3607 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3608 session
->session_recv_window_size_
);
3609 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3611 base::RunLoop().RunUntilIdle();
3613 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3614 session
->session_recv_window_size_
);
3615 EXPECT_EQ(kUploadDataSize
+ padding_length
,
3616 session
->session_unacked_recv_window_bytes_
);
3618 data
.CompleteRead();
3619 base::RunLoop().RunUntilIdle();
3620 EXPECT_FALSE(session
);
3623 // Peer sends more data than stream level receiving flow control window.
3624 TEST_P(SpdySessionTest
, StreamFlowControlTooMuchData
) {
3625 const int32 stream_max_recv_window_size
= 1024;
3626 const int32 data_frame_size
= 2 * stream_max_recv_window_size
;
3628 scoped_ptr
<SpdyFrame
> req(
3629 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3630 scoped_ptr
<SpdyFrame
> rst(
3631 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
3632 MockWrite writes
[] = {
3633 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 4),
3636 scoped_ptr
<SpdyFrame
> resp(
3637 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3638 const std::string
payload(data_frame_size
, 'a');
3639 scoped_ptr
<SpdyFrame
> data_frame(spdy_util_
.ConstructSpdyBodyFrame(
3640 1, payload
.data(), data_frame_size
, false));
3641 MockRead reads
[] = {
3642 CreateMockRead(*resp
, 1),
3643 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
3644 CreateMockRead(*data_frame
, 3),
3645 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
3646 MockRead(ASYNC
, 0, 6),
3649 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3650 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3651 CreateNetworkSession();
3653 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
3654 pool_peer
.SetStreamInitialRecvWindowSize(stream_max_recv_window_size
);
3655 base::WeakPtr
<SpdySession
> session
=
3656 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3657 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM
, session
->flow_control_state());
3659 GURL
url(kDefaultURL
);
3660 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
3661 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, LOWEST
, BoundNetLog());
3662 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3664 test::StreamDelegateDoNothing
delegate(spdy_stream
);
3665 spdy_stream
->SetDelegate(&delegate
);
3667 scoped_ptr
<SpdyHeaderBlock
> headers(
3668 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
3669 EXPECT_EQ(ERR_IO_PENDING
, spdy_stream
->SendRequestHeaders(
3670 headers
.Pass(), NO_MORE_DATA_TO_SEND
));
3672 // Request and response.
3673 base::RunLoop().RunUntilIdle();
3674 EXPECT_EQ(1u, spdy_stream
->stream_id());
3676 // Too large data frame causes flow control error, should close stream.
3677 data
.CompleteRead();
3678 base::RunLoop().RunUntilIdle();
3679 EXPECT_FALSE(spdy_stream
);
3681 EXPECT_TRUE(session
);
3682 data
.CompleteRead();
3683 base::RunLoop().RunUntilIdle();
3684 EXPECT_FALSE(session
);
3687 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3688 // deltas in the receiving window size when checking incoming frames for flow
3689 // control errors at session level.
3690 TEST_P(SpdySessionTest
, SessionFlowControlTooMuchDataTwoDataFrames
) {
3691 const int32 session_max_recv_window_size
= 500;
3692 const int32 first_data_frame_size
= 200;
3693 const int32 second_data_frame_size
= 400;
3695 // First data frame should not trigger a WINDOW_UPDATE.
3696 ASSERT_GT(session_max_recv_window_size
/ 2, first_data_frame_size
);
3697 // Second data frame would be fine had there been a WINDOW_UPDATE.
3698 ASSERT_GT(session_max_recv_window_size
, second_data_frame_size
);
3699 // But in fact, the two data frames together overflow the receiving window at
3701 ASSERT_LT(session_max_recv_window_size
,
3702 first_data_frame_size
+ second_data_frame_size
);
3704 session_deps_
.host_resolver
->set_synchronous_mode(true);
3706 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3707 0, GOAWAY_FLOW_CONTROL_ERROR
,
3708 "delta_window_size is 400 in DecreaseRecvWindowSize, which is larger "
3709 "than the receive window size of 500"));
3710 MockWrite writes
[] = {
3711 CreateMockWrite(*goaway
, 4),
3714 const std::string
first_data_frame(first_data_frame_size
, 'a');
3715 scoped_ptr
<SpdyFrame
> first(spdy_util_
.ConstructSpdyBodyFrame(
3716 1, first_data_frame
.data(), first_data_frame_size
, false));
3717 const std::string
second_data_frame(second_data_frame_size
, 'b');
3718 scoped_ptr
<SpdyFrame
> second(spdy_util_
.ConstructSpdyBodyFrame(
3719 1, second_data_frame
.data(), second_data_frame_size
, false));
3720 MockRead reads
[] = {
3721 CreateMockRead(*first
, 0),
3722 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3723 CreateMockRead(*second
, 2),
3724 MockRead(ASYNC
, 0, 3),
3726 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3727 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3729 CreateNetworkSession();
3730 base::WeakPtr
<SpdySession
> session
=
3731 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3732 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3733 session
->flow_control_state());
3734 // Setting session level receiving window size to smaller than initial is not
3735 // possible via SpdySessionPoolPeer.
3736 session
->session_recv_window_size_
= session_max_recv_window_size
;
3738 // First data frame is immediately consumed and does not trigger
3740 base::RunLoop().RunUntilIdle();
3741 EXPECT_EQ(first_data_frame_size
, session
->session_unacked_recv_window_bytes_
);
3742 EXPECT_EQ(session_max_recv_window_size
, session
->session_recv_window_size_
);
3743 EXPECT_EQ(SpdySession::STATE_AVAILABLE
, session
->availability_state_
);
3745 // Second data frame overflows receiving window, causes session to close.
3746 data
.CompleteRead();
3747 base::RunLoop().RunUntilIdle();
3748 EXPECT_EQ(SpdySession::STATE_DRAINING
, session
->availability_state_
);
3751 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3752 // deltas in the receiving window size when checking incoming data frames for
3753 // flow control errors at stream level.
3754 TEST_P(SpdySessionTest
, StreamFlowControlTooMuchDataTwoDataFrames
) {
3755 const int32 stream_max_recv_window_size
= 500;
3756 const int32 first_data_frame_size
= 200;
3757 const int32 second_data_frame_size
= 400;
3759 // First data frame should not trigger a WINDOW_UPDATE.
3760 ASSERT_GT(stream_max_recv_window_size
/ 2, first_data_frame_size
);
3761 // Second data frame would be fine had there been a WINDOW_UPDATE.
3762 ASSERT_GT(stream_max_recv_window_size
, second_data_frame_size
);
3763 // But in fact, they should overflow the receiving window at stream level.
3764 ASSERT_LT(stream_max_recv_window_size
,
3765 first_data_frame_size
+ second_data_frame_size
);
3767 scoped_ptr
<SpdyFrame
> req(
3768 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3769 scoped_ptr
<SpdyFrame
> rst(
3770 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
3771 MockWrite writes
[] = {
3772 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 6),
3775 scoped_ptr
<SpdyFrame
> resp(
3776 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3777 const std::string
first_data_frame(first_data_frame_size
, 'a');
3778 scoped_ptr
<SpdyFrame
> first(spdy_util_
.ConstructSpdyBodyFrame(
3779 1, first_data_frame
.data(), first_data_frame_size
, false));
3780 const std::string
second_data_frame(second_data_frame_size
, 'b');
3781 scoped_ptr
<SpdyFrame
> second(spdy_util_
.ConstructSpdyBodyFrame(
3782 1, second_data_frame
.data(), second_data_frame_size
, false));
3783 MockRead reads
[] = {
3784 CreateMockRead(*resp
, 1),
3785 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
3786 CreateMockRead(*first
, 3),
3787 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
3788 CreateMockRead(*second
, 5),
3789 MockRead(ASYNC
, ERR_IO_PENDING
, 7),
3790 MockRead(ASYNC
, 0, 8),
3793 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3794 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3796 CreateNetworkSession();
3797 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
3798 pool_peer
.SetStreamInitialRecvWindowSize(stream_max_recv_window_size
);
3800 base::WeakPtr
<SpdySession
> session
=
3801 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3802 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM
, session
->flow_control_state());
3804 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
3805 SPDY_REQUEST_RESPONSE_STREAM
, session
, test_url_
, LOWEST
, BoundNetLog());
3806 test::StreamDelegateDoNothing
delegate(spdy_stream
);
3807 spdy_stream
->SetDelegate(&delegate
);
3809 scoped_ptr
<SpdyHeaderBlock
> headers(
3810 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
3811 EXPECT_EQ(ERR_IO_PENDING
, spdy_stream
->SendRequestHeaders(
3812 headers
.Pass(), NO_MORE_DATA_TO_SEND
));
3814 // Request and response.
3815 base::RunLoop().RunUntilIdle();
3816 EXPECT_TRUE(spdy_stream
->IsLocallyClosed());
3817 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3819 // First data frame.
3820 data
.CompleteRead();
3821 base::RunLoop().RunUntilIdle();
3822 EXPECT_TRUE(spdy_stream
->IsLocallyClosed());
3823 EXPECT_EQ(stream_max_recv_window_size
- first_data_frame_size
,
3824 spdy_stream
->recv_window_size());
3826 // Consume first data frame. This does not trigger a WINDOW_UPDATE.
3827 std::string received_data
= delegate
.TakeReceivedData();
3828 EXPECT_EQ(static_cast<size_t>(first_data_frame_size
), received_data
.size());
3829 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3831 // Second data frame overflows receiving window, causes the stream to close.
3832 data
.CompleteRead();
3833 base::RunLoop().RunUntilIdle();
3834 EXPECT_FALSE(spdy_stream
.get());
3837 EXPECT_TRUE(session
);
3838 data
.CompleteRead();
3839 base::RunLoop().RunUntilIdle();
3840 EXPECT_FALSE(session
);
3843 // A delegate that drops any received data.
3844 class DropReceivedDataDelegate
: public test::StreamDelegateSendImmediate
{
3846 DropReceivedDataDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3847 base::StringPiece data
)
3848 : StreamDelegateSendImmediate(stream
, data
) {}
3850 ~DropReceivedDataDelegate() override
{}
3852 // Drop any received data.
3853 void OnDataReceived(scoped_ptr
<SpdyBuffer
> buffer
) override
{}
3856 // Send data back and forth but use a delegate that drops its received
3857 // data. The receive window should still increase to its original
3858 // value, i.e. we shouldn't "leak" receive window bytes.
3859 TEST_P(SpdySessionTest
, SessionFlowControlNoReceiveLeaks
) {
3860 const char kStreamUrl
[] = "http://www.example.org/";
3862 const int32 msg_data_size
= 100;
3863 const std::string
msg_data(msg_data_size
, 'a');
3865 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3866 kStreamUrl
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
3867 scoped_ptr
<SpdyFrame
> msg(
3868 spdy_util_
.ConstructSpdyBodyFrame(
3869 1, msg_data
.data(), msg_data_size
, false));
3870 MockWrite writes
[] = {
3871 CreateMockWrite(*req
, 0),
3872 CreateMockWrite(*msg
, 2),
3875 scoped_ptr
<SpdyFrame
> resp(
3876 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3877 scoped_ptr
<SpdyFrame
> echo(
3878 spdy_util_
.ConstructSpdyBodyFrame(
3879 1, msg_data
.data(), msg_data_size
, false));
3880 scoped_ptr
<SpdyFrame
> window_update(
3881 spdy_util_
.ConstructSpdyWindowUpdate(
3882 kSessionFlowControlStreamId
, msg_data_size
));
3883 MockRead reads
[] = {
3884 CreateMockRead(*resp
, 1),
3885 CreateMockRead(*echo
, 3),
3886 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
3887 MockRead(ASYNC
, 0, 5) // EOF
3890 // Create SpdySession and SpdyStream and send the request.
3891 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3892 session_deps_
.host_resolver
->set_synchronous_mode(true);
3893 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3895 CreateNetworkSession();
3897 base::WeakPtr
<SpdySession
> session
=
3898 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3900 GURL
url(kStreamUrl
);
3901 base::WeakPtr
<SpdyStream
> stream
=
3902 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3903 session
, url
, MEDIUM
, BoundNetLog());
3904 ASSERT_TRUE(stream
.get() != nullptr);
3905 EXPECT_EQ(0u, stream
->stream_id());
3907 DropReceivedDataDelegate
delegate(stream
, msg_data
);
3908 stream
->SetDelegate(&delegate
);
3910 scoped_ptr
<SpdyHeaderBlock
> headers(
3911 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3912 EXPECT_EQ(ERR_IO_PENDING
,
3913 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3914 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3916 const int32 initial_window_size
=
3917 SpdySession::GetDefaultInitialWindowSize(GetParam());
3918 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3919 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3921 base::RunLoop().RunUntilIdle();
3923 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3924 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3927 EXPECT_FALSE(stream
);
3929 EXPECT_EQ(OK
, delegate
.WaitForClose());
3931 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3932 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3934 data
.CompleteRead();
3935 base::RunLoop().RunUntilIdle();
3936 EXPECT_FALSE(session
);
3939 // Send data back and forth but close the stream before its data frame
3940 // can be written to the socket. The send window should then increase
3941 // to its original value, i.e. we shouldn't "leak" send window bytes.
3942 TEST_P(SpdySessionTest
, SessionFlowControlNoSendLeaks
) {
3943 const char kStreamUrl
[] = "http://www.example.org/";
3945 const int32 msg_data_size
= 100;
3946 const std::string
msg_data(msg_data_size
, 'a');
3948 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3949 kStreamUrl
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
3950 MockWrite writes
[] = {
3951 CreateMockWrite(*req
, 0),
3954 scoped_ptr
<SpdyFrame
> resp(
3955 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3956 MockRead reads
[] = {
3957 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3958 CreateMockRead(*resp
, 2),
3959 MockRead(ASYNC
, 0, 3) // EOF
3962 // Create SpdySession and SpdyStream and send the request.
3963 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3964 session_deps_
.host_resolver
->set_synchronous_mode(true);
3965 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3967 CreateNetworkSession();
3969 base::WeakPtr
<SpdySession
> session
=
3970 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3972 GURL
url(kStreamUrl
);
3973 base::WeakPtr
<SpdyStream
> stream
=
3974 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3975 session
, url
, MEDIUM
, BoundNetLog());
3976 ASSERT_TRUE(stream
.get() != nullptr);
3977 EXPECT_EQ(0u, stream
->stream_id());
3979 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3980 stream
->SetDelegate(&delegate
);
3982 scoped_ptr
<SpdyHeaderBlock
> headers(
3983 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3984 EXPECT_EQ(ERR_IO_PENDING
,
3985 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3986 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3988 const int32 initial_window_size
=
3989 SpdySession::GetDefaultInitialWindowSize(GetParam());
3990 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3993 base::RunLoop().RunUntilIdle();
3995 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3997 // Read response, but do not run the message loop, so that the body is not
3998 // written to the socket.
3999 data
.CompleteRead();
4001 EXPECT_EQ(initial_window_size
- msg_data_size
,
4002 session
->session_send_window_size_
);
4004 // Closing the stream should increase the session's send window.
4006 EXPECT_FALSE(stream
);
4008 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
4010 EXPECT_EQ(OK
, delegate
.WaitForClose());
4012 base::RunLoop().RunUntilIdle();
4013 EXPECT_FALSE(session
);
4015 EXPECT_TRUE(data
.AllWriteDataConsumed());
4016 EXPECT_TRUE(data
.AllReadDataConsumed());
4019 // Send data back and forth; the send and receive windows should
4020 // change appropriately.
4021 TEST_P(SpdySessionTest
, SessionFlowControlEndToEnd
) {
4022 const char kStreamUrl
[] = "http://www.example.org/";
4024 const int32 msg_data_size
= 100;
4025 const std::string
msg_data(msg_data_size
, 'a');
4027 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
4028 kStreamUrl
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
4029 scoped_ptr
<SpdyFrame
> msg(
4030 spdy_util_
.ConstructSpdyBodyFrame(
4031 1, msg_data
.data(), msg_data_size
, false));
4032 MockWrite writes
[] = {
4033 CreateMockWrite(*req
, 0),
4034 CreateMockWrite(*msg
, 2),
4037 scoped_ptr
<SpdyFrame
> resp(
4038 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4039 scoped_ptr
<SpdyFrame
> echo(
4040 spdy_util_
.ConstructSpdyBodyFrame(
4041 1, msg_data
.data(), msg_data_size
, false));
4042 scoped_ptr
<SpdyFrame
> window_update(
4043 spdy_util_
.ConstructSpdyWindowUpdate(
4044 kSessionFlowControlStreamId
, msg_data_size
));
4045 MockRead reads
[] = {
4046 CreateMockRead(*resp
, 1),
4047 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4048 CreateMockRead(*echo
, 4),
4049 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4050 CreateMockRead(*window_update
, 6),
4051 MockRead(ASYNC
, ERR_IO_PENDING
, 7),
4052 MockRead(ASYNC
, 0, 8) // EOF
4055 // Create SpdySession and SpdyStream and send the request.
4056 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4057 session_deps_
.host_resolver
->set_synchronous_mode(true);
4058 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4060 CreateNetworkSession();
4062 base::WeakPtr
<SpdySession
> session
=
4063 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4065 GURL
url(kStreamUrl
);
4066 base::WeakPtr
<SpdyStream
> stream
=
4067 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
4068 session
, url
, MEDIUM
, BoundNetLog());
4069 ASSERT_TRUE(stream
.get() != nullptr);
4070 EXPECT_EQ(0u, stream
->stream_id());
4072 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
4073 stream
->SetDelegate(&delegate
);
4075 scoped_ptr
<SpdyHeaderBlock
> headers(
4076 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
4077 EXPECT_EQ(ERR_IO_PENDING
,
4078 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
4079 EXPECT_TRUE(stream
->HasUrlFromHeaders());
4081 const int32 initial_window_size
=
4082 SpdySession::GetDefaultInitialWindowSize(GetParam());
4083 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
4084 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
4085 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
4087 // Send request and message.
4088 base::RunLoop().RunUntilIdle();
4090 EXPECT_EQ(initial_window_size
- msg_data_size
,
4091 session
->session_send_window_size_
);
4092 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
4093 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
4096 data
.CompleteRead();
4097 base::RunLoop().RunUntilIdle();
4099 EXPECT_EQ(initial_window_size
- msg_data_size
,
4100 session
->session_send_window_size_
);
4101 EXPECT_EQ(initial_window_size
- msg_data_size
,
4102 session
->session_recv_window_size_
);
4103 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
4105 // Read window update.
4106 data
.CompleteRead();
4107 base::RunLoop().RunUntilIdle();
4109 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
4110 EXPECT_EQ(initial_window_size
- msg_data_size
,
4111 session
->session_recv_window_size_
);
4112 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
4114 EXPECT_EQ(msg_data
, delegate
.TakeReceivedData());
4116 // Draining the delegate's read queue should increase the session's
4118 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
4119 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
4120 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
4123 EXPECT_FALSE(stream
);
4125 EXPECT_EQ(OK
, delegate
.WaitForClose());
4127 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
4128 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
4129 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
4131 data
.CompleteRead();
4132 base::RunLoop().RunUntilIdle();
4133 EXPECT_FALSE(session
);
4136 // Given a stall function and an unstall function, runs a test to make
4137 // sure that a stream resumes after unstall.
4138 void SpdySessionTest::RunResumeAfterUnstallTest(
4139 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
4140 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
4142 const char kStreamUrl
[] = "http://www.example.org/";
4143 GURL
url(kStreamUrl
);
4145 session_deps_
.host_resolver
->set_synchronous_mode(true);
4147 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
4148 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4149 scoped_ptr
<SpdyFrame
> body(
4150 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
4151 MockWrite writes
[] = {
4152 CreateMockWrite(*req
, 0),
4153 CreateMockWrite(*body
, 1),
4156 scoped_ptr
<SpdyFrame
> resp(
4157 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4158 scoped_ptr
<SpdyFrame
> echo(
4159 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4160 MockRead reads
[] = {
4161 CreateMockRead(*resp
, 2), MockRead(ASYNC
, 0, 3) // EOF
4164 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4165 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4167 CreateNetworkSession();
4168 base::WeakPtr
<SpdySession
> session
=
4169 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4170 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4171 session
->flow_control_state());
4173 base::WeakPtr
<SpdyStream
> stream
=
4174 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4175 session
, url
, LOWEST
, BoundNetLog());
4176 ASSERT_TRUE(stream
.get() != nullptr);
4178 test::StreamDelegateWithBody
delegate(stream
, kBodyDataStringPiece
);
4179 stream
->SetDelegate(&delegate
);
4181 EXPECT_FALSE(stream
->HasUrlFromHeaders());
4182 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4184 scoped_ptr
<SpdyHeaderBlock
> headers(
4185 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4186 EXPECT_EQ(ERR_IO_PENDING
,
4187 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
4188 EXPECT_TRUE(stream
->HasUrlFromHeaders());
4189 EXPECT_EQ(kStreamUrl
, stream
->GetUrlFromHeaders().spec());
4191 stall_function
.Run(session
.get(), stream
.get());
4193 base::RunLoop().RunUntilIdle();
4195 EXPECT_TRUE(stream
->send_stalled_by_flow_control());
4197 unstall_function
.Run(session
.get(), stream
.get(), kBodyDataSize
);
4199 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4201 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
4203 EXPECT_TRUE(delegate
.send_headers_completed());
4204 EXPECT_EQ("200", delegate
.GetResponseHeaderValue(":status"));
4205 EXPECT_EQ(std::string(), delegate
.TakeReceivedData());
4206 EXPECT_FALSE(session
);
4207 EXPECT_TRUE(data
.AllWriteDataConsumed());
4210 // Run the resume-after-unstall test with all possible stall and
4211 // unstall sequences.
4213 TEST_P(SpdySessionTest
, ResumeAfterUnstallSession
) {
4214 RunResumeAfterUnstallTest(
4215 base::Bind(&SpdySessionTest::StallSessionOnly
,
4216 base::Unretained(this)),
4217 base::Bind(&SpdySessionTest::UnstallSessionOnly
,
4218 base::Unretained(this)));
4222 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4223 TEST_P(SpdySessionTest
, ResumeAfterUnstallStream
) {
4224 RunResumeAfterUnstallTest(
4225 base::Bind(&SpdySessionTest::StallStreamOnly
,
4226 base::Unretained(this)),
4227 base::Bind(&SpdySessionTest::UnstallStreamOnly
,
4228 base::Unretained(this)));
4231 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallSessionStream
) {
4232 RunResumeAfterUnstallTest(
4233 base::Bind(&SpdySessionTest::StallSessionStream
,
4234 base::Unretained(this)),
4235 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4236 base::Unretained(this)));
4239 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallSessionStream
) {
4240 RunResumeAfterUnstallTest(
4241 base::Bind(&SpdySessionTest::StallStreamSession
,
4242 base::Unretained(this)),
4243 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4244 base::Unretained(this)));
4247 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallStreamSession
) {
4248 RunResumeAfterUnstallTest(
4249 base::Bind(&SpdySessionTest::StallStreamSession
,
4250 base::Unretained(this)),
4251 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4252 base::Unretained(this)));
4255 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallStreamSession
) {
4256 RunResumeAfterUnstallTest(
4257 base::Bind(&SpdySessionTest::StallSessionStream
,
4258 base::Unretained(this)),
4259 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4260 base::Unretained(this)));
4263 // Cause a stall by reducing the flow control send window to 0. The
4264 // streams should resume in priority order when that window is then
4266 TEST_P(SpdySessionTest
, ResumeByPriorityAfterSendWindowSizeIncrease
) {
4267 const char kStreamUrl
[] = "http://www.example.org/";
4268 GURL
url(kStreamUrl
);
4270 session_deps_
.host_resolver
->set_synchronous_mode(true);
4272 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4273 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4274 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4275 kStreamUrl
, 3, kBodyDataSize
, MEDIUM
, nullptr, 0));
4276 scoped_ptr
<SpdyFrame
> body1(
4277 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
4278 scoped_ptr
<SpdyFrame
> body2(
4279 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4280 MockWrite writes
[] = {
4281 CreateMockWrite(*req1
, 0),
4282 CreateMockWrite(*req2
, 1),
4283 CreateMockWrite(*body2
, 2),
4284 CreateMockWrite(*body1
, 3),
4287 scoped_ptr
<SpdyFrame
> resp1(
4288 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4289 scoped_ptr
<SpdyFrame
> resp2(
4290 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
4291 MockRead reads
[] = {
4292 CreateMockRead(*resp1
, 4),
4293 CreateMockRead(*resp2
, 5),
4294 MockRead(ASYNC
, 0, 6) // EOF
4297 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4298 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4300 CreateNetworkSession();
4301 base::WeakPtr
<SpdySession
> session
=
4302 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4303 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4304 session
->flow_control_state());
4306 base::WeakPtr
<SpdyStream
> stream1
=
4307 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4308 session
, url
, LOWEST
, BoundNetLog());
4309 ASSERT_TRUE(stream1
.get() != nullptr);
4311 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4312 stream1
->SetDelegate(&delegate1
);
4314 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4316 base::WeakPtr
<SpdyStream
> stream2
=
4317 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4318 session
, url
, MEDIUM
, BoundNetLog());
4319 ASSERT_TRUE(stream2
.get() != nullptr);
4321 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4322 stream2
->SetDelegate(&delegate2
);
4324 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4326 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4327 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4329 StallSessionSend(session
.get());
4331 scoped_ptr
<SpdyHeaderBlock
> headers1(
4332 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4333 EXPECT_EQ(ERR_IO_PENDING
,
4334 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4335 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4336 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4338 base::RunLoop().RunUntilIdle();
4339 EXPECT_EQ(1u, stream1
->stream_id());
4340 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4342 scoped_ptr
<SpdyHeaderBlock
> headers2(
4343 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4344 EXPECT_EQ(ERR_IO_PENDING
,
4345 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4346 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4347 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4349 base::RunLoop().RunUntilIdle();
4350 EXPECT_EQ(3u, stream2
->stream_id());
4351 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4353 // This should unstall only stream2.
4354 UnstallSessionSend(session
.get(), kBodyDataSize
);
4356 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4357 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4359 base::RunLoop().RunUntilIdle();
4361 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4362 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4364 // This should then unstall stream1.
4365 UnstallSessionSend(session
.get(), kBodyDataSize
);
4367 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4368 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4370 base::RunLoop().RunUntilIdle();
4372 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4373 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4375 EXPECT_TRUE(delegate1
.send_headers_completed());
4376 EXPECT_EQ("200", delegate1
.GetResponseHeaderValue(":status"));
4377 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4379 EXPECT_TRUE(delegate2
.send_headers_completed());
4380 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4381 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4383 EXPECT_FALSE(session
);
4384 EXPECT_TRUE(data
.AllWriteDataConsumed());
4385 EXPECT_TRUE(data
.AllReadDataConsumed());
4388 // Delegate that closes a given stream after sending its body.
4389 class StreamClosingDelegate
: public test::StreamDelegateWithBody
{
4391 StreamClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
4392 base::StringPiece data
)
4393 : StreamDelegateWithBody(stream
, data
) {}
4395 ~StreamClosingDelegate() override
{}
4397 void set_stream_to_close(const base::WeakPtr
<SpdyStream
>& stream_to_close
) {
4398 stream_to_close_
= stream_to_close
;
4401 void OnDataSent() override
{
4402 test::StreamDelegateWithBody::OnDataSent();
4403 if (stream_to_close_
.get()) {
4404 stream_to_close_
->Close();
4405 EXPECT_FALSE(stream_to_close_
);
4410 base::WeakPtr
<SpdyStream
> stream_to_close_
;
4413 // Cause a stall by reducing the flow control send window to
4414 // 0. Unstalling the session should properly handle deleted streams.
4415 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedStreams
) {
4416 const char kStreamUrl
[] = "http://www.example.org/";
4417 GURL
url(kStreamUrl
);
4419 session_deps_
.host_resolver
->set_synchronous_mode(true);
4421 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4422 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4423 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4424 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, nullptr, 0));
4425 scoped_ptr
<SpdyFrame
> req3(spdy_util_
.ConstructSpdyPost(
4426 kStreamUrl
, 5, kBodyDataSize
, LOWEST
, nullptr, 0));
4427 scoped_ptr
<SpdyFrame
> body2(
4428 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4429 MockWrite writes
[] = {
4430 CreateMockWrite(*req1
, 0),
4431 CreateMockWrite(*req2
, 1),
4432 CreateMockWrite(*req3
, 2),
4433 CreateMockWrite(*body2
, 3),
4436 scoped_ptr
<SpdyFrame
> resp2(
4437 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
4438 MockRead reads
[] = {
4439 CreateMockRead(*resp2
, 4),
4440 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4441 MockRead(ASYNC
, 0, 6) // EOF
4444 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4445 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4447 CreateNetworkSession();
4448 base::WeakPtr
<SpdySession
> session
=
4449 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4450 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4451 session
->flow_control_state());
4453 base::WeakPtr
<SpdyStream
> stream1
=
4454 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4455 session
, url
, LOWEST
, BoundNetLog());
4456 ASSERT_TRUE(stream1
.get() != nullptr);
4458 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4459 stream1
->SetDelegate(&delegate1
);
4461 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4463 base::WeakPtr
<SpdyStream
> stream2
=
4464 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4465 session
, url
, LOWEST
, BoundNetLog());
4466 ASSERT_TRUE(stream2
.get() != nullptr);
4468 StreamClosingDelegate
delegate2(stream2
, kBodyDataStringPiece
);
4469 stream2
->SetDelegate(&delegate2
);
4471 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4473 base::WeakPtr
<SpdyStream
> stream3
=
4474 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4475 session
, url
, LOWEST
, BoundNetLog());
4476 ASSERT_TRUE(stream3
.get() != nullptr);
4478 test::StreamDelegateWithBody
delegate3(stream3
, kBodyDataStringPiece
);
4479 stream3
->SetDelegate(&delegate3
);
4481 EXPECT_FALSE(stream3
->HasUrlFromHeaders());
4483 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4484 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4485 EXPECT_FALSE(stream3
->send_stalled_by_flow_control());
4487 StallSessionSend(session
.get());
4489 scoped_ptr
<SpdyHeaderBlock
> headers1(
4490 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4491 EXPECT_EQ(ERR_IO_PENDING
,
4492 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4493 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4494 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4496 base::RunLoop().RunUntilIdle();
4497 EXPECT_EQ(1u, stream1
->stream_id());
4498 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4500 scoped_ptr
<SpdyHeaderBlock
> headers2(
4501 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4502 EXPECT_EQ(ERR_IO_PENDING
,
4503 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4504 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4505 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4507 base::RunLoop().RunUntilIdle();
4508 EXPECT_EQ(3u, stream2
->stream_id());
4509 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4511 scoped_ptr
<SpdyHeaderBlock
> headers3(
4512 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4513 EXPECT_EQ(ERR_IO_PENDING
,
4514 stream3
->SendRequestHeaders(headers3
.Pass(), MORE_DATA_TO_SEND
));
4515 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
4516 EXPECT_EQ(kStreamUrl
, stream3
->GetUrlFromHeaders().spec());
4518 base::RunLoop().RunUntilIdle();
4519 EXPECT_EQ(5u, stream3
->stream_id());
4520 EXPECT_TRUE(stream3
->send_stalled_by_flow_control());
4522 SpdyStreamId stream_id1
= stream1
->stream_id();
4523 SpdyStreamId stream_id2
= stream2
->stream_id();
4524 SpdyStreamId stream_id3
= stream3
->stream_id();
4526 // Close stream1 preemptively.
4527 session
->CloseActiveStream(stream_id1
, ERR_CONNECTION_CLOSED
);
4528 EXPECT_FALSE(stream1
);
4530 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4531 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4532 EXPECT_TRUE(session
->IsStreamActive(stream_id3
));
4534 // Unstall stream2, which should then close stream3.
4535 delegate2
.set_stream_to_close(stream3
);
4536 UnstallSessionSend(session
.get(), kBodyDataSize
);
4538 base::RunLoop().RunUntilIdle();
4539 EXPECT_FALSE(stream3
);
4541 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4542 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4543 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4544 EXPECT_FALSE(session
->IsStreamActive(stream_id3
));
4546 data
.CompleteRead();
4547 base::RunLoop().RunUntilIdle();
4548 EXPECT_FALSE(stream2
);
4549 EXPECT_FALSE(session
);
4551 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4552 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4553 EXPECT_EQ(OK
, delegate3
.WaitForClose());
4555 EXPECT_TRUE(delegate1
.send_headers_completed());
4556 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4558 EXPECT_TRUE(delegate2
.send_headers_completed());
4559 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4560 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4562 EXPECT_TRUE(delegate3
.send_headers_completed());
4563 EXPECT_EQ(std::string(), delegate3
.TakeReceivedData());
4565 EXPECT_TRUE(data
.AllWriteDataConsumed());
4568 // Cause a stall by reducing the flow control send window to
4569 // 0. Unstalling the session should properly handle the session itself
4571 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedSession
) {
4572 const char kStreamUrl
[] = "http://www.example.org/";
4573 GURL
url(kStreamUrl
);
4575 session_deps_
.host_resolver
->set_synchronous_mode(true);
4577 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4578 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4579 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4580 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, nullptr, 0));
4581 scoped_ptr
<SpdyFrame
> body1(
4582 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4583 MockWrite writes
[] = {
4584 CreateMockWrite(*req1
, 0),
4585 CreateMockWrite(*req2
, 1),
4588 MockRead reads
[] = {
4589 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
4592 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4593 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4595 CreateNetworkSession();
4596 base::WeakPtr
<SpdySession
> session
=
4597 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4598 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4599 session
->flow_control_state());
4601 base::WeakPtr
<SpdyStream
> stream1
=
4602 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4603 session
, url
, LOWEST
, BoundNetLog());
4604 ASSERT_TRUE(stream1
.get() != nullptr);
4606 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4607 stream1
->SetDelegate(&delegate1
);
4609 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4611 base::WeakPtr
<SpdyStream
> stream2
=
4612 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4613 session
, url
, LOWEST
, BoundNetLog());
4614 ASSERT_TRUE(stream2
.get() != nullptr);
4616 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4617 stream2
->SetDelegate(&delegate2
);
4619 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4621 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4622 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4624 StallSessionSend(session
.get());
4626 scoped_ptr
<SpdyHeaderBlock
> headers1(
4627 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4628 EXPECT_EQ(ERR_IO_PENDING
,
4629 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4630 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4631 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4633 base::RunLoop().RunUntilIdle();
4634 EXPECT_EQ(1u, stream1
->stream_id());
4635 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4637 scoped_ptr
<SpdyHeaderBlock
> headers2(
4638 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4639 EXPECT_EQ(ERR_IO_PENDING
,
4640 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4641 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4642 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4644 base::RunLoop().RunUntilIdle();
4645 EXPECT_EQ(3u, stream2
->stream_id());
4646 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4648 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
4651 UnstallSessionSend(session
.get(), kBodyDataSize
);
4653 // Close the session (since we can't do it from within the delegate
4654 // method, since it's in the stream's loop).
4655 session
->CloseSessionOnError(ERR_CONNECTION_CLOSED
, "Closing session");
4656 data
.CompleteRead();
4657 base::RunLoop().RunUntilIdle();
4658 EXPECT_FALSE(session
);
4660 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
4662 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4663 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4665 EXPECT_TRUE(delegate1
.send_headers_completed());
4666 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4668 EXPECT_TRUE(delegate2
.send_headers_completed());
4669 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4671 EXPECT_TRUE(data
.AllWriteDataConsumed());
4674 TEST_P(SpdySessionTest
, GoAwayOnSessionFlowControlError
) {
4675 scoped_ptr
<SpdyFrame
> req(
4676 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4677 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
4678 0, GOAWAY_FLOW_CONTROL_ERROR
,
4679 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4680 "the receive window size of 1"));
4681 MockWrite writes
[] = {
4682 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 4),
4685 scoped_ptr
<SpdyFrame
> resp(
4686 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4687 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4688 MockRead reads
[] = {
4689 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4690 CreateMockRead(*resp
, 2),
4691 CreateMockRead(*body
, 3),
4694 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4695 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4697 CreateNetworkSession();
4699 base::WeakPtr
<SpdySession
> session
=
4700 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4702 GURL
url(kDefaultURL
);
4703 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
4704 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, LOWEST
, BoundNetLog());
4705 ASSERT_TRUE(spdy_stream
.get() != nullptr);
4706 test::StreamDelegateDoNothing
delegate(spdy_stream
);
4707 spdy_stream
->SetDelegate(&delegate
);
4709 scoped_ptr
<SpdyHeaderBlock
> headers(
4710 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
4711 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4714 base::RunLoop().RunUntilIdle();
4716 // Put session on the edge of overflowing it's recv window.
4717 session
->session_recv_window_size_
= 1;
4719 // Read response headers & body. Body overflows the session window, and a
4720 // goaway is written.
4721 data
.CompleteRead();
4722 base::RunLoop().RunUntilIdle();
4724 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR
, delegate
.WaitForClose());
4725 EXPECT_FALSE(session
);
4728 TEST_P(SpdySessionTest
, SplitHeaders
) {
4729 GURL
kStreamUrl("http://www.example.org/foo.dat");
4730 SpdyHeaderBlock headers
;
4731 spdy_util_
.AddUrlToHeaderBlock(kStreamUrl
.spec(), &headers
);
4732 headers
["alpha"] = "beta";
4734 SpdyHeaderBlock request_headers
;
4735 SpdyHeaderBlock response_headers
;
4737 SplitPushedHeadersToRequestAndResponse(
4738 headers
, spdy_util_
.spdy_version(), &request_headers
, &response_headers
);
4740 SpdyHeaderBlock::const_iterator it
= response_headers
.find("alpha");
4741 std::string alpha_val
=
4742 (it
== response_headers
.end()) ? std::string() : it
->second
;
4743 EXPECT_EQ("beta", alpha_val
);
4746 GetUrlFromHeaderBlock(request_headers
, spdy_util_
.spdy_version(), true);
4747 EXPECT_EQ(kStreamUrl
, request_url
);
4750 // Regression. Sorta. Push streams and client streams were sharing a single
4751 // limit for a long time.
4752 TEST_P(SpdySessionTest
, PushedStreamShouldNotCountToClientConcurrencyLimit
) {
4753 SettingsMap new_settings
;
4754 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4755 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, 2);
4756 scoped_ptr
<SpdyFrame
> settings_frame(
4757 spdy_util_
.ConstructSpdySettings(new_settings
));
4758 scoped_ptr
<SpdyFrame
> pushed(spdy_util_
.ConstructSpdyPush(
4759 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4760 MockRead reads
[] = {
4761 CreateMockRead(*settings_frame
, 0),
4762 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4763 CreateMockRead(*pushed
, 4),
4764 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4765 MockRead(ASYNC
, 0, 6),
4768 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
4769 scoped_ptr
<SpdyFrame
> req(
4770 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4771 MockWrite writes
[] = {
4772 CreateMockWrite(*settings_ack
, 1), CreateMockWrite(*req
, 2),
4775 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4776 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4778 CreateNetworkSession();
4780 base::WeakPtr
<SpdySession
> session
=
4781 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4783 // Read the settings frame.
4784 base::RunLoop().RunUntilIdle();
4786 GURL
url1(kDefaultURL
);
4787 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4788 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4789 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4790 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4791 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4792 spdy_stream1
->SetDelegate(&delegate1
);
4794 EXPECT_EQ(0u, session
->num_active_streams());
4795 EXPECT_EQ(1u, session
->num_created_streams());
4796 EXPECT_EQ(0u, session
->num_pushed_streams());
4797 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4799 scoped_ptr
<SpdyHeaderBlock
> headers(
4800 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4801 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4802 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4804 // Run until 1st stream is activated.
4805 EXPECT_EQ(0u, delegate1
.stream_id());
4806 base::RunLoop().RunUntilIdle();
4807 EXPECT_EQ(1u, delegate1
.stream_id());
4808 EXPECT_EQ(1u, session
->num_active_streams());
4809 EXPECT_EQ(0u, session
->num_created_streams());
4810 EXPECT_EQ(0u, session
->num_pushed_streams());
4811 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4813 // Run until pushed stream is created.
4814 data
.CompleteRead();
4815 base::RunLoop().RunUntilIdle();
4816 EXPECT_EQ(2u, session
->num_active_streams());
4817 EXPECT_EQ(0u, session
->num_created_streams());
4818 EXPECT_EQ(1u, session
->num_pushed_streams());
4819 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4821 // Second stream should not be stalled, although we have 2 active streams, but
4822 // one of them is push stream and should not be taken into account when we
4823 // create streams on the client.
4824 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
4825 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4826 EXPECT_TRUE(spdy_stream2
);
4827 EXPECT_EQ(2u, session
->num_active_streams());
4828 EXPECT_EQ(1u, session
->num_created_streams());
4829 EXPECT_EQ(1u, session
->num_pushed_streams());
4830 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4833 data
.CompleteRead();
4834 base::RunLoop().RunUntilIdle();
4835 EXPECT_FALSE(session
);
4838 TEST_P(SpdySessionTest
, RejectPushedStreamExceedingConcurrencyLimit
) {
4839 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4840 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4841 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
4842 nullptr, 0, 4, 1, "http://www.example.org/b.dat"));
4843 MockRead reads
[] = {
4844 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4845 CreateMockRead(*push_a
, 2),
4846 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4847 CreateMockRead(*push_b
, 4),
4848 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
4849 MockRead(ASYNC
, 0, 7),
4852 scoped_ptr
<SpdyFrame
> req(
4853 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4854 scoped_ptr
<SpdyFrame
> rst(
4855 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4856 MockWrite writes
[] = {
4857 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5),
4860 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4861 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4863 CreateNetworkSession();
4865 base::WeakPtr
<SpdySession
> session
=
4866 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4867 session
->set_max_concurrent_pushed_streams(1);
4869 GURL
url1(kDefaultURL
);
4870 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4871 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4872 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4873 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4874 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4875 spdy_stream1
->SetDelegate(&delegate1
);
4877 EXPECT_EQ(0u, session
->num_active_streams());
4878 EXPECT_EQ(1u, session
->num_created_streams());
4879 EXPECT_EQ(0u, session
->num_pushed_streams());
4880 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4882 scoped_ptr
<SpdyHeaderBlock
> headers(
4883 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4884 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4885 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4887 // Run until 1st stream is activated.
4888 EXPECT_EQ(0u, delegate1
.stream_id());
4889 base::RunLoop().RunUntilIdle();
4890 EXPECT_EQ(1u, delegate1
.stream_id());
4891 EXPECT_EQ(1u, session
->num_active_streams());
4892 EXPECT_EQ(0u, session
->num_created_streams());
4893 EXPECT_EQ(0u, session
->num_pushed_streams());
4894 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4896 // Run until pushed stream is created.
4897 data
.CompleteRead();
4898 base::RunLoop().RunUntilIdle();
4899 EXPECT_EQ(2u, session
->num_active_streams());
4900 EXPECT_EQ(0u, session
->num_created_streams());
4901 EXPECT_EQ(1u, session
->num_pushed_streams());
4902 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4904 // Reset incoming pushed stream.
4905 data
.CompleteRead();
4906 base::RunLoop().RunUntilIdle();
4907 EXPECT_EQ(2u, session
->num_active_streams());
4908 EXPECT_EQ(0u, session
->num_created_streams());
4909 EXPECT_EQ(1u, session
->num_pushed_streams());
4910 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4913 data
.CompleteRead();
4914 base::RunLoop().RunUntilIdle();
4915 EXPECT_FALSE(session
);
4918 TEST_P(SpdySessionTest
, IgnoreReservedRemoteStreamsCount
) {
4919 // Streams in reserved remote state exist only in HTTP/2.
4920 if (spdy_util_
.spdy_version() < HTTP2
)
4923 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4924 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4925 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4926 spdy_util_
.AddUrlToHeaderBlock("http://www.example.org/b.dat",
4927 push_headers
.get());
4928 scoped_ptr
<SpdyFrame
> push_b(
4929 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 4, 1));
4930 scoped_ptr
<SpdyFrame
> headers_b(
4931 spdy_util_
.ConstructSpdyPushHeaders(4, nullptr, 0));
4932 MockRead reads
[] = {
4933 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4934 CreateMockRead(*push_a
, 2),
4935 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4936 CreateMockRead(*push_b
, 4),
4937 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4938 CreateMockRead(*headers_b
, 6),
4939 MockRead(ASYNC
, ERR_IO_PENDING
, 8),
4940 MockRead(ASYNC
, 0, 9),
4943 scoped_ptr
<SpdyFrame
> req(
4944 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4945 scoped_ptr
<SpdyFrame
> rst(
4946 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4947 MockWrite writes
[] = {
4948 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 7),
4951 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4952 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4954 CreateNetworkSession();
4956 base::WeakPtr
<SpdySession
> session
=
4957 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4958 session
->set_max_concurrent_pushed_streams(1);
4960 GURL
url1(kDefaultURL
);
4961 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4962 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4963 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4964 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4965 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4966 spdy_stream1
->SetDelegate(&delegate1
);
4968 EXPECT_EQ(0u, session
->num_active_streams());
4969 EXPECT_EQ(1u, session
->num_created_streams());
4970 EXPECT_EQ(0u, session
->num_pushed_streams());
4971 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4973 scoped_ptr
<SpdyHeaderBlock
> headers(
4974 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4975 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4976 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4978 // Run until 1st stream is activated.
4979 EXPECT_EQ(0u, delegate1
.stream_id());
4980 base::RunLoop().RunUntilIdle();
4981 EXPECT_EQ(1u, delegate1
.stream_id());
4982 EXPECT_EQ(1u, session
->num_active_streams());
4983 EXPECT_EQ(0u, session
->num_created_streams());
4984 EXPECT_EQ(0u, session
->num_pushed_streams());
4985 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4987 // Run until pushed stream is created.
4988 data
.CompleteRead();
4989 base::RunLoop().RunUntilIdle();
4990 EXPECT_EQ(2u, session
->num_active_streams());
4991 EXPECT_EQ(0u, session
->num_created_streams());
4992 EXPECT_EQ(1u, session
->num_pushed_streams());
4993 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4995 // Accept promised stream. It should not count towards pushed stream limit.
4996 data
.CompleteRead();
4997 base::RunLoop().RunUntilIdle();
4998 EXPECT_EQ(3u, session
->num_active_streams());
4999 EXPECT_EQ(0u, session
->num_created_streams());
5000 EXPECT_EQ(2u, session
->num_pushed_streams());
5001 EXPECT_EQ(1u, session
->num_active_pushed_streams());
5003 // Reset last pushed stream upon headers reception as it is going to be 2nd,
5004 // while we accept only one.
5005 data
.CompleteRead();
5006 base::RunLoop().RunUntilIdle();
5007 EXPECT_EQ(2u, session
->num_active_streams());
5008 EXPECT_EQ(0u, session
->num_created_streams());
5009 EXPECT_EQ(1u, session
->num_pushed_streams());
5010 EXPECT_EQ(1u, session
->num_active_pushed_streams());
5013 data
.CompleteRead();
5014 base::RunLoop().RunUntilIdle();
5015 EXPECT_FALSE(session
);
5018 TEST_P(SpdySessionTest
, CancelReservedStreamOnHeadersReceived
) {
5019 // Streams in reserved remote state exist only in HTTP/2.
5020 if (spdy_util_
.spdy_version() < HTTP2
)
5023 const char kPushedUrl
[] = "http://www.example.org/a.dat";
5024 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
5025 spdy_util_
.AddUrlToHeaderBlock(kPushedUrl
, push_headers
.get());
5026 scoped_ptr
<SpdyFrame
> push_promise(
5027 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 2, 1));
5028 scoped_ptr
<SpdyFrame
> headers_frame(
5029 spdy_util_
.ConstructSpdyPushHeaders(2, nullptr, 0));
5030 MockRead reads
[] = {
5031 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
5032 CreateMockRead(*push_promise
, 2),
5033 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
5034 CreateMockRead(*headers_frame
, 4),
5035 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
5036 MockRead(ASYNC
, 0, 7),
5039 scoped_ptr
<SpdyFrame
> req(
5040 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
5041 scoped_ptr
<SpdyFrame
> rst(
5042 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
5043 MockWrite writes
[] = {
5044 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5),
5047 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
5048 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5050 CreateNetworkSession();
5052 base::WeakPtr
<SpdySession
> session
=
5053 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
5055 GURL
url1(kDefaultURL
);
5056 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
5057 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
5058 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
5059 EXPECT_EQ(0u, spdy_stream1
->stream_id());
5060 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
5061 spdy_stream1
->SetDelegate(&delegate1
);
5063 EXPECT_EQ(0u, session
->num_active_streams());
5064 EXPECT_EQ(1u, session
->num_created_streams());
5065 EXPECT_EQ(0u, session
->num_pushed_streams());
5066 EXPECT_EQ(0u, session
->num_active_pushed_streams());
5068 scoped_ptr
<SpdyHeaderBlock
> headers(
5069 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
5070 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
5071 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
5073 // Run until 1st stream is activated.
5074 EXPECT_EQ(0u, delegate1
.stream_id());
5075 base::RunLoop().RunUntilIdle();
5076 EXPECT_EQ(1u, delegate1
.stream_id());
5077 EXPECT_EQ(1u, session
->num_active_streams());
5078 EXPECT_EQ(0u, session
->num_created_streams());
5079 EXPECT_EQ(0u, session
->num_pushed_streams());
5080 EXPECT_EQ(0u, session
->num_active_pushed_streams());
5082 // Run until pushed stream is created.
5083 data
.CompleteRead();
5084 base::RunLoop().RunUntilIdle();
5085 EXPECT_EQ(2u, session
->num_active_streams());
5086 EXPECT_EQ(0u, session
->num_created_streams());
5087 EXPECT_EQ(1u, session
->num_pushed_streams());
5088 EXPECT_EQ(0u, session
->num_active_pushed_streams());
5090 base::WeakPtr
<SpdyStream
> pushed_stream
;
5092 session
->GetPushStream(GURL(kPushedUrl
), &pushed_stream
, BoundNetLog());
5094 ASSERT_TRUE(pushed_stream
.get() != nullptr);
5095 test::StreamDelegateCloseOnHeaders
delegate2(pushed_stream
);
5096 pushed_stream
->SetDelegate(&delegate2
);
5098 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
5099 // that all our counters are in consistent state.
5100 data
.CompleteRead();
5101 base::RunLoop().RunUntilIdle();
5102 EXPECT_EQ(1u, session
->num_active_streams());
5103 EXPECT_EQ(0u, session
->num_created_streams());
5104 EXPECT_EQ(0u, session
->num_pushed_streams());
5105 EXPECT_EQ(0u, session
->num_active_pushed_streams());
5108 data
.CompleteRead();
5109 base::RunLoop().RunUntilIdle();
5110 EXPECT_TRUE(data
.AllWriteDataConsumed());
5111 EXPECT_TRUE(data
.AllReadDataConsumed());
5114 TEST_P(SpdySessionTest
, RejectInvalidUnknownFrames
) {
5115 session_deps_
.host_resolver
->set_synchronous_mode(true);
5117 MockRead reads
[] = {
5118 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
5121 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
5122 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5124 CreateNetworkSession();
5125 base::WeakPtr
<SpdySession
> session
=
5126 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
5128 session
->stream_hi_water_mark_
= 5;
5129 // Low client (odd) ids are fine.
5130 EXPECT_TRUE(session
->OnUnknownFrame(3, 0));
5131 // Client id exceeding watermark.
5132 EXPECT_FALSE(session
->OnUnknownFrame(9, 0));
5134 session
->last_accepted_push_stream_id_
= 6;
5135 // Low server (even) ids are fine.
5136 EXPECT_TRUE(session
->OnUnknownFrame(2, 0));
5137 // Server id exceeding last accepted id.
5138 EXPECT_FALSE(session
->OnUnknownFrame(8, 0));
5141 TEST(MapFramerErrorToProtocolError
, MapsValues
) {
5143 SPDY_ERROR_INVALID_CONTROL_FRAME
,
5144 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
5146 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS
,
5147 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
5149 SPDY_ERROR_GOAWAY_FRAME_CORRUPT
,
5150 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT
));
5151 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME
,
5152 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME
));
5155 TEST(MapFramerErrorToNetError
, MapsValue
) {
5156 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR
,
5157 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
5158 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
5159 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE
));
5160 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
5161 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE
));
5163 ERR_SPDY_FRAME_SIZE_ERROR
,
5164 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
));
5167 TEST(MapRstStreamStatusToProtocolError
, MapsValues
) {
5168 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR
,
5169 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR
));
5170 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR
,
5171 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR
));
5172 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM
,
5173 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM
));
5174 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY
,
5175 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY
));
5176 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED
,
5177 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED
));
5180 TEST(MapNetErrorToGoAwayStatus
, MapsValue
) {
5181 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY
,
5182 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
));
5183 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR
,
5184 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR
));
5185 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
,
5186 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR
));
5187 CHECK_EQ(GOAWAY_COMPRESSION_ERROR
,
5188 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR
));
5189 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR
,
5190 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR
));
5191 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED
));
5194 TEST(CanPoolTest
, CanPool
) {
5195 // Load a cert that is valid for:
5200 TransportSecurityState tss
;
5202 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5203 "spdy_pooling.pem");
5205 EXPECT_TRUE(SpdySession::CanPool(
5206 &tss
, ssl_info
, "www.example.org", "www.example.org"));
5207 EXPECT_TRUE(SpdySession::CanPool(
5208 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5209 EXPECT_TRUE(SpdySession::CanPool(
5210 &tss
, ssl_info
, "www.example.org", "mail.example.com"));
5211 EXPECT_FALSE(SpdySession::CanPool(
5212 &tss
, ssl_info
, "www.example.org", "mail.google.com"));
5215 TEST(CanPoolTest
, CanNotPoolWithCertErrors
) {
5216 // Load a cert that is valid for:
5221 TransportSecurityState tss
;
5223 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5224 "spdy_pooling.pem");
5225 ssl_info
.cert_status
= CERT_STATUS_REVOKED
;
5227 EXPECT_FALSE(SpdySession::CanPool(
5228 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5231 TEST(CanPoolTest
, CanNotPoolWithClientCerts
) {
5232 // Load a cert that is valid for:
5237 TransportSecurityState tss
;
5239 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5240 "spdy_pooling.pem");
5241 ssl_info
.client_cert_sent
= true;
5243 EXPECT_FALSE(SpdySession::CanPool(
5244 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5247 TEST(CanPoolTest
, CanNotPoolAcrossETLDsWithChannelID
) {
5248 // Load a cert that is valid for:
5253 TransportSecurityState tss
;
5255 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5256 "spdy_pooling.pem");
5257 ssl_info
.channel_id_sent
= true;
5259 EXPECT_TRUE(SpdySession::CanPool(
5260 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5261 EXPECT_FALSE(SpdySession::CanPool(
5262 &tss
, ssl_info
, "www.example.org", "www.example.com"));
5265 TEST(CanPoolTest
, CanNotPoolWithBadPins
) {
5266 uint8 primary_pin
= 1;
5267 uint8 backup_pin
= 2;
5269 TransportSecurityState tss
;
5270 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5273 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5274 "spdy_pooling.pem");
5275 ssl_info
.is_issued_by_known_root
= true;
5276 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(bad_pin
));
5278 EXPECT_FALSE(SpdySession::CanPool(
5279 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5282 TEST(CanPoolTest
, CanPoolWithAcceptablePins
) {
5283 uint8 primary_pin
= 1;
5284 uint8 backup_pin
= 2;
5285 TransportSecurityState tss
;
5286 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5289 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5290 "spdy_pooling.pem");
5291 ssl_info
.is_issued_by_known_root
= true;
5292 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(primary_pin
));
5294 EXPECT_TRUE(SpdySession::CanPool(
5295 &tss
, ssl_info
, "www.example.org", "mail.example.org"));