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(SpdyStream
* stream
) { StallSessionSend(); }
66 void StallStreamOnly(SpdyStream
* stream
) { StallStreamSend(stream
); }
68 void StallSessionStream(SpdyStream
* stream
) {
70 StallStreamSend(stream
);
73 void StallStreamSession(SpdyStream
* stream
) {
74 StallStreamSend(stream
);
78 void UnstallSessionOnly(SpdyStream
* stream
, int32 delta_window_size
) {
79 UnstallSessionSend(delta_window_size
);
82 void UnstallStreamOnly(SpdyStream
* stream
, int32 delta_window_size
) {
83 UnstallStreamSend(stream
, delta_window_size
);
86 void UnstallSessionStream(SpdyStream
* stream
, int32 delta_window_size
) {
87 UnstallSessionSend(delta_window_size
);
88 UnstallStreamSend(stream
, delta_window_size
);
91 void UnstallStreamSession(SpdyStream
* stream
, int32 delta_window_size
) {
92 UnstallStreamSend(stream
, delta_window_size
);
93 UnstallSessionSend(delta_window_size
);
98 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
99 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
100 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
101 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
102 spdy_util_(GetParam()),
103 session_deps_(GetParam()),
104 spdy_session_pool_(nullptr),
106 test_host_port_pair_(kTestHost
, kTestPort
),
107 key_(test_host_port_pair_
,
108 ProxyServer::Direct(),
109 PRIVACY_MODE_DISABLED
) {}
111 virtual ~SpdySessionTest() {
112 // Important to restore the per-pool limit first, since the pool limit must
113 // always be greater than group limit, and the tests reduce both limits.
114 ClientSocketPoolManager::set_max_sockets_per_pool(
115 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
116 ClientSocketPoolManager::set_max_sockets_per_group(
117 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
120 void SetUp() override
{
121 g_time_delta
= base::TimeDelta();
122 session_deps_
.net_log
= log_
.bound().net_log();
125 void CreateNetworkSession() {
126 DCHECK(!http_session_
);
127 DCHECK(!spdy_session_pool_
);
129 SpdySessionDependencies::SpdyCreateSession(&session_deps_
);
130 spdy_session_pool_
= http_session_
->spdy_session_pool();
133 void CreateInsecureSpdySession() {
136 ::net::CreateInsecureSpdySession(http_session_
, key_
, log_
.bound());
139 void StallSessionSend() {
140 // Reduce the send window size to 0 to stall.
141 while (session_
->session_send_window_size_
> 0) {
142 session_
->DecreaseSendWindowSize(std::min(
143 kMaxSpdyFrameChunkSize
, session_
->session_send_window_size_
));
147 void UnstallSessionSend(int32 delta_window_size
) {
148 session_
->IncreaseSendWindowSize(delta_window_size
);
151 void StallStreamSend(SpdyStream
* stream
) {
152 // Reduce the send window size to 0 to stall.
153 while (stream
->send_window_size() > 0) {
154 stream
->DecreaseSendWindowSize(
155 std::min(kMaxSpdyFrameChunkSize
, stream
->send_window_size()));
159 void UnstallStreamSend(SpdyStream
* stream
, int32 delta_window_size
) {
160 stream
->IncreaseSendWindowSize(delta_window_size
);
163 void RunResumeAfterUnstallTest(
164 const base::Callback
<void(SpdyStream
*)>& stall_function
,
165 const base::Callback
<void(SpdyStream
*, int32
)>& unstall_function
);
167 // Original socket limits. Some tests set these. Safest to always restore
168 // them once each test has been run.
169 int old_max_group_sockets_
;
170 int old_max_pool_sockets_
;
172 SpdyTestUtil spdy_util_
;
173 SpdySessionDependencies session_deps_
;
174 scoped_refptr
<HttpNetworkSession
> http_session_
;
175 base::WeakPtr
<SpdySession
> session_
;
176 SpdySessionPool
* spdy_session_pool_
;
178 HostPortPair test_host_port_pair_
;
180 BoundTestNetLog log_
;
183 INSTANTIATE_TEST_CASE_P(NextProto
,
185 testing::Values(kProtoSPDY31
,
188 // Try to create a SPDY session that will fail during
189 // initialization. Nothing should blow up.
190 TEST_P(SpdySessionTest
, InitialReadError
) {
191 CreateNetworkSession();
193 session_
= TryCreateFakeSpdySessionExpectingFailure(spdy_session_pool_
, key_
,
194 ERR_CONNECTION_CLOSED
);
195 EXPECT_TRUE(session_
);
197 base::RunLoop().RunUntilIdle();
198 EXPECT_FALSE(session_
);
203 // A helper class that vends a callback that, when fired, destroys a
204 // given SpdyStreamRequest.
205 class StreamRequestDestroyingCallback
: public TestCompletionCallbackBase
{
207 StreamRequestDestroyingCallback() {}
209 ~StreamRequestDestroyingCallback() override
{}
211 void SetRequestToDestroy(scoped_ptr
<SpdyStreamRequest
> request
) {
212 request_
= request
.Pass();
215 CompletionCallback
MakeCallback() {
216 return base::Bind(&StreamRequestDestroyingCallback::OnComplete
,
217 base::Unretained(this));
221 void OnComplete(int result
) {
226 scoped_ptr
<SpdyStreamRequest
> request_
;
231 // Request kInitialMaxConcurrentStreams streams. Request two more
232 // streams, but have the callback for one destroy the second stream
233 // request. Close the session. Nothing should blow up. This is a
234 // regression test for http://crbug.com/250841 .
235 TEST_P(SpdySessionTest
, PendingStreamCancellingAnother
) {
236 session_deps_
.host_resolver
->set_synchronous_mode(true);
238 MockRead reads
[] = {MockRead(ASYNC
, 0, 0), };
240 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
241 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
243 CreateNetworkSession();
244 CreateInsecureSpdySession();
246 // Create the maximum number of concurrent streams.
247 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
248 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
249 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
250 ASSERT_TRUE(spdy_stream
!= nullptr);
253 SpdyStreamRequest request1
;
254 scoped_ptr
<SpdyStreamRequest
> request2(new SpdyStreamRequest
);
256 StreamRequestDestroyingCallback callback1
;
259 request1
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
260 MEDIUM
, BoundNetLog(), callback1
.MakeCallback()));
262 // |callback2| is never called.
263 TestCompletionCallback callback2
;
264 ASSERT_EQ(ERR_IO_PENDING
, request2
->StartRequest(
265 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
266 MEDIUM
, BoundNetLog(), callback2
.callback()));
268 callback1
.SetRequestToDestroy(request2
.Pass());
270 session_
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
272 EXPECT_EQ(ERR_ABORTED
, callback1
.WaitForResult());
275 // A session receiving a GOAWAY frame with no active streams should close.
276 TEST_P(SpdySessionTest
, GoAwayWithNoActiveStreams
) {
277 session_deps_
.host_resolver
->set_synchronous_mode(true);
279 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
281 CreateMockRead(*goaway
, 0),
283 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
284 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
286 CreateNetworkSession();
287 CreateInsecureSpdySession();
289 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
291 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
293 // Read and process the GOAWAY frame.
294 base::RunLoop().RunUntilIdle();
295 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
296 EXPECT_FALSE(session_
);
299 // A session receiving a GOAWAY frame immediately with no active
300 // streams should then close.
301 TEST_P(SpdySessionTest
, GoAwayImmediatelyWithNoActiveStreams
) {
302 session_deps_
.host_resolver
->set_synchronous_mode(true);
304 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
306 CreateMockRead(*goaway
, 0, SYNCHRONOUS
), MockRead(ASYNC
, 0, 1) // EOF
308 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
309 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
311 CreateNetworkSession();
313 session_
= TryCreateInsecureSpdySessionExpectingFailure(
314 http_session_
, key_
, ERR_CONNECTION_CLOSED
, BoundNetLog());
315 base::RunLoop().RunUntilIdle();
317 EXPECT_FALSE(session_
);
318 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
319 EXPECT_FALSE(data
.AllReadDataConsumed());
322 // A session receiving a GOAWAY frame with active streams should close
323 // when the last active stream is closed.
324 TEST_P(SpdySessionTest
, GoAwayWithActiveStreams
) {
325 session_deps_
.host_resolver
->set_synchronous_mode(true);
327 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
329 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
330 CreateMockRead(*goaway
, 3),
331 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
332 MockRead(ASYNC
, 0, 5) // EOF
334 scoped_ptr
<SpdyFrame
> req1(
335 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
336 scoped_ptr
<SpdyFrame
> req2(
337 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
338 MockWrite writes
[] = {
339 CreateMockWrite(*req1
, 0),
340 CreateMockWrite(*req2
, 1),
342 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
343 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
345 CreateNetworkSession();
346 CreateInsecureSpdySession();
348 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
350 GURL
url(kDefaultURL
);
351 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
352 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
353 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
354 spdy_stream1
->SetDelegate(&delegate1
);
356 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
357 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
358 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
359 spdy_stream2
->SetDelegate(&delegate2
);
361 scoped_ptr
<SpdyHeaderBlock
> headers(
362 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
363 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
365 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
366 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
367 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
368 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
370 base::RunLoop().RunUntilIdle();
372 EXPECT_EQ(1u, spdy_stream1
->stream_id());
373 EXPECT_EQ(3u, spdy_stream2
->stream_id());
375 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
377 // Read and process the GOAWAY frame.
379 base::RunLoop().RunUntilIdle();
381 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
383 EXPECT_FALSE(session_
->IsStreamActive(3));
384 EXPECT_FALSE(spdy_stream2
);
385 EXPECT_TRUE(session_
->IsStreamActive(1));
387 EXPECT_TRUE(session_
->IsGoingAway());
389 // Should close the session.
390 spdy_stream1
->Close();
391 EXPECT_FALSE(spdy_stream1
);
393 EXPECT_TRUE(session_
);
395 base::RunLoop().RunUntilIdle();
396 EXPECT_FALSE(session_
);
399 // Have a session receive two GOAWAY frames, with the last one causing
400 // the last active stream to be closed. The session should then be
401 // closed after the second GOAWAY frame.
402 TEST_P(SpdySessionTest
, GoAwayTwice
) {
403 session_deps_
.host_resolver
->set_synchronous_mode(true);
405 scoped_ptr
<SpdyFrame
> goaway1(spdy_util_
.ConstructSpdyGoAway(1));
406 scoped_ptr
<SpdyFrame
> goaway2(spdy_util_
.ConstructSpdyGoAway(0));
408 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
409 CreateMockRead(*goaway1
, 3),
410 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
411 CreateMockRead(*goaway2
, 5),
412 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
413 MockRead(ASYNC
, 0, 7) // EOF
415 scoped_ptr
<SpdyFrame
> req1(
416 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
417 scoped_ptr
<SpdyFrame
> req2(
418 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
419 MockWrite writes
[] = {
420 CreateMockWrite(*req1
, 0),
421 CreateMockWrite(*req2
, 1),
423 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
424 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
426 CreateNetworkSession();
427 CreateInsecureSpdySession();
429 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
431 GURL
url(kDefaultURL
);
432 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
433 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
434 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
435 spdy_stream1
->SetDelegate(&delegate1
);
437 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
438 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
439 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
440 spdy_stream2
->SetDelegate(&delegate2
);
442 scoped_ptr
<SpdyHeaderBlock
> headers(
443 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
444 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
446 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
447 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
448 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
449 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
451 base::RunLoop().RunUntilIdle();
453 EXPECT_EQ(1u, spdy_stream1
->stream_id());
454 EXPECT_EQ(3u, spdy_stream2
->stream_id());
456 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
458 // Read and process the first GOAWAY frame.
460 base::RunLoop().RunUntilIdle();
462 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
464 EXPECT_FALSE(session_
->IsStreamActive(3));
465 EXPECT_FALSE(spdy_stream2
);
466 EXPECT_TRUE(session_
->IsStreamActive(1));
467 EXPECT_TRUE(session_
->IsGoingAway());
469 // Read and process the second GOAWAY frame, which should close the
472 base::RunLoop().RunUntilIdle();
473 EXPECT_FALSE(session_
);
476 // Have a session with active streams receive a GOAWAY frame and then
477 // close it. It should handle the close properly (i.e., not try to
478 // make itself unavailable in its pool twice).
479 TEST_P(SpdySessionTest
, GoAwayWithActiveStreamsThenClose
) {
480 session_deps_
.host_resolver
->set_synchronous_mode(true);
482 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
484 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
485 CreateMockRead(*goaway
, 3),
486 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
487 MockRead(ASYNC
, 0, 5) // EOF
489 scoped_ptr
<SpdyFrame
> req1(
490 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
491 scoped_ptr
<SpdyFrame
> req2(
492 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
493 MockWrite writes
[] = {
494 CreateMockWrite(*req1
, 0),
495 CreateMockWrite(*req2
, 1),
497 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
498 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
500 CreateNetworkSession();
501 CreateInsecureSpdySession();
503 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
505 GURL
url(kDefaultURL
);
506 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
507 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
508 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
509 spdy_stream1
->SetDelegate(&delegate1
);
511 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
512 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
513 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
514 spdy_stream2
->SetDelegate(&delegate2
);
516 scoped_ptr
<SpdyHeaderBlock
> headers(
517 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
518 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
520 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
521 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
522 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
523 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
525 base::RunLoop().RunUntilIdle();
527 EXPECT_EQ(1u, spdy_stream1
->stream_id());
528 EXPECT_EQ(3u, spdy_stream2
->stream_id());
530 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
532 // Read and process the GOAWAY frame.
534 base::RunLoop().RunUntilIdle();
536 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
538 EXPECT_FALSE(session_
->IsStreamActive(3));
539 EXPECT_FALSE(spdy_stream2
);
540 EXPECT_TRUE(session_
->IsStreamActive(1));
541 EXPECT_TRUE(session_
->IsGoingAway());
543 session_
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
544 EXPECT_FALSE(spdy_stream1
);
547 base::RunLoop().RunUntilIdle();
548 EXPECT_FALSE(session_
);
551 // Process a joint read buffer which causes the session to begin draining, and
552 // then processes a GOAWAY. The session should gracefully drain. Regression test
553 // for crbug.com/379469
554 TEST_P(SpdySessionTest
, GoAwayWhileDraining
) {
555 session_deps_
.host_resolver
->set_synchronous_mode(true);
557 scoped_ptr
<SpdyFrame
> req(
558 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
559 MockWrite writes
[] = {
560 CreateMockWrite(*req
, 0),
563 scoped_ptr
<SpdyFrame
> resp(
564 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
565 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
566 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
567 size_t joint_size
= goaway
->size() * 2 + body
->size();
569 // Compose interleaved |goaway| and |body| frames into a single read.
570 scoped_ptr
<char[]> buffer(new char[joint_size
]);
573 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
574 out
+= goaway
->size();
575 memcpy(&buffer
[out
], body
->data(), body
->size());
577 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
578 out
+= goaway
->size();
579 ASSERT_EQ(out
, joint_size
);
581 SpdyFrame
joint_frames(buffer
.get(), joint_size
, false);
584 CreateMockRead(*resp
, 1), CreateMockRead(joint_frames
, 2),
585 MockRead(ASYNC
, 0, 3) // EOF
588 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
589 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
591 CreateNetworkSession();
592 CreateInsecureSpdySession();
594 GURL
url(kDefaultURL
);
595 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
596 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
597 test::StreamDelegateDoNothing
delegate(spdy_stream
);
598 spdy_stream
->SetDelegate(&delegate
);
600 scoped_ptr
<SpdyHeaderBlock
> headers(
601 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
602 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
603 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
605 base::RunLoop().RunUntilIdle();
607 // Stream and session closed gracefully.
608 EXPECT_TRUE(delegate
.StreamIsClosed());
609 EXPECT_EQ(OK
, delegate
.WaitForClose());
610 EXPECT_EQ(kUploadData
, delegate
.TakeReceivedData());
611 EXPECT_FALSE(session_
);
614 // Try to create a stream after receiving a GOAWAY frame. It should
616 TEST_P(SpdySessionTest
, CreateStreamAfterGoAway
) {
617 session_deps_
.host_resolver
->set_synchronous_mode(true);
619 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
621 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
622 CreateMockRead(*goaway
, 2),
623 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
624 MockRead(ASYNC
, 0, 4) // EOF
626 scoped_ptr
<SpdyFrame
> req(
627 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
628 MockWrite writes
[] = {
629 CreateMockWrite(*req
, 0),
631 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
632 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
634 CreateNetworkSession();
635 CreateInsecureSpdySession();
637 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
639 GURL
url(kDefaultURL
);
640 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
641 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
642 test::StreamDelegateDoNothing
delegate(spdy_stream
);
643 spdy_stream
->SetDelegate(&delegate
);
645 scoped_ptr
<SpdyHeaderBlock
> headers(
646 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
647 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
648 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
650 base::RunLoop().RunUntilIdle();
652 EXPECT_EQ(1u, spdy_stream
->stream_id());
654 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
656 // Read and process the GOAWAY frame.
658 base::RunLoop().RunUntilIdle();
660 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
661 EXPECT_TRUE(session_
->IsStreamActive(1));
663 SpdyStreamRequest stream_request
;
665 stream_request
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
,
666 MEDIUM
, BoundNetLog(), CompletionCallback());
667 EXPECT_EQ(ERR_FAILED
, rv
);
669 EXPECT_TRUE(session_
);
671 base::RunLoop().RunUntilIdle();
672 EXPECT_FALSE(session_
);
675 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
676 // the stream being refused.
677 TEST_P(SpdySessionTest
, SynStreamAfterGoAway
) {
678 session_deps_
.host_resolver
->set_synchronous_mode(true);
680 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
681 scoped_ptr
<SpdyFrame
> push(
682 spdy_util_
.ConstructSpdyPush(nullptr, 0, 2, 1, kDefaultURL
));
684 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
685 CreateMockRead(*goaway
, 2),
686 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
687 CreateMockRead(*push
, 4),
688 MockRead(ASYNC
, 0, 6) // EOF
690 scoped_ptr
<SpdyFrame
> req(
691 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
692 scoped_ptr
<SpdyFrame
> rst(
693 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
694 MockWrite writes
[] = {CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5)};
695 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
696 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
698 CreateNetworkSession();
699 CreateInsecureSpdySession();
701 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
703 GURL
url(kDefaultURL
);
704 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
705 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
706 test::StreamDelegateDoNothing
delegate(spdy_stream
);
707 spdy_stream
->SetDelegate(&delegate
);
709 scoped_ptr
<SpdyHeaderBlock
> headers(
710 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
711 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
712 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
714 base::RunLoop().RunUntilIdle();
716 EXPECT_EQ(1u, spdy_stream
->stream_id());
718 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
720 // Read and process the GOAWAY frame.
722 base::RunLoop().RunUntilIdle();
724 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
725 EXPECT_TRUE(session_
->IsStreamActive(1));
727 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
730 base::RunLoop().RunUntilIdle();
731 EXPECT_FALSE(session_
);
734 // A session observing a network change with active streams should close
735 // when the last active stream is closed.
736 TEST_P(SpdySessionTest
, NetworkChangeWithActiveStreams
) {
737 session_deps_
.host_resolver
->set_synchronous_mode(true);
740 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
742 scoped_ptr
<SpdyFrame
> req1(
743 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
744 MockWrite writes
[] = {
745 CreateMockWrite(*req1
, 0),
747 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
748 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
750 CreateNetworkSession();
751 CreateInsecureSpdySession();
753 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
755 base::WeakPtr
<SpdyStream
> spdy_stream
=
756 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
, session_
,
757 GURL(kDefaultURL
), MEDIUM
, BoundNetLog());
758 test::StreamDelegateDoNothing
delegate(spdy_stream
);
759 spdy_stream
->SetDelegate(&delegate
);
761 scoped_ptr
<SpdyHeaderBlock
> headers(
762 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
764 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
765 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
767 base::RunLoop().RunUntilIdle();
769 EXPECT_EQ(1u, spdy_stream
->stream_id());
771 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
773 spdy_session_pool_
->OnIPAddressChanged();
775 // The SpdySessionPool behavior differs based on how the OSs reacts to
776 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
777 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
778 // For OSs where the TCP connections will close upon relevant network
779 // changes, SpdySessionPool doesn't need to force them to close, so in these
780 // cases verify the session has become unavailable but remains open and the
781 // pre-existing stream is still active.
782 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
784 EXPECT_TRUE(session_
->IsGoingAway());
786 EXPECT_TRUE(session_
->IsStreamActive(1));
788 // Should close the session.
789 spdy_stream
->Close();
791 EXPECT_FALSE(spdy_stream
);
794 base::RunLoop().RunUntilIdle();
795 EXPECT_FALSE(session_
);
798 TEST_P(SpdySessionTest
, ClientPing
) {
799 session_deps_
.enable_ping
= true;
800 session_deps_
.host_resolver
->set_synchronous_mode(true);
802 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(1, true));
804 CreateMockRead(*read_ping
, 1),
805 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
806 MockRead(ASYNC
, 0, 3) // EOF
808 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
809 MockWrite writes
[] = {
810 CreateMockWrite(*write_ping
, 0),
812 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
813 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
815 CreateNetworkSession();
816 CreateInsecureSpdySession();
818 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
819 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
820 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
821 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
822 spdy_stream1
->SetDelegate(&delegate
);
824 base::TimeTicks before_ping_time
= base::TimeTicks::Now();
826 session_
->set_connection_at_risk_of_loss_time(
827 base::TimeDelta::FromSeconds(-1));
828 session_
->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
830 session_
->SendPrefacePingIfNoneInFlight();
832 base::RunLoop().RunUntilIdle();
834 session_
->CheckPingStatus(before_ping_time
);
836 EXPECT_EQ(0, session_
->pings_in_flight());
837 EXPECT_GE(session_
->next_ping_id(), 1U);
838 EXPECT_FALSE(session_
->check_ping_status_pending());
839 EXPECT_GE(session_
->last_activity_time(), before_ping_time
);
842 base::RunLoop().RunUntilIdle();
844 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
846 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
847 EXPECT_FALSE(session_
);
850 TEST_P(SpdySessionTest
, ServerPing
) {
851 session_deps_
.host_resolver
->set_synchronous_mode(true);
853 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(2, false));
855 CreateMockRead(*read_ping
),
856 MockRead(SYNCHRONOUS
, 0, 0) // EOF
858 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(2, true));
859 MockWrite writes
[] = {
860 CreateMockWrite(*write_ping
),
862 StaticSocketDataProvider
data(
863 reads
, arraysize(reads
), writes
, arraysize(writes
));
864 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
866 CreateNetworkSession();
867 CreateInsecureSpdySession();
869 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
870 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
871 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
872 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
873 spdy_stream1
->SetDelegate(&delegate
);
875 // Flush the read completion task.
876 base::RunLoop().RunUntilIdle();
878 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
880 EXPECT_FALSE(session_
);
881 EXPECT_FALSE(spdy_stream1
);
884 // Cause a ping to be sent out while producing a write. The write loop
885 // should handle this properly, i.e. another DoWriteLoop task should
886 // not be posted. This is a regression test for
887 // http://crbug.com/261043 .
888 TEST_P(SpdySessionTest
, PingAndWriteLoop
) {
889 session_deps_
.enable_ping
= true;
890 session_deps_
.time_func
= TheNearFuture
;
892 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
893 scoped_ptr
<SpdyFrame
> req(
894 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
895 MockWrite writes
[] = {
896 CreateMockWrite(*req
, 0),
897 CreateMockWrite(*write_ping
, 1),
901 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
904 session_deps_
.host_resolver
->set_synchronous_mode(true);
906 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
907 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
909 CreateNetworkSession();
910 CreateInsecureSpdySession();
912 GURL
url(kDefaultURL
);
913 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
914 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, LOWEST
, BoundNetLog());
915 test::StreamDelegateDoNothing
delegate(spdy_stream
);
916 spdy_stream
->SetDelegate(&delegate
);
918 scoped_ptr
<SpdyHeaderBlock
> headers(
919 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
920 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
922 // Shift time so that a ping will be sent out.
923 g_time_delta
= base::TimeDelta::FromSeconds(11);
925 base::RunLoop().RunUntilIdle();
926 session_
->CloseSessionOnError(ERR_ABORTED
, "Aborting");
929 base::RunLoop().RunUntilIdle();
930 EXPECT_FALSE(session_
);
933 TEST_P(SpdySessionTest
, StreamIdSpaceExhausted
) {
934 const SpdyStreamId kLastStreamId
= 0x7fffffff;
935 session_deps_
.host_resolver
->set_synchronous_mode(true);
937 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
938 // fixed to allow for two stream ID assignments, and three concurrent
939 // streams. Four streams are started, and two are activated. Verify the
940 // session goes away, and that the created (but not activated) and
941 // stalled streams are aborted. Also verify the activated streams complete,
942 // at which point the session closes.
944 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyGet(
945 nullptr, 0, false, kLastStreamId
- 2, MEDIUM
, true));
946 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyGet(
947 nullptr, 0, false, kLastStreamId
, MEDIUM
, true));
949 MockWrite writes
[] = {
950 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
953 scoped_ptr
<SpdyFrame
> resp1(
954 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId
- 2));
955 scoped_ptr
<SpdyFrame
> resp2(
956 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId
));
958 scoped_ptr
<SpdyFrame
> body1(
959 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
- 2, true));
960 scoped_ptr
<SpdyFrame
> body2(
961 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
, true));
964 CreateMockRead(*resp1
, 2),
965 CreateMockRead(*resp2
, 3),
966 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
967 CreateMockRead(*body1
, 5),
968 CreateMockRead(*body2
, 6),
969 MockRead(ASYNC
, 0, 7) // EOF
972 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
973 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
975 CreateNetworkSession();
976 CreateInsecureSpdySession();
978 // Fix stream_hi_water_mark_ to allow for two stream activations.
979 session_
->stream_hi_water_mark_
= kLastStreamId
- 2;
980 // Fix max_concurrent_streams to allow for three stream creations.
981 session_
->max_concurrent_streams_
= 3;
983 // Create three streams synchronously, and begin a fourth (which is stalled).
984 GURL
url(kDefaultURL
);
985 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
986 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
987 test::StreamDelegateDoNothing
delegate1(stream1
);
988 stream1
->SetDelegate(&delegate1
);
990 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
991 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
992 test::StreamDelegateDoNothing
delegate2(stream2
);
993 stream2
->SetDelegate(&delegate2
);
995 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
996 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
997 test::StreamDelegateDoNothing
delegate3(stream3
);
998 stream3
->SetDelegate(&delegate3
);
1000 SpdyStreamRequest request4
;
1001 TestCompletionCallback callback4
;
1002 EXPECT_EQ(ERR_IO_PENDING
,
1003 request4
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
,
1004 MEDIUM
, BoundNetLog(), callback4
.callback()));
1006 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1007 EXPECT_EQ(0u, session_
->num_active_streams());
1008 EXPECT_EQ(3u, session_
->num_created_streams());
1009 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(MEDIUM
));
1011 // Activate stream 1. One ID remains available.
1012 stream1
->SendRequestHeaders(
1013 scoped_ptr
<SpdyHeaderBlock
>(
1014 spdy_util_
.ConstructGetHeaderBlock(url
.spec())),
1015 NO_MORE_DATA_TO_SEND
);
1016 base::RunLoop().RunUntilIdle();
1018 EXPECT_EQ(kLastStreamId
- 2u, stream1
->stream_id());
1019 EXPECT_EQ(1u, session_
->num_active_streams());
1020 EXPECT_EQ(2u, session_
->num_created_streams());
1021 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(MEDIUM
));
1023 // Activate stream 2. ID space is exhausted.
1024 stream2
->SendRequestHeaders(
1025 scoped_ptr
<SpdyHeaderBlock
>(
1026 spdy_util_
.ConstructGetHeaderBlock(url
.spec())),
1027 NO_MORE_DATA_TO_SEND
);
1028 base::RunLoop().RunUntilIdle();
1030 // Active streams remain active.
1031 EXPECT_EQ(kLastStreamId
, stream2
->stream_id());
1032 EXPECT_EQ(2u, session_
->num_active_streams());
1034 // Session is going away. Created and stalled streams were aborted.
1035 EXPECT_EQ(SpdySession::STATE_GOING_AWAY
, session_
->availability_state_
);
1036 EXPECT_EQ(ERR_ABORTED
, delegate3
.WaitForClose());
1037 EXPECT_EQ(ERR_ABORTED
, callback4
.WaitForResult());
1038 EXPECT_EQ(0u, session_
->num_created_streams());
1039 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(MEDIUM
));
1041 // Read responses on remaining active streams.
1042 data
.CompleteRead();
1043 base::RunLoop().RunUntilIdle();
1044 EXPECT_EQ(OK
, delegate1
.WaitForClose());
1045 EXPECT_EQ(kUploadData
, delegate1
.TakeReceivedData());
1046 EXPECT_EQ(OK
, delegate2
.WaitForClose());
1047 EXPECT_EQ(kUploadData
, delegate2
.TakeReceivedData());
1049 // Session was destroyed.
1050 EXPECT_FALSE(session_
);
1053 // Verifies that an unstalled pending stream creation racing with a new stream
1054 // creation doesn't violate the maximum stream concurrency. Regression test for
1055 // crbug.com/373858.
1056 TEST_P(SpdySessionTest
, UnstallRacesWithStreamCreation
) {
1057 session_deps_
.host_resolver
->set_synchronous_mode(true);
1059 MockRead reads
[] = {
1060 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1063 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1064 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1066 CreateNetworkSession();
1067 CreateInsecureSpdySession();
1069 // Fix max_concurrent_streams to allow for one open stream.
1070 session_
->max_concurrent_streams_
= 1;
1072 // Create two streams: one synchronously, and one which stalls.
1073 GURL
url(kDefaultURL
);
1074 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
1075 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
1077 SpdyStreamRequest request2
;
1078 TestCompletionCallback callback2
;
1079 EXPECT_EQ(ERR_IO_PENDING
,
1080 request2
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
,
1081 MEDIUM
, BoundNetLog(), callback2
.callback()));
1083 EXPECT_EQ(1u, session_
->num_created_streams());
1084 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(MEDIUM
));
1086 // Cancel the first stream. A callback to unstall the second stream was
1087 // posted. Don't run it yet.
1090 EXPECT_EQ(0u, session_
->num_created_streams());
1091 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(MEDIUM
));
1093 // Create a third stream prior to the second stream's callback.
1094 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
1095 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
1097 EXPECT_EQ(1u, session_
->num_created_streams());
1098 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(MEDIUM
));
1100 // Now run the message loop. The unstalled stream will re-stall itself.
1101 base::RunLoop().RunUntilIdle();
1102 EXPECT_EQ(1u, session_
->num_created_streams());
1103 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(MEDIUM
));
1105 // Cancel the third stream and run the message loop. Verify that the second
1106 // stream creation now completes.
1108 base::RunLoop().RunUntilIdle();
1110 EXPECT_EQ(1u, session_
->num_created_streams());
1111 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(MEDIUM
));
1112 EXPECT_EQ(OK
, callback2
.WaitForResult());
1115 TEST_P(SpdySessionTest
, DeleteExpiredPushStreams
) {
1116 session_deps_
.host_resolver
->set_synchronous_mode(true);
1117 session_deps_
.time_func
= TheNearFuture
;
1119 scoped_ptr
<SpdyFrame
> req(
1120 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
1121 scoped_ptr
<SpdyFrame
> rst(
1122 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
1123 MockWrite writes
[] = {CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5)};
1125 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
1126 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
1127 scoped_ptr
<SpdyFrame
> push_a_body(
1128 spdy_util_
.ConstructSpdyBodyFrame(2, false));
1129 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1130 // iterators inside. See http://crbug.com/443490
1131 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
1132 nullptr, 0, 4, 1, "http://www.example.org/0.dat"));
1133 MockRead reads
[] = {
1134 CreateMockRead(*push_a
, 1),
1135 CreateMockRead(*push_a_body
, 2),
1136 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
1137 CreateMockRead(*push_b
, 4),
1138 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
1139 MockRead(ASYNC
, 0, 7) // EOF
1142 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1143 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1145 CreateNetworkSession();
1146 CreateInsecureSpdySession();
1148 // Process the principal request, and the first push stream request & body.
1149 GURL
url(kDefaultURL
);
1150 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1151 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
1152 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1153 spdy_stream
->SetDelegate(&delegate
);
1155 scoped_ptr
<SpdyHeaderBlock
> headers(
1156 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1157 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1159 base::RunLoop().RunUntilIdle();
1161 // Verify that there is one unclaimed push stream.
1162 EXPECT_EQ(1u, session_
->num_unclaimed_pushed_streams());
1163 SpdySession::PushedStreamMap::iterator iter
=
1164 session_
->unclaimed_pushed_streams_
.find(
1165 GURL("http://www.example.org/a.dat"));
1166 EXPECT_TRUE(session_
->unclaimed_pushed_streams_
.end() != iter
);
1168 if (session_
->flow_control_state_
==
1169 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1170 // Unclaimed push body consumed bytes from the session window.
1172 SpdySession::GetDefaultInitialWindowSize(GetParam()) - kUploadDataSize
,
1173 session_
->session_recv_window_size_
);
1174 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
1177 // Shift time to expire the push stream. Read the second SYN_STREAM,
1178 // and verify a RST_STREAM was written.
1179 g_time_delta
= base::TimeDelta::FromSeconds(301);
1180 data
.CompleteRead();
1181 base::RunLoop().RunUntilIdle();
1183 // Verify that the second pushed stream evicted the first pushed stream.
1184 EXPECT_EQ(1u, session_
->num_unclaimed_pushed_streams());
1185 iter
= session_
->unclaimed_pushed_streams_
.find(
1186 GURL("http://www.example.org/0.dat"));
1187 EXPECT_TRUE(session_
->unclaimed_pushed_streams_
.end() != iter
);
1189 if (session_
->flow_control_state_
==
1190 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1191 // Verify that the session window reclaimed the evicted stream body.
1192 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
1193 session_
->session_recv_window_size_
);
1194 EXPECT_EQ(kUploadDataSize
, session_
->session_unacked_recv_window_bytes_
);
1197 // Read and process EOF.
1198 EXPECT_TRUE(session_
);
1199 data
.CompleteRead();
1200 base::RunLoop().RunUntilIdle();
1201 EXPECT_FALSE(session_
);
1204 TEST_P(SpdySessionTest
, FailedPing
) {
1205 session_deps_
.host_resolver
->set_synchronous_mode(true);
1207 MockRead reads
[] = {
1208 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1210 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
1211 scoped_ptr
<SpdyFrame
> goaway(
1212 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Failed ping."));
1213 MockWrite writes
[] = {CreateMockWrite(*write_ping
), CreateMockWrite(*goaway
)};
1215 StaticSocketDataProvider
data(
1216 reads
, arraysize(reads
), writes
, arraysize(writes
));
1217 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1219 CreateNetworkSession();
1220 CreateInsecureSpdySession();
1222 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1223 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1224 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1225 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
1226 spdy_stream1
->SetDelegate(&delegate
);
1228 session_
->set_connection_at_risk_of_loss_time(
1229 base::TimeDelta::FromSeconds(0));
1230 session_
->set_hung_interval(base::TimeDelta::FromSeconds(0));
1232 // Send a PING frame.
1233 session_
->WritePingFrame(1, false);
1234 EXPECT_LT(0, session_
->pings_in_flight());
1235 EXPECT_GE(session_
->next_ping_id(), 1U);
1236 EXPECT_TRUE(session_
->check_ping_status_pending());
1238 // Assert session is not closed.
1239 EXPECT_TRUE(session_
->IsAvailable());
1241 session_
->num_active_streams() + session_
->num_created_streams());
1242 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1244 // We set last time we have received any data in 1 sec less than now.
1245 // CheckPingStatus will trigger timeout because hung interval is zero.
1246 base::TimeTicks now
= base::TimeTicks::Now();
1247 session_
->last_activity_time_
= now
- base::TimeDelta::FromSeconds(1);
1248 session_
->CheckPingStatus(now
);
1249 base::RunLoop().RunUntilIdle();
1251 EXPECT_FALSE(session_
);
1252 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1253 EXPECT_FALSE(spdy_stream1
);
1256 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1257 // settings frame increasing the max concurrent streams by 1. Make
1258 // sure nothing blows up. This is a regression test for
1259 // http://crbug.com/57331 .
1260 TEST_P(SpdySessionTest
, OnSettings
) {
1261 session_deps_
.host_resolver
->set_synchronous_mode(true);
1263 const SpdySettingsIds kSpdySettingsIds
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1266 std::vector
<MockWrite
> writes
;
1267 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1268 if (GetParam() >= kProtoHTTP2MinimumVersion
) {
1269 writes
.push_back(CreateMockWrite(*settings_ack
, ++seq
));
1272 SettingsMap new_settings
;
1273 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1274 new_settings
[kSpdySettingsIds
] =
1275 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1276 scoped_ptr
<SpdyFrame
> settings_frame(
1277 spdy_util_
.ConstructSpdySettings(new_settings
));
1278 MockRead reads
[] = {
1279 CreateMockRead(*settings_frame
, 0),
1280 MockRead(ASYNC
, ERR_IO_PENDING
, ++seq
),
1281 MockRead(ASYNC
, 0, ++seq
),
1284 SequencedSocketData
data(reads
, arraysize(reads
), vector_as_array(&writes
),
1286 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1288 CreateNetworkSession();
1289 CreateInsecureSpdySession();
1291 // Create the maximum number of concurrent streams.
1292 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1293 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1294 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1295 ASSERT_TRUE(spdy_stream
!= nullptr);
1298 StreamReleaserCallback stream_releaser
;
1299 SpdyStreamRequest request
;
1300 ASSERT_EQ(ERR_IO_PENDING
,
1301 request
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
1302 MEDIUM
, BoundNetLog(),
1303 stream_releaser
.MakeCallback(&request
)));
1305 base::RunLoop().RunUntilIdle();
1307 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1309 data
.CompleteRead();
1310 base::RunLoop().RunUntilIdle();
1311 EXPECT_FALSE(session_
);
1313 EXPECT_TRUE(data
.AllWriteDataConsumed());
1314 EXPECT_TRUE(data
.AllReadDataConsumed());
1317 // Start with a persisted value for max concurrent streams. Receive a
1318 // settings frame increasing the max concurrent streams by 1 and which
1319 // also clears the persisted data. Verify that persisted data is
1321 TEST_P(SpdySessionTest
, ClearSettings
) {
1322 if (spdy_util_
.spdy_version() >= HTTP2
) {
1323 // HTTP/2 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1324 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in HTTP/2.
1327 session_deps_
.host_resolver
->set_synchronous_mode(true);
1329 SettingsMap new_settings
;
1330 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1331 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1332 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1333 scoped_ptr
<SpdyFrame
> settings_frame(
1334 spdy_util_
.ConstructSpdySettings(new_settings
));
1335 uint8 flags
= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
1336 test::SetFrameFlags(settings_frame
.get(), flags
, spdy_util_
.spdy_version());
1337 MockRead reads
[] = {
1338 CreateMockRead(*settings_frame
, 0),
1339 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
1340 MockRead(ASYNC
, 0, 2),
1343 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
1344 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1346 CreateNetworkSession();
1348 // Initialize the SpdySetting with the default.
1349 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1350 test_host_port_pair_
,
1351 SETTINGS_MAX_CONCURRENT_STREAMS
,
1352 SETTINGS_FLAG_PLEASE_PERSIST
,
1353 kInitialMaxConcurrentStreams
);
1356 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1357 test_host_port_pair_
).empty());
1359 CreateInsecureSpdySession();
1361 // Create the maximum number of concurrent streams.
1362 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1363 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1364 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1365 ASSERT_TRUE(spdy_stream
!= nullptr);
1368 StreamReleaserCallback stream_releaser
;
1370 SpdyStreamRequest request
;
1371 ASSERT_EQ(ERR_IO_PENDING
,
1372 request
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
1373 MEDIUM
, BoundNetLog(),
1374 stream_releaser
.MakeCallback(&request
)));
1376 base::RunLoop().RunUntilIdle();
1378 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1380 // Make sure that persisted data is cleared.
1382 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1383 test_host_port_pair_
).empty());
1385 // Make sure session's max_concurrent_streams is correct.
1386 EXPECT_EQ(kInitialMaxConcurrentStreams
+ 1,
1387 session_
->max_concurrent_streams());
1389 data
.CompleteRead();
1390 base::RunLoop().RunUntilIdle();
1391 EXPECT_FALSE(session_
);
1394 // Start with max concurrent streams set to 1. Request two streams.
1395 // When the first completes, have the callback close its stream, which
1396 // should trigger the second stream creation. Then cancel that one
1397 // immediately. Don't crash. This is a regression test for
1398 // http://crbug.com/63532 .
1399 TEST_P(SpdySessionTest
, CancelPendingCreateStream
) {
1400 session_deps_
.host_resolver
->set_synchronous_mode(true);
1402 MockRead reads
[] = {
1403 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1406 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1407 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1409 CreateNetworkSession();
1411 // Initialize the SpdySetting with 1 max concurrent streams.
1412 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1413 test_host_port_pair_
,
1414 SETTINGS_MAX_CONCURRENT_STREAMS
,
1415 SETTINGS_FLAG_PLEASE_PERSIST
,
1418 CreateInsecureSpdySession();
1420 // Leave room for only one more stream to be created.
1421 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
1422 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1423 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1424 ASSERT_TRUE(spdy_stream
!= nullptr);
1427 // Create 2 more streams. First will succeed. Second will be pending.
1428 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1429 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1430 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1432 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1433 // a valgrind error if the callback is invoked when it's not supposed to be.
1434 scoped_ptr
<TestCompletionCallback
> callback(new TestCompletionCallback
);
1436 SpdyStreamRequest request
;
1437 ASSERT_EQ(ERR_IO_PENDING
,
1438 request
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
1439 MEDIUM
, BoundNetLog(), callback
->callback()));
1441 // Release the first one, this will allow the second to be created.
1442 spdy_stream1
->Cancel();
1443 EXPECT_FALSE(spdy_stream1
);
1445 request
.CancelRequest();
1448 // Should not crash when running the pending callback.
1449 base::RunLoop().RunUntilIdle();
1452 TEST_P(SpdySessionTest
, SendInitialDataOnNewSession
) {
1453 session_deps_
.host_resolver
->set_synchronous_mode(true);
1455 MockRead reads
[] = {
1456 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1459 SettingsMap settings
;
1460 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1461 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
1462 scoped_ptr
<SpdyFrame
> settings_frame(
1463 spdy_util_
.ConstructSpdySettings(settings
));
1464 std::vector
<MockWrite
> writes
;
1465 if ((GetParam() >= kProtoHTTP2MinimumVersion
) &&
1466 (GetParam() <= kProtoHTTP2MaximumVersion
)) {
1469 kHttp2ConnectionHeaderPrefix
,
1470 kHttp2ConnectionHeaderPrefixSize
));
1472 writes
.push_back(CreateMockWrite(*settings_frame
));
1474 SettingsMap server_settings
;
1475 const uint32 initial_max_concurrent_streams
= 1;
1476 server_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1477 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED
,
1478 initial_max_concurrent_streams
);
1479 scoped_ptr
<SpdyFrame
> server_settings_frame(
1480 spdy_util_
.ConstructSpdySettings(server_settings
));
1481 if (GetParam() <= kProtoSPDY31
) {
1482 writes
.push_back(CreateMockWrite(*server_settings_frame
));
1485 StaticSocketDataProvider
data(reads
, arraysize(reads
),
1486 vector_as_array(&writes
), writes
.size());
1487 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1489 CreateNetworkSession();
1491 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1492 test_host_port_pair_
,
1493 SETTINGS_MAX_CONCURRENT_STREAMS
,
1494 SETTINGS_FLAG_PLEASE_PERSIST
,
1495 initial_max_concurrent_streams
);
1497 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
1498 pool_peer
.SetEnableSendingInitialData(true);
1500 CreateInsecureSpdySession();
1502 base::RunLoop().RunUntilIdle();
1503 EXPECT_TRUE(data
.AllWriteDataConsumed());
1506 TEST_P(SpdySessionTest
, ClearSettingsStorageOnIPAddressChanged
) {
1507 CreateNetworkSession();
1509 base::WeakPtr
<HttpServerProperties
> test_http_server_properties
=
1510 spdy_session_pool_
->http_server_properties();
1511 SettingsFlagsAndValue
flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST
, 2);
1512 test_http_server_properties
->SetSpdySetting(
1513 test_host_port_pair_
,
1514 SETTINGS_MAX_CONCURRENT_STREAMS
,
1515 SETTINGS_FLAG_PLEASE_PERSIST
,
1517 EXPECT_NE(0u, test_http_server_properties
->GetSpdySettings(
1518 test_host_port_pair_
).size());
1519 spdy_session_pool_
->OnIPAddressChanged();
1520 EXPECT_EQ(0u, test_http_server_properties
->GetSpdySettings(
1521 test_host_port_pair_
).size());
1524 TEST_P(SpdySessionTest
, Initialize
) {
1525 session_deps_
.host_resolver
->set_synchronous_mode(true);
1527 MockRead reads
[] = {
1528 MockRead(ASYNC
, 0, 0) // EOF
1531 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1532 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1534 CreateNetworkSession();
1535 CreateInsecureSpdySession();
1536 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1538 // Flush the read completion task.
1539 base::RunLoop().RunUntilIdle();
1541 TestNetLogEntry::List entries
;
1542 log_
.GetEntries(&entries
);
1543 EXPECT_LT(0u, entries
.size());
1545 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1546 int pos
= ExpectLogContainsSomewhere(
1547 entries
, 0, NetLog::TYPE_HTTP2_SESSION_INITIALIZED
, NetLog::PHASE_NONE
);
1550 TestNetLogEntry entry
= entries
[pos
];
1551 NetLog::Source socket_source
;
1552 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry
.params
.get(),
1554 EXPECT_TRUE(socket_source
.IsValid());
1555 EXPECT_NE(log_
.bound().source().id
, socket_source
.id
);
1558 TEST_P(SpdySessionTest
, NetLogOnSessionGoaway
) {
1559 session_deps_
.host_resolver
->set_synchronous_mode(true);
1561 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
1562 MockRead reads
[] = {
1563 CreateMockRead(*goaway
),
1564 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1567 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1568 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1570 CreateNetworkSession();
1571 CreateInsecureSpdySession();
1572 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1574 // Flush the read completion task.
1575 base::RunLoop().RunUntilIdle();
1577 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1578 EXPECT_FALSE(session_
);
1580 // Check that the NetLog was filled reasonably.
1581 TestNetLogEntry::List entries
;
1582 log_
.GetEntries(&entries
);
1583 EXPECT_LT(0u, entries
.size());
1585 // Check that we logged SPDY_SESSION_CLOSE correctly.
1586 int pos
= ExpectLogContainsSomewhere(
1587 entries
, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE
, NetLog::PHASE_NONE
);
1589 if (pos
< static_cast<int>(entries
.size())) {
1590 TestNetLogEntry entry
= entries
[pos
];
1592 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1593 EXPECT_EQ(OK
, error_code
);
1599 TEST_P(SpdySessionTest
, NetLogOnSessionEOF
) {
1600 session_deps_
.host_resolver
->set_synchronous_mode(true);
1602 MockRead reads
[] = {
1603 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1606 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1607 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1609 CreateNetworkSession();
1610 CreateInsecureSpdySession();
1611 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1613 // Flush the read completion task.
1614 base::RunLoop().RunUntilIdle();
1616 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1617 EXPECT_FALSE(session_
);
1619 // Check that the NetLog was filled reasonably.
1620 TestNetLogEntry::List entries
;
1621 log_
.GetEntries(&entries
);
1622 EXPECT_LT(0u, entries
.size());
1624 // Check that we logged SPDY_SESSION_CLOSE correctly.
1625 int pos
= ExpectLogContainsSomewhere(
1626 entries
, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE
, NetLog::PHASE_NONE
);
1628 if (pos
< static_cast<int>(entries
.size())) {
1629 TestNetLogEntry entry
= entries
[pos
];
1631 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1632 EXPECT_EQ(ERR_CONNECTION_CLOSED
, error_code
);
1638 TEST_P(SpdySessionTest
, SynCompressionHistograms
) {
1639 session_deps_
.enable_compression
= true;
1641 scoped_ptr
<SpdyFrame
> req(
1642 spdy_util_
.ConstructSpdyGet(nullptr, 0, true, 1, MEDIUM
, true));
1643 MockWrite writes
[] = {
1644 CreateMockWrite(*req
, 0),
1646 MockRead reads
[] = {
1647 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
1649 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1650 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1652 CreateNetworkSession();
1653 CreateInsecureSpdySession();
1655 GURL
url(kDefaultURL
);
1656 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1657 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
1658 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1659 spdy_stream
->SetDelegate(&delegate
);
1661 scoped_ptr
<SpdyHeaderBlock
> headers(
1662 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1663 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1664 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
1666 // Write request headers & capture resulting histogram update.
1667 base::HistogramTester histogram_tester
;
1669 base::RunLoop().RunUntilIdle();
1670 // Regression test of compression performance under the request fixture.
1671 switch (spdy_util_
.spdy_version()) {
1673 histogram_tester
.ExpectBucketCount(
1674 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1677 histogram_tester
.ExpectBucketCount(
1678 "Net.SpdySynStreamCompressionPercentage", 81, 1);
1684 // Read and process EOF.
1685 EXPECT_TRUE(session_
);
1686 data
.CompleteRead();
1687 base::RunLoop().RunUntilIdle();
1688 EXPECT_FALSE(session_
);
1691 // Queue up a low-priority SYN_STREAM followed by a high-priority
1692 // one. The high priority one should still send first and receive
1694 TEST_P(SpdySessionTest
, OutOfOrderSynStreams
) {
1695 // Construct the request.
1696 scoped_ptr
<SpdyFrame
> req_highest(
1697 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, HIGHEST
, true));
1698 scoped_ptr
<SpdyFrame
> req_lowest(
1699 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST
, true));
1700 MockWrite writes
[] = {
1701 CreateMockWrite(*req_highest
, 0),
1702 CreateMockWrite(*req_lowest
, 1),
1705 scoped_ptr
<SpdyFrame
> resp_highest(
1706 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
1707 scoped_ptr
<SpdyFrame
> body_highest(
1708 spdy_util_
.ConstructSpdyBodyFrame(1, true));
1709 scoped_ptr
<SpdyFrame
> resp_lowest(
1710 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
1711 scoped_ptr
<SpdyFrame
> body_lowest(
1712 spdy_util_
.ConstructSpdyBodyFrame(3, true));
1713 MockRead reads
[] = {
1714 CreateMockRead(*resp_highest
, 2),
1715 CreateMockRead(*body_highest
, 3),
1716 CreateMockRead(*resp_lowest
, 4),
1717 CreateMockRead(*body_lowest
, 5),
1718 MockRead(ASYNC
, 0, 6) // EOF
1721 session_deps_
.host_resolver
->set_synchronous_mode(true);
1723 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1724 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1726 CreateNetworkSession();
1727 CreateInsecureSpdySession();
1729 GURL
url(kDefaultURL
);
1731 base::WeakPtr
<SpdyStream
> spdy_stream_lowest
= CreateStreamSynchronously(
1732 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, LOWEST
, BoundNetLog());
1733 ASSERT_TRUE(spdy_stream_lowest
);
1734 EXPECT_EQ(0u, spdy_stream_lowest
->stream_id());
1735 test::StreamDelegateDoNothing
delegate_lowest(spdy_stream_lowest
);
1736 spdy_stream_lowest
->SetDelegate(&delegate_lowest
);
1738 base::WeakPtr
<SpdyStream
> spdy_stream_highest
= CreateStreamSynchronously(
1739 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, HIGHEST
, BoundNetLog());
1740 ASSERT_TRUE(spdy_stream_highest
);
1741 EXPECT_EQ(0u, spdy_stream_highest
->stream_id());
1742 test::StreamDelegateDoNothing
delegate_highest(spdy_stream_highest
);
1743 spdy_stream_highest
->SetDelegate(&delegate_highest
);
1745 // Queue the lower priority one first.
1747 scoped_ptr
<SpdyHeaderBlock
> headers_lowest(
1748 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1749 spdy_stream_lowest
->SendRequestHeaders(
1750 headers_lowest
.Pass(), NO_MORE_DATA_TO_SEND
);
1751 EXPECT_TRUE(spdy_stream_lowest
->HasUrlFromHeaders());
1753 scoped_ptr
<SpdyHeaderBlock
> headers_highest(
1754 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1755 spdy_stream_highest
->SendRequestHeaders(
1756 headers_highest
.Pass(), NO_MORE_DATA_TO_SEND
);
1757 EXPECT_TRUE(spdy_stream_highest
->HasUrlFromHeaders());
1759 base::RunLoop().RunUntilIdle();
1761 EXPECT_FALSE(spdy_stream_lowest
);
1762 EXPECT_FALSE(spdy_stream_highest
);
1763 EXPECT_EQ(3u, delegate_lowest
.stream_id());
1764 EXPECT_EQ(1u, delegate_highest
.stream_id());
1767 TEST_P(SpdySessionTest
, CancelStream
) {
1768 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1769 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1770 scoped_ptr
<SpdyFrame
> req2(
1771 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
1772 MockWrite writes
[] = {
1773 CreateMockWrite(*req2
, 0),
1776 scoped_ptr
<SpdyFrame
> resp2(
1777 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
1778 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1779 MockRead reads
[] = {
1780 CreateMockRead(*resp2
, 1),
1781 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
1782 CreateMockRead(*body2
, 3),
1783 MockRead(ASYNC
, 0, 4) // EOF
1786 session_deps_
.host_resolver
->set_synchronous_mode(true);
1788 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1789 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1791 CreateNetworkSession();
1792 CreateInsecureSpdySession();
1794 GURL
url1(kDefaultURL
);
1795 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1796 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url1
, HIGHEST
, BoundNetLog());
1797 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1798 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1799 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
1800 spdy_stream1
->SetDelegate(&delegate1
);
1802 GURL
url2(kDefaultURL
);
1803 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
1804 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url2
, LOWEST
, BoundNetLog());
1805 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
1806 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1807 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
1808 spdy_stream2
->SetDelegate(&delegate2
);
1810 scoped_ptr
<SpdyHeaderBlock
> headers(
1811 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1812 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1813 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1815 scoped_ptr
<SpdyHeaderBlock
> headers2(
1816 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1817 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1818 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1820 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1822 spdy_stream1
->Cancel();
1823 EXPECT_FALSE(spdy_stream1
);
1825 EXPECT_EQ(0u, delegate1
.stream_id());
1827 base::RunLoop().RunUntilIdle();
1829 EXPECT_EQ(0u, delegate1
.stream_id());
1830 EXPECT_EQ(1u, delegate2
.stream_id());
1832 spdy_stream2
->Cancel();
1833 EXPECT_FALSE(spdy_stream2
);
1836 // Create two streams that are set to re-close themselves on close,
1837 // and then close the session. Nothing should blow up. Also a
1838 // regression test for http://crbug.com/139518 .
1839 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedSelfClosingStreams
) {
1840 session_deps_
.host_resolver
->set_synchronous_mode(true);
1843 // No actual data will be sent.
1844 MockWrite writes
[] = {
1845 MockWrite(ASYNC
, 0, 1) // EOF
1848 MockRead reads
[] = {
1849 MockRead(ASYNC
, 0, 0) // EOF
1851 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1852 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1854 CreateNetworkSession();
1855 CreateInsecureSpdySession();
1857 GURL
url1(kDefaultURL
);
1858 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1859 SPDY_BIDIRECTIONAL_STREAM
, session_
, url1
, HIGHEST
, BoundNetLog());
1860 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1861 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1863 GURL
url2(kDefaultURL
);
1864 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
1865 SPDY_BIDIRECTIONAL_STREAM
, session_
, url2
, LOWEST
, BoundNetLog());
1866 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
1867 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1869 test::ClosingDelegate
delegate1(spdy_stream1
);
1870 spdy_stream1
->SetDelegate(&delegate1
);
1872 test::ClosingDelegate
delegate2(spdy_stream2
);
1873 spdy_stream2
->SetDelegate(&delegate2
);
1875 scoped_ptr
<SpdyHeaderBlock
> headers(
1876 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1877 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1878 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1880 scoped_ptr
<SpdyHeaderBlock
> headers2(
1881 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1882 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1883 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1885 // Ensure that the streams have not yet been activated and assigned an id.
1886 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1887 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1889 // Ensure we don't crash while closing the session.
1890 session_
->CloseSessionOnError(ERR_ABORTED
, std::string());
1892 EXPECT_FALSE(spdy_stream1
);
1893 EXPECT_FALSE(spdy_stream2
);
1895 EXPECT_TRUE(delegate1
.StreamIsClosed());
1896 EXPECT_TRUE(delegate2
.StreamIsClosed());
1898 base::RunLoop().RunUntilIdle();
1899 EXPECT_FALSE(session_
);
1902 // Create two streams that are set to close each other on close, and
1903 // then close the session. Nothing should blow up.
1904 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedMutuallyClosingStreams
) {
1905 session_deps_
.host_resolver
->set_synchronous_mode(true);
1907 SequencedSocketData
data(nullptr, 0, nullptr, 0);
1908 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1910 CreateNetworkSession();
1911 CreateInsecureSpdySession();
1913 GURL
url1(kDefaultURL
);
1914 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1915 SPDY_BIDIRECTIONAL_STREAM
, session_
, url1
, HIGHEST
, BoundNetLog());
1916 ASSERT_TRUE(spdy_stream1
);
1917 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1919 GURL
url2(kDefaultURL
);
1920 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
1921 SPDY_BIDIRECTIONAL_STREAM
, session_
, url2
, LOWEST
, BoundNetLog());
1922 ASSERT_TRUE(spdy_stream2
);
1923 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1925 // Make |spdy_stream1| close |spdy_stream2|.
1926 test::ClosingDelegate
delegate1(spdy_stream2
);
1927 spdy_stream1
->SetDelegate(&delegate1
);
1929 // Make |spdy_stream2| close |spdy_stream1|.
1930 test::ClosingDelegate
delegate2(spdy_stream1
);
1931 spdy_stream2
->SetDelegate(&delegate2
);
1933 scoped_ptr
<SpdyHeaderBlock
> headers(
1934 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1935 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1936 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1938 scoped_ptr
<SpdyHeaderBlock
> headers2(
1939 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1940 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1941 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1943 // Ensure that the streams have not yet been activated and assigned an id.
1944 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1945 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1947 // Ensure we don't crash while closing the session.
1948 session_
->CloseSessionOnError(ERR_ABORTED
, std::string());
1950 EXPECT_FALSE(spdy_stream1
);
1951 EXPECT_FALSE(spdy_stream2
);
1953 EXPECT_TRUE(delegate1
.StreamIsClosed());
1954 EXPECT_TRUE(delegate2
.StreamIsClosed());
1956 base::RunLoop().RunUntilIdle();
1957 EXPECT_FALSE(session_
);
1960 // Create two streams that are set to re-close themselves on close,
1961 // activate them, and then close the session. Nothing should blow up.
1962 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedSelfClosingStreams
) {
1963 session_deps_
.host_resolver
->set_synchronous_mode(true);
1965 scoped_ptr
<SpdyFrame
> req1(
1966 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
1967 scoped_ptr
<SpdyFrame
> req2(
1968 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
1969 MockWrite writes
[] = {
1970 CreateMockWrite(*req1
, 0),
1971 CreateMockWrite(*req2
, 1),
1974 MockRead reads
[] = {
1975 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
1978 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1979 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1981 CreateNetworkSession();
1982 CreateInsecureSpdySession();
1984 GURL
url1(kDefaultURL
);
1985 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1986 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url1
, MEDIUM
, BoundNetLog());
1987 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1988 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1990 GURL
url2(kDefaultURL
);
1991 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
1992 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url2
, MEDIUM
, BoundNetLog());
1993 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
1994 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1996 test::ClosingDelegate
delegate1(spdy_stream1
);
1997 spdy_stream1
->SetDelegate(&delegate1
);
1999 test::ClosingDelegate
delegate2(spdy_stream2
);
2000 spdy_stream2
->SetDelegate(&delegate2
);
2002 scoped_ptr
<SpdyHeaderBlock
> headers(
2003 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2004 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2005 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2007 scoped_ptr
<SpdyHeaderBlock
> headers2(
2008 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2009 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2010 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2012 // Ensure that the streams have not yet been activated and assigned an id.
2013 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2014 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2016 base::RunLoop().RunUntilIdle();
2018 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2019 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2021 // Ensure we don't crash while closing the session.
2022 session_
->CloseSessionOnError(ERR_ABORTED
, std::string());
2024 EXPECT_FALSE(spdy_stream1
);
2025 EXPECT_FALSE(spdy_stream2
);
2027 EXPECT_TRUE(delegate1
.StreamIsClosed());
2028 EXPECT_TRUE(delegate2
.StreamIsClosed());
2030 EXPECT_TRUE(session_
);
2031 data
.CompleteRead();
2032 base::RunLoop().RunUntilIdle();
2033 EXPECT_FALSE(session_
);
2036 // Create two streams that are set to close each other on close,
2037 // activate them, and then close the session. Nothing should blow up.
2038 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedMutuallyClosingStreams
) {
2039 session_deps_
.host_resolver
->set_synchronous_mode(true);
2041 scoped_ptr
<SpdyFrame
> req1(
2042 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2043 scoped_ptr
<SpdyFrame
> req2(
2044 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
2045 MockWrite writes
[] = {
2046 CreateMockWrite(*req1
, 0),
2047 CreateMockWrite(*req2
, 1),
2050 MockRead reads
[] = {
2051 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
2054 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2055 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2057 CreateNetworkSession();
2058 CreateInsecureSpdySession();
2060 GURL
url1(kDefaultURL
);
2061 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2062 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url1
, MEDIUM
, BoundNetLog());
2063 ASSERT_TRUE(spdy_stream1
);
2064 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2066 GURL
url2(kDefaultURL
);
2067 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
2068 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url2
, MEDIUM
, BoundNetLog());
2069 ASSERT_TRUE(spdy_stream2
);
2070 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2072 // Make |spdy_stream1| close |spdy_stream2|.
2073 test::ClosingDelegate
delegate1(spdy_stream2
);
2074 spdy_stream1
->SetDelegate(&delegate1
);
2076 // Make |spdy_stream2| close |spdy_stream1|.
2077 test::ClosingDelegate
delegate2(spdy_stream1
);
2078 spdy_stream2
->SetDelegate(&delegate2
);
2080 scoped_ptr
<SpdyHeaderBlock
> headers(
2081 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2082 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2083 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2085 scoped_ptr
<SpdyHeaderBlock
> headers2(
2086 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2087 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2088 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2090 // Ensure that the streams have not yet been activated and assigned an id.
2091 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2092 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2094 base::RunLoop().RunUntilIdle();
2096 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2097 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2099 // Ensure we don't crash while closing the session.
2100 session_
->CloseSessionOnError(ERR_ABORTED
, std::string());
2102 EXPECT_FALSE(spdy_stream1
);
2103 EXPECT_FALSE(spdy_stream2
);
2105 EXPECT_TRUE(delegate1
.StreamIsClosed());
2106 EXPECT_TRUE(delegate2
.StreamIsClosed());
2108 EXPECT_TRUE(session_
);
2109 data
.CompleteRead();
2110 base::RunLoop().RunUntilIdle();
2111 EXPECT_FALSE(session_
);
2114 // Delegate that closes a given session when the stream is closed.
2115 class SessionClosingDelegate
: public test::StreamDelegateDoNothing
{
2117 SessionClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
2118 const base::WeakPtr
<SpdySession
>& session_to_close
)
2119 : StreamDelegateDoNothing(stream
),
2120 session_to_close_(session_to_close
) {}
2122 ~SessionClosingDelegate() override
{}
2124 void OnClose(int status
) override
{
2125 session_to_close_
->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR
, "Error");
2129 base::WeakPtr
<SpdySession
> session_to_close_
;
2132 // Close an activated stream that closes its session. Nothing should
2133 // blow up. This is a regression test for https://crbug.com/263691.
2134 TEST_P(SpdySessionTest
, CloseActivatedStreamThatClosesSession
) {
2135 session_deps_
.host_resolver
->set_synchronous_mode(true);
2137 scoped_ptr
<SpdyFrame
> req(
2138 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2139 scoped_ptr
<SpdyFrame
> rst(
2140 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2141 scoped_ptr
<SpdyFrame
> goaway(
2142 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Error"));
2143 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2144 // despite being queued second.
2145 MockWrite writes
[] = {
2146 CreateMockWrite(*req
, 0),
2147 CreateMockWrite(*goaway
, 1),
2148 CreateMockWrite(*rst
, 3),
2151 MockRead reads
[] = {
2152 MockRead(ASYNC
, 0, 2) // EOF
2154 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2155 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2157 CreateNetworkSession();
2158 CreateInsecureSpdySession();
2160 GURL
url(kDefaultURL
);
2161 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
2162 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
2163 ASSERT_TRUE(spdy_stream
.get() != nullptr);
2164 EXPECT_EQ(0u, spdy_stream
->stream_id());
2166 SessionClosingDelegate
delegate(spdy_stream
, session_
);
2167 spdy_stream
->SetDelegate(&delegate
);
2169 scoped_ptr
<SpdyHeaderBlock
> headers(
2170 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
2171 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2172 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
2174 EXPECT_EQ(0u, spdy_stream
->stream_id());
2176 base::RunLoop().RunUntilIdle();
2178 EXPECT_EQ(1u, spdy_stream
->stream_id());
2180 // Ensure we don't crash while closing the stream (which closes the
2182 spdy_stream
->Cancel();
2184 EXPECT_FALSE(spdy_stream
);
2185 EXPECT_TRUE(delegate
.StreamIsClosed());
2187 // Write the RST_STREAM & GOAWAY.
2188 base::RunLoop().RunUntilIdle();
2189 EXPECT_TRUE(data
.AllWriteDataConsumed());
2190 EXPECT_TRUE(data
.AllReadDataConsumed());
2193 TEST_P(SpdySessionTest
, VerifyDomainAuthentication
) {
2194 session_deps_
.host_resolver
->set_synchronous_mode(true);
2196 SequencedSocketData
data(nullptr, 0, nullptr, 0);
2197 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2199 // Load a cert that is valid for:
2203 base::FilePath certs_dir
= GetTestCertsDirectory();
2204 scoped_refptr
<X509Certificate
> test_cert(
2205 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2206 ASSERT_NE(static_cast<X509Certificate
*>(nullptr), test_cert
.get());
2208 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2209 ssl
.cert
= test_cert
;
2210 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2212 CreateNetworkSession();
2214 session_
= CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2216 EXPECT_TRUE(session_
->VerifyDomainAuthentication("www.example.org"));
2217 EXPECT_TRUE(session_
->VerifyDomainAuthentication("mail.example.org"));
2218 EXPECT_TRUE(session_
->VerifyDomainAuthentication("mail.example.com"));
2219 EXPECT_FALSE(session_
->VerifyDomainAuthentication("mail.google.com"));
2222 TEST_P(SpdySessionTest
, ConnectionPooledWithTlsChannelId
) {
2223 session_deps_
.host_resolver
->set_synchronous_mode(true);
2225 SequencedSocketData
data(nullptr, 0, nullptr, 0);
2226 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2228 // Load a cert that is valid for:
2232 base::FilePath certs_dir
= GetTestCertsDirectory();
2233 scoped_refptr
<X509Certificate
> test_cert(
2234 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2235 ASSERT_NE(static_cast<X509Certificate
*>(nullptr), test_cert
.get());
2237 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2238 ssl
.channel_id_sent
= true;
2239 ssl
.cert
= test_cert
;
2240 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2242 CreateNetworkSession();
2244 session_
= CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2246 EXPECT_TRUE(session_
->VerifyDomainAuthentication("www.example.org"));
2247 EXPECT_TRUE(session_
->VerifyDomainAuthentication("mail.example.org"));
2248 EXPECT_FALSE(session_
->VerifyDomainAuthentication("mail.example.com"));
2249 EXPECT_FALSE(session_
->VerifyDomainAuthentication("mail.google.com"));
2252 TEST_P(SpdySessionTest
, CloseTwoStalledCreateStream
) {
2253 // TODO(rtenneti): Define a helper class/methods and move the common code in
2255 SettingsMap new_settings
;
2256 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
2257 const uint32 max_concurrent_streams
= 1;
2258 new_settings
[kSpdySettingsIds1
] =
2259 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
2261 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
2262 scoped_ptr
<SpdyFrame
> req1(
2263 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
2264 scoped_ptr
<SpdyFrame
> req2(
2265 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST
, true));
2266 scoped_ptr
<SpdyFrame
> req3(
2267 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 5, LOWEST
, true));
2268 MockWrite writes
[] = {
2269 CreateMockWrite(*settings_ack
, 1),
2270 CreateMockWrite(*req1
, 2),
2271 CreateMockWrite(*req2
, 5),
2272 CreateMockWrite(*req3
, 8),
2275 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2277 scoped_ptr
<SpdyFrame
> settings_frame(
2278 spdy_util_
.ConstructSpdySettings(new_settings
));
2280 scoped_ptr
<SpdyFrame
> resp1(
2281 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2282 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2284 scoped_ptr
<SpdyFrame
> resp2(
2285 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
2286 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
2288 scoped_ptr
<SpdyFrame
> resp3(
2289 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 5));
2290 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
2292 MockRead reads
[] = {
2293 CreateMockRead(*settings_frame
, 0),
2294 CreateMockRead(*resp1
, 3),
2295 CreateMockRead(*body1
, 4),
2296 CreateMockRead(*resp2
, 6),
2297 CreateMockRead(*body2
, 7),
2298 CreateMockRead(*resp3
, 9),
2299 CreateMockRead(*body3
, 10),
2300 MockRead(ASYNC
, ERR_IO_PENDING
, 11),
2301 MockRead(ASYNC
, 0, 12) // EOF
2304 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2305 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2307 CreateNetworkSession();
2308 CreateInsecureSpdySession();
2310 // Read the settings frame.
2311 base::RunLoop().RunUntilIdle();
2313 GURL
url1(kDefaultURL
);
2314 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2315 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url1
, LOWEST
, BoundNetLog());
2316 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2317 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2318 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2319 spdy_stream1
->SetDelegate(&delegate1
);
2321 TestCompletionCallback callback2
;
2322 GURL
url2(kDefaultURL
);
2323 SpdyStreamRequest request2
;
2324 ASSERT_EQ(ERR_IO_PENDING
,
2325 request2
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
, url2
,
2326 LOWEST
, BoundNetLog(), callback2
.callback()));
2328 TestCompletionCallback callback3
;
2329 GURL
url3(kDefaultURL
);
2330 SpdyStreamRequest request3
;
2331 ASSERT_EQ(ERR_IO_PENDING
,
2332 request3
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
, url3
,
2333 LOWEST
, BoundNetLog(), callback3
.callback()));
2335 EXPECT_EQ(0u, session_
->num_active_streams());
2336 EXPECT_EQ(1u, session_
->num_created_streams());
2337 EXPECT_EQ(2u, session_
->pending_create_stream_queue_size(LOWEST
));
2339 scoped_ptr
<SpdyHeaderBlock
> headers(
2340 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2341 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2342 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2344 // Run until 1st stream is activated and then closed.
2345 EXPECT_EQ(0u, delegate1
.stream_id());
2346 base::RunLoop().RunUntilIdle();
2347 EXPECT_FALSE(spdy_stream1
);
2348 EXPECT_EQ(1u, delegate1
.stream_id());
2350 EXPECT_EQ(0u, session_
->num_active_streams());
2351 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(LOWEST
));
2353 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2354 // create the 2nd stream.
2355 base::RunLoop().RunUntilIdle();
2357 EXPECT_EQ(0u, session_
->num_active_streams());
2358 EXPECT_EQ(1u, session_
->num_created_streams());
2359 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(LOWEST
));
2361 base::WeakPtr
<SpdyStream
> stream2
= request2
.ReleaseStream();
2362 test::StreamDelegateDoNothing
delegate2(stream2
);
2363 stream2
->SetDelegate(&delegate2
);
2364 scoped_ptr
<SpdyHeaderBlock
> headers2(
2365 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2366 stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2367 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
2369 // Run until 2nd stream is activated and then closed.
2370 EXPECT_EQ(0u, delegate2
.stream_id());
2371 base::RunLoop().RunUntilIdle();
2372 EXPECT_FALSE(stream2
);
2373 EXPECT_EQ(3u, delegate2
.stream_id());
2375 EXPECT_EQ(0u, session_
->num_active_streams());
2376 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2378 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2379 // create the 3rd stream.
2380 base::RunLoop().RunUntilIdle();
2382 EXPECT_EQ(0u, session_
->num_active_streams());
2383 EXPECT_EQ(1u, session_
->num_created_streams());
2384 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2386 base::WeakPtr
<SpdyStream
> stream3
= request3
.ReleaseStream();
2387 test::StreamDelegateDoNothing
delegate3(stream3
);
2388 stream3
->SetDelegate(&delegate3
);
2389 scoped_ptr
<SpdyHeaderBlock
> headers3(
2390 spdy_util_
.ConstructGetHeaderBlock(url3
.spec()));
2391 stream3
->SendRequestHeaders(headers3
.Pass(), NO_MORE_DATA_TO_SEND
);
2392 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
2394 // Run until 2nd stream is activated and then closed.
2395 EXPECT_EQ(0u, delegate3
.stream_id());
2396 base::RunLoop().RunUntilIdle();
2397 EXPECT_FALSE(stream3
);
2398 EXPECT_EQ(5u, delegate3
.stream_id());
2400 EXPECT_EQ(0u, session_
->num_active_streams());
2401 EXPECT_EQ(0u, session_
->num_created_streams());
2402 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2404 data
.CompleteRead();
2405 base::RunLoop().RunUntilIdle();
2408 TEST_P(SpdySessionTest
, CancelTwoStalledCreateStream
) {
2409 session_deps_
.host_resolver
->set_synchronous_mode(true);
2411 MockRead reads
[] = {
2412 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2415 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2416 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2418 CreateNetworkSession();
2419 CreateInsecureSpdySession();
2421 // Leave room for only one more stream to be created.
2422 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
2423 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
2424 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2425 ASSERT_TRUE(spdy_stream
!= nullptr);
2428 GURL
url1(kDefaultURL
);
2429 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2430 SPDY_BIDIRECTIONAL_STREAM
, session_
, url1
, LOWEST
, BoundNetLog());
2431 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2432 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2434 TestCompletionCallback callback2
;
2435 GURL
url2(kDefaultURL
);
2436 SpdyStreamRequest request2
;
2437 ASSERT_EQ(ERR_IO_PENDING
,
2438 request2
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
, session_
, url2
,
2439 LOWEST
, BoundNetLog(), callback2
.callback()));
2441 TestCompletionCallback callback3
;
2442 GURL
url3(kDefaultURL
);
2443 SpdyStreamRequest request3
;
2444 ASSERT_EQ(ERR_IO_PENDING
,
2445 request3
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
, session_
, url3
,
2446 LOWEST
, BoundNetLog(), callback3
.callback()));
2448 EXPECT_EQ(0u, session_
->num_active_streams());
2449 EXPECT_EQ(kInitialMaxConcurrentStreams
, session_
->num_created_streams());
2450 EXPECT_EQ(2u, session_
->pending_create_stream_queue_size(LOWEST
));
2452 // Cancel the first stream; this will allow the second stream to be created.
2453 EXPECT_TRUE(spdy_stream1
);
2454 spdy_stream1
->Cancel();
2455 EXPECT_FALSE(spdy_stream1
);
2457 EXPECT_EQ(OK
, callback2
.WaitForResult());
2458 EXPECT_EQ(0u, session_
->num_active_streams());
2459 EXPECT_EQ(kInitialMaxConcurrentStreams
, session_
->num_created_streams());
2460 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(LOWEST
));
2462 // Cancel the second stream; this will allow the third stream to be created.
2463 base::WeakPtr
<SpdyStream
> spdy_stream2
= request2
.ReleaseStream();
2464 spdy_stream2
->Cancel();
2465 EXPECT_FALSE(spdy_stream2
);
2467 EXPECT_EQ(OK
, callback3
.WaitForResult());
2468 EXPECT_EQ(0u, session_
->num_active_streams());
2469 EXPECT_EQ(kInitialMaxConcurrentStreams
, session_
->num_created_streams());
2470 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2472 // Cancel the third stream.
2473 base::WeakPtr
<SpdyStream
> spdy_stream3
= request3
.ReleaseStream();
2474 spdy_stream3
->Cancel();
2475 EXPECT_FALSE(spdy_stream3
);
2476 EXPECT_EQ(0u, session_
->num_active_streams());
2477 EXPECT_EQ(kInitialMaxConcurrentStreams
- 1, session_
->num_created_streams());
2478 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2481 // Test that SpdySession::DoReadLoop reads data from the socket
2482 // without yielding. This test makes 32k - 1 bytes of data available
2483 // on the socket for reading. It then verifies that it has read all
2484 // the available data without yielding.
2485 TEST_P(SpdySessionTest
, ReadDataWithoutYielding
) {
2486 session_deps_
.host_resolver
->set_synchronous_mode(true);
2488 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2490 scoped_ptr
<SpdyFrame
> req1(
2491 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2492 MockWrite writes
[] = {
2493 CreateMockWrite(*req1
, 0),
2496 // Build buffer of size kYieldAfterBytesRead / 4
2497 // (-spdy_data_frame_size).
2498 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead
);
2499 const int kPayloadSize
=
2500 kYieldAfterBytesRead
/ 4 - framer
.GetControlFrameHeaderSize();
2501 TestDataStream test_stream
;
2502 scoped_refptr
<IOBuffer
> payload(new IOBuffer(kPayloadSize
));
2503 char* payload_data
= payload
->data();
2504 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2506 scoped_ptr
<SpdyFrame
> partial_data_frame(
2507 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2508 scoped_ptr
<SpdyFrame
> finish_data_frame(
2509 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
- 1, DATA_FLAG_FIN
));
2511 scoped_ptr
<SpdyFrame
> resp1(
2512 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2514 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2516 MockRead reads
[] = {
2517 CreateMockRead(*resp1
, 1),
2518 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2519 CreateMockRead(*partial_data_frame
, 3),
2520 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2521 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2522 CreateMockRead(*finish_data_frame
, 6, SYNCHRONOUS
),
2523 MockRead(ASYNC
, 0, 7) // EOF
2526 // Create SpdySession and SpdyStream and send the request.
2527 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2528 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2530 CreateNetworkSession();
2531 CreateInsecureSpdySession();
2533 GURL
url1(kDefaultURL
);
2534 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2535 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url1
, MEDIUM
, BoundNetLog());
2536 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2537 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2538 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2539 spdy_stream1
->SetDelegate(&delegate1
);
2541 scoped_ptr
<SpdyHeaderBlock
> headers1(
2542 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2543 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2544 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2546 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2548 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2550 // Run until 1st read.
2551 EXPECT_EQ(0u, delegate1
.stream_id());
2552 base::RunLoop().RunUntilIdle();
2553 EXPECT_EQ(1u, delegate1
.stream_id());
2554 EXPECT_EQ(0u, observer
.executed_count());
2556 // Read all the data and verify SpdySession::DoReadLoop has not
2558 data
.CompleteRead();
2559 base::RunLoop().RunUntilIdle();
2560 EXPECT_FALSE(spdy_stream1
);
2562 // Verify task observer's executed_count is zero, which indicates DoRead read
2563 // all the available data.
2564 EXPECT_EQ(0u, observer
.executed_count());
2565 EXPECT_TRUE(data
.AllWriteDataConsumed());
2566 EXPECT_TRUE(data
.AllReadDataConsumed());
2569 // Test that SpdySession::DoReadLoop yields if more than
2570 // |kYieldAfterDurationMilliseconds| has passed. This test uses a mock time
2571 // function that makes the response frame look very slow to read.
2572 TEST_P(SpdySessionTest
, TestYieldingSlowReads
) {
2573 session_deps_
.host_resolver
->set_synchronous_mode(true);
2574 session_deps_
.time_func
= SlowReads
;
2576 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2578 scoped_ptr
<SpdyFrame
> req1(
2579 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2580 MockWrite writes
[] = {
2581 CreateMockWrite(*req1
, 0),
2584 scoped_ptr
<SpdyFrame
> resp1(
2585 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2587 MockRead reads
[] = {
2588 CreateMockRead(*resp1
, 1), MockRead(ASYNC
, 0, 2) // EOF
2591 // Create SpdySession and SpdyStream and send the request.
2592 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2593 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2595 CreateNetworkSession();
2596 CreateInsecureSpdySession();
2598 GURL
url1(kDefaultURL
);
2599 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2600 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url1
, MEDIUM
, BoundNetLog());
2601 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2602 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2603 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2604 spdy_stream1
->SetDelegate(&delegate1
);
2606 scoped_ptr
<SpdyHeaderBlock
> headers1(
2607 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2608 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2609 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2611 // Set up the TaskObserver to verify that SpdySession::DoReadLoop posts a
2613 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2615 EXPECT_EQ(0u, delegate1
.stream_id());
2616 EXPECT_EQ(0u, observer
.executed_count());
2618 // Read all the data and verify that SpdySession::DoReadLoop has posted a
2620 base::RunLoop().RunUntilIdle();
2621 EXPECT_EQ(1u, delegate1
.stream_id());
2622 EXPECT_FALSE(spdy_stream1
);
2624 // Verify task that the observer's executed_count is 1, which indicates DoRead
2625 // has posted only one task and thus yielded though there is data available
2627 EXPECT_EQ(1u, observer
.executed_count());
2628 EXPECT_TRUE(data
.AllWriteDataConsumed());
2629 EXPECT_TRUE(data
.AllReadDataConsumed());
2632 // Test that SpdySession::DoReadLoop yields while reading the
2633 // data. This test makes 32k + 1 bytes of data available on the socket
2634 // for reading. It then verifies that DoRead has yielded even though
2635 // there is data available for it to read (i.e, socket()->Read didn't
2636 // return ERR_IO_PENDING during socket reads).
2637 TEST_P(SpdySessionTest
, TestYieldingDuringReadData
) {
2638 session_deps_
.host_resolver
->set_synchronous_mode(true);
2640 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2642 scoped_ptr
<SpdyFrame
> req1(
2643 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2644 MockWrite writes
[] = {
2645 CreateMockWrite(*req1
, 0),
2648 // Build buffer of size kYieldAfterBytesRead / 4
2649 // (-spdy_data_frame_size).
2650 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead
);
2651 const int kPayloadSize
=
2652 kYieldAfterBytesRead
/ 4 - framer
.GetControlFrameHeaderSize();
2653 TestDataStream test_stream
;
2654 scoped_refptr
<IOBuffer
> payload(new IOBuffer(kPayloadSize
));
2655 char* payload_data
= payload
->data();
2656 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2658 scoped_ptr
<SpdyFrame
> partial_data_frame(
2659 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2660 scoped_ptr
<SpdyFrame
> finish_data_frame(
2661 framer
.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN
));
2663 scoped_ptr
<SpdyFrame
> resp1(
2664 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2666 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2667 MockRead reads
[] = {
2668 CreateMockRead(*resp1
, 1),
2669 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2670 CreateMockRead(*partial_data_frame
, 3),
2671 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2672 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2673 CreateMockRead(*partial_data_frame
, 6, SYNCHRONOUS
),
2674 CreateMockRead(*finish_data_frame
, 7, SYNCHRONOUS
),
2675 MockRead(ASYNC
, 0, 8) // EOF
2678 // Create SpdySession and SpdyStream and send the request.
2679 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2680 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2682 CreateNetworkSession();
2683 CreateInsecureSpdySession();
2685 GURL
url1(kDefaultURL
);
2686 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2687 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url1
, MEDIUM
, BoundNetLog());
2688 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2689 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2690 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2691 spdy_stream1
->SetDelegate(&delegate1
);
2693 scoped_ptr
<SpdyHeaderBlock
> headers1(
2694 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2695 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2696 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2698 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a task.
2699 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2701 // Run until 1st read.
2702 EXPECT_EQ(0u, delegate1
.stream_id());
2703 base::RunLoop().RunUntilIdle();
2704 EXPECT_EQ(1u, delegate1
.stream_id());
2705 EXPECT_EQ(0u, observer
.executed_count());
2707 // Read all the data and verify SpdySession::DoReadLoop has posted a task.
2708 data
.CompleteRead();
2709 base::RunLoop().RunUntilIdle();
2710 EXPECT_FALSE(spdy_stream1
);
2712 // Verify task observer's executed_count is 1, which indicates DoRead has
2713 // posted only one task and thus yielded though there is data available for it
2715 EXPECT_EQ(1u, observer
.executed_count());
2716 EXPECT_TRUE(data
.AllWriteDataConsumed());
2717 EXPECT_TRUE(data
.AllReadDataConsumed());
2720 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2721 // + async, by doing the following MockReads.
2723 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2724 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2726 // The above reads 26K synchronously. Since that is less that 32K, we
2727 // will attempt to read again. However, that DoRead() will return
2728 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2729 // yield. When we come back, DoRead() will read the results from the
2730 // async read, and rest of the data synchronously.
2731 TEST_P(SpdySessionTest
, TestYieldingDuringAsyncReadData
) {
2732 session_deps_
.host_resolver
->set_synchronous_mode(true);
2734 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2736 scoped_ptr
<SpdyFrame
> req1(
2737 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2738 MockWrite writes
[] = {
2739 CreateMockWrite(*req1
, 0),
2742 // Build buffer of size kYieldAfterBytesRead / 4
2743 // (-spdy_data_frame_size).
2744 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead
);
2745 TestDataStream test_stream
;
2746 const int kEightKPayloadSize
=
2747 kYieldAfterBytesRead
/ 4 - framer
.GetControlFrameHeaderSize();
2748 scoped_refptr
<IOBuffer
> eightk_payload(new IOBuffer(kEightKPayloadSize
));
2749 char* eightk_payload_data
= eightk_payload
->data();
2750 test_stream
.GetBytes(eightk_payload_data
, kEightKPayloadSize
);
2752 // Build buffer of 2k size.
2753 TestDataStream test_stream2
;
2754 const int kTwoKPayloadSize
= kEightKPayloadSize
- 6 * 1024;
2755 scoped_refptr
<IOBuffer
> twok_payload(new IOBuffer(kTwoKPayloadSize
));
2756 char* twok_payload_data
= twok_payload
->data();
2757 test_stream2
.GetBytes(twok_payload_data
, kTwoKPayloadSize
);
2759 scoped_ptr
<SpdyFrame
> eightk_data_frame(framer
.CreateDataFrame(
2760 1, eightk_payload_data
, kEightKPayloadSize
, DATA_FLAG_NONE
));
2761 scoped_ptr
<SpdyFrame
> twok_data_frame(framer
.CreateDataFrame(
2762 1, twok_payload_data
, kTwoKPayloadSize
, DATA_FLAG_NONE
));
2763 scoped_ptr
<SpdyFrame
> finish_data_frame(framer
.CreateDataFrame(
2764 1, "h", 1, DATA_FLAG_FIN
));
2766 scoped_ptr
<SpdyFrame
> resp1(
2767 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2769 MockRead reads
[] = {
2770 CreateMockRead(*resp1
, 1),
2771 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2772 CreateMockRead(*eightk_data_frame
, 3),
2773 CreateMockRead(*eightk_data_frame
, 4, SYNCHRONOUS
),
2774 CreateMockRead(*eightk_data_frame
, 5, SYNCHRONOUS
),
2775 CreateMockRead(*twok_data_frame
, 6, SYNCHRONOUS
),
2776 CreateMockRead(*eightk_data_frame
, 7, ASYNC
),
2777 CreateMockRead(*eightk_data_frame
, 8, SYNCHRONOUS
),
2778 CreateMockRead(*eightk_data_frame
, 9, SYNCHRONOUS
),
2779 CreateMockRead(*eightk_data_frame
, 10, SYNCHRONOUS
),
2780 CreateMockRead(*twok_data_frame
, 11, SYNCHRONOUS
),
2781 CreateMockRead(*finish_data_frame
, 12, SYNCHRONOUS
),
2782 MockRead(ASYNC
, 0, 13) // EOF
2785 // Create SpdySession and SpdyStream and send the request.
2786 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2787 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2789 CreateNetworkSession();
2790 CreateInsecureSpdySession();
2792 GURL
url1(kDefaultURL
);
2793 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2794 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url1
, MEDIUM
, BoundNetLog());
2795 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2796 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2797 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2798 spdy_stream1
->SetDelegate(&delegate1
);
2800 scoped_ptr
<SpdyHeaderBlock
> headers1(
2801 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2802 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2803 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2805 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2806 // posting of tasks.
2807 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2809 // Run until 1st read.
2810 EXPECT_EQ(0u, delegate1
.stream_id());
2811 base::RunLoop().RunUntilIdle();
2812 EXPECT_EQ(1u, delegate1
.stream_id());
2813 EXPECT_EQ(0u, observer
.executed_count());
2815 // Read all the data and verify SpdySession::DoReadLoop has posted a
2817 data
.CompleteRead();
2818 base::RunLoop().RunUntilIdle();
2819 EXPECT_FALSE(spdy_stream1
);
2821 // Verify task observer's executed_count is 1, which indicates DoRead has
2822 // posted only one task and thus yielded though there is data available for
2824 EXPECT_EQ(1u, observer
.executed_count());
2825 EXPECT_TRUE(data
.AllWriteDataConsumed());
2826 EXPECT_TRUE(data
.AllReadDataConsumed());
2829 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2830 // nothing blows up.
2831 TEST_P(SpdySessionTest
, GoAwayWhileInDoReadLoop
) {
2832 session_deps_
.host_resolver
->set_synchronous_mode(true);
2834 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2836 scoped_ptr
<SpdyFrame
> req1(
2837 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2838 MockWrite writes
[] = {
2839 CreateMockWrite(*req1
, 0),
2842 scoped_ptr
<SpdyFrame
> resp1(
2843 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2844 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2845 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
2847 MockRead reads
[] = {
2848 CreateMockRead(*resp1
, 1),
2849 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2850 CreateMockRead(*body1
, 3),
2851 CreateMockRead(*goaway
, 4),
2854 // Create SpdySession and SpdyStream and send the request.
2855 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2856 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2858 CreateNetworkSession();
2859 CreateInsecureSpdySession();
2861 GURL
url1(kDefaultURL
);
2862 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2863 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url1
, MEDIUM
, BoundNetLog());
2864 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2865 spdy_stream1
->SetDelegate(&delegate1
);
2866 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2867 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2869 scoped_ptr
<SpdyHeaderBlock
> headers1(
2870 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2871 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2872 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2874 // Run until 1st read.
2875 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2876 base::RunLoop().RunUntilIdle();
2877 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2879 // Run until GoAway.
2880 data
.CompleteRead();
2881 base::RunLoop().RunUntilIdle();
2882 EXPECT_FALSE(spdy_stream1
);
2883 EXPECT_TRUE(data
.AllWriteDataConsumed());
2884 EXPECT_TRUE(data
.AllReadDataConsumed());
2885 EXPECT_FALSE(session_
);
2888 // Within this framework, a SpdySession should be initialized with
2889 // flow control disabled for protocol version 2, with flow control
2890 // enabled only for streams for protocol version 3, and with flow
2891 // control enabled for streams and sessions for higher versions.
2892 TEST_P(SpdySessionTest
, ProtocolNegotiation
) {
2893 session_deps_
.host_resolver
->set_synchronous_mode(true);
2895 MockRead reads
[] = {
2896 MockRead(SYNCHRONOUS
, 0, 0) // EOF
2898 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2899 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2901 CreateNetworkSession();
2902 session_
= CreateFakeSpdySession(spdy_session_pool_
, key_
);
2904 EXPECT_EQ(spdy_util_
.spdy_version(),
2905 session_
->buffered_spdy_framer_
->protocol_version());
2906 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
2907 session_
->flow_control_state());
2908 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
2909 session_
->session_send_window_size_
);
2910 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
2911 session_
->session_recv_window_size_
);
2912 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
2915 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2916 // pointers to the idle session are currently held.
2917 TEST_P(SpdySessionTest
, CloseOneIdleConnection
) {
2918 ClientSocketPoolManager::set_max_sockets_per_group(
2919 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2920 ClientSocketPoolManager::set_max_sockets_per_pool(
2921 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2923 MockRead reads
[] = {
2924 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2926 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2927 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2928 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2930 CreateNetworkSession();
2932 TransportClientSocketPool
* pool
=
2933 http_session_
->GetTransportSocketPool(
2934 HttpNetworkSession::NORMAL_SOCKET_POOL
);
2936 // Create an idle SPDY session.
2937 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2938 PRIVACY_MODE_DISABLED
);
2939 base::WeakPtr
<SpdySession
> session1
=
2940 ::net::CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
2941 EXPECT_FALSE(pool
->IsStalled());
2943 // Trying to create a new connection should cause the pool to be stalled, and
2944 // post a task asynchronously to try and close the session.
2945 TestCompletionCallback callback2
;
2946 HostPortPair
host_port2("2.com", 80);
2947 scoped_refptr
<TransportSocketParams
> params2(
2948 new TransportSocketParams(
2949 host_port2
, false, false, OnHostResolutionCallback(),
2950 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
2951 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
2952 EXPECT_EQ(ERR_IO_PENDING
,
2953 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
2954 callback2
.callback(), pool
, BoundNetLog()));
2955 EXPECT_TRUE(pool
->IsStalled());
2957 // The socket pool should close the connection asynchronously and establish a
2959 EXPECT_EQ(OK
, callback2
.WaitForResult());
2960 EXPECT_FALSE(pool
->IsStalled());
2961 EXPECT_FALSE(session1
);
2964 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2965 // pointers to the idle session are currently held, in the case the SPDY session
2967 TEST_P(SpdySessionTest
, CloseOneIdleConnectionWithAlias
) {
2968 ClientSocketPoolManager::set_max_sockets_per_group(
2969 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2970 ClientSocketPoolManager::set_max_sockets_per_pool(
2971 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2973 MockRead reads
[] = {
2974 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2976 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2977 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2978 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2980 session_deps_
.host_resolver
->set_synchronous_mode(true);
2981 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
2982 "1.com", "192.168.0.2", std::string());
2983 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
2984 "2.com", "192.168.0.2", std::string());
2985 // Not strictly needed.
2986 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
2987 "3.com", "192.168.0.3", std::string());
2989 CreateNetworkSession();
2991 TransportClientSocketPool
* pool
=
2992 http_session_
->GetTransportSocketPool(
2993 HttpNetworkSession::NORMAL_SOCKET_POOL
);
2995 // Create an idle SPDY session.
2996 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2997 PRIVACY_MODE_DISABLED
);
2998 base::WeakPtr
<SpdySession
> session1
=
2999 ::net::CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3000 EXPECT_FALSE(pool
->IsStalled());
3002 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3003 SpdySessionKey
key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3004 PRIVACY_MODE_DISABLED
);
3005 HostResolver::RequestInfo
info(key2
.host_port_pair());
3006 AddressList addresses
;
3007 // Pre-populate the DNS cache, since a synchronous resolution is required in
3008 // order to create the alias.
3009 session_deps_
.host_resolver
->Resolve(info
, DEFAULT_PRIORITY
, &addresses
,
3010 CompletionCallback(), nullptr,
3012 // Get a session for |key2|, which should return the session created earlier.
3013 base::WeakPtr
<SpdySession
> session2
=
3014 spdy_session_pool_
->FindAvailableSession(key2
, BoundNetLog());
3015 ASSERT_EQ(session1
.get(), session2
.get());
3016 EXPECT_FALSE(pool
->IsStalled());
3018 // Trying to create a new connection should cause the pool to be stalled, and
3019 // post a task asynchronously to try and close the session.
3020 TestCompletionCallback callback3
;
3021 HostPortPair
host_port3("3.com", 80);
3022 scoped_refptr
<TransportSocketParams
> params3(
3023 new TransportSocketParams(
3024 host_port3
, false, false, OnHostResolutionCallback(),
3025 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3026 scoped_ptr
<ClientSocketHandle
> connection3(new ClientSocketHandle
);
3027 EXPECT_EQ(ERR_IO_PENDING
,
3028 connection3
->Init(host_port3
.ToString(), params3
, DEFAULT_PRIORITY
,
3029 callback3
.callback(), pool
, BoundNetLog()));
3030 EXPECT_TRUE(pool
->IsStalled());
3032 // The socket pool should close the connection asynchronously and establish a
3034 EXPECT_EQ(OK
, callback3
.WaitForResult());
3035 EXPECT_FALSE(pool
->IsStalled());
3036 EXPECT_FALSE(session1
);
3037 EXPECT_FALSE(session2
);
3040 // Tests that when a SPDY session becomes idle, it closes itself if there is
3041 // a lower layer pool stalled on the per-pool socket limit.
3042 TEST_P(SpdySessionTest
, CloseSessionOnIdleWhenPoolStalled
) {
3043 ClientSocketPoolManager::set_max_sockets_per_group(
3044 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3045 ClientSocketPoolManager::set_max_sockets_per_pool(
3046 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3048 MockRead reads
[] = {
3049 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3051 scoped_ptr
<SpdyFrame
> req1(
3052 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3053 scoped_ptr
<SpdyFrame
> cancel1(
3054 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3055 MockWrite writes
[] = {
3056 CreateMockWrite(*req1
, 1),
3057 CreateMockWrite(*cancel1
, 1),
3059 StaticSocketDataProvider
data(reads
, arraysize(reads
),
3060 writes
, arraysize(writes
));
3061 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3063 MockRead http_reads
[] = {
3064 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3066 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
), nullptr,
3068 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
3071 CreateNetworkSession();
3073 TransportClientSocketPool
* pool
=
3074 http_session_
->GetTransportSocketPool(
3075 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3077 // Create a SPDY session.
3078 GURL
url1(kDefaultURL
);
3079 SpdySessionKey
key1(HostPortPair(url1
.host(), 80),
3080 ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3081 base::WeakPtr
<SpdySession
> session1
=
3082 ::net::CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3083 EXPECT_FALSE(pool
->IsStalled());
3085 // Create a stream using the session, and send a request.
3087 TestCompletionCallback callback1
;
3088 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3089 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3090 session1
, url1
, DEFAULT_PRIORITY
,
3092 ASSERT_TRUE(spdy_stream1
.get());
3093 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3094 spdy_stream1
->SetDelegate(&delegate1
);
3096 scoped_ptr
<SpdyHeaderBlock
> headers1(
3097 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
3098 EXPECT_EQ(ERR_IO_PENDING
,
3099 spdy_stream1
->SendRequestHeaders(
3100 headers1
.Pass(), NO_MORE_DATA_TO_SEND
));
3101 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3103 base::RunLoop().RunUntilIdle();
3105 // Trying to create a new connection should cause the pool to be stalled, and
3106 // post a task asynchronously to try and close the session.
3107 TestCompletionCallback callback2
;
3108 HostPortPair
host_port2("2.com", 80);
3109 scoped_refptr
<TransportSocketParams
> params2(
3110 new TransportSocketParams(
3111 host_port2
, false, false, OnHostResolutionCallback(),
3112 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3113 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3114 EXPECT_EQ(ERR_IO_PENDING
,
3115 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3116 callback2
.callback(), pool
, BoundNetLog()));
3117 EXPECT_TRUE(pool
->IsStalled());
3119 // Running the message loop should cause the socket pool to ask the SPDY
3120 // session to close an idle socket, but since the socket is in use, nothing
3122 base::RunLoop().RunUntilIdle();
3123 EXPECT_TRUE(pool
->IsStalled());
3124 EXPECT_FALSE(callback2
.have_result());
3126 // Cancelling the request should result in the session's socket being
3127 // closed, since the pool is stalled.
3128 ASSERT_TRUE(spdy_stream1
.get());
3129 spdy_stream1
->Cancel();
3130 base::RunLoop().RunUntilIdle();
3131 ASSERT_FALSE(pool
->IsStalled());
3132 EXPECT_EQ(OK
, callback2
.WaitForResult());
3135 // Verify that SpdySessionKey and therefore SpdySession is different when
3136 // privacy mode is enabled or disabled.
3137 TEST_P(SpdySessionTest
, SpdySessionKeyPrivacyMode
) {
3138 CreateNetworkSession();
3140 HostPortPair
host_port_pair("www.example.org", 443);
3141 SpdySessionKey
key_privacy_enabled(host_port_pair
, ProxyServer::Direct(),
3142 PRIVACY_MODE_ENABLED
);
3143 SpdySessionKey
key_privacy_disabled(host_port_pair
, ProxyServer::Direct(),
3144 PRIVACY_MODE_DISABLED
);
3146 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3147 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3149 // Add SpdySession with PrivacyMode Enabled to the pool.
3150 base::WeakPtr
<SpdySession
> session_privacy_enabled
=
3151 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_enabled
);
3153 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3154 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3156 // Add SpdySession with PrivacyMode Disabled to the pool.
3157 base::WeakPtr
<SpdySession
> session_privacy_disabled
=
3158 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_disabled
);
3160 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3161 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3163 session_privacy_enabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3164 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3165 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3167 session_privacy_disabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3168 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3169 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3172 // Delegate that creates another stream when its stream is closed.
3173 class StreamCreatingDelegate
: public test::StreamDelegateDoNothing
{
3175 StreamCreatingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3176 const base::WeakPtr
<SpdySession
>& session
)
3177 : StreamDelegateDoNothing(stream
),
3178 session_(session
) {}
3180 ~StreamCreatingDelegate() override
{}
3182 void OnClose(int status
) override
{
3183 GURL
url(kDefaultURL
);
3185 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3186 session_
, url
, MEDIUM
, BoundNetLog()));
3190 const base::WeakPtr
<SpdySession
> session_
;
3193 // Create another stream in response to a stream being reset. Nothing
3194 // should blow up. This is a regression test for
3195 // http://crbug.com/263690 .
3196 TEST_P(SpdySessionTest
, CreateStreamOnStreamReset
) {
3197 session_deps_
.host_resolver
->set_synchronous_mode(true);
3199 scoped_ptr
<SpdyFrame
> req(
3200 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
3201 MockWrite writes
[] = {
3202 CreateMockWrite(*req
, 0),
3205 scoped_ptr
<SpdyFrame
> rst(
3206 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
3207 MockRead reads
[] = {
3208 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3209 CreateMockRead(*rst
, 2),
3210 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3211 MockRead(ASYNC
, 0, 4) // EOF
3213 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3214 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3216 CreateNetworkSession();
3217 CreateInsecureSpdySession();
3219 GURL
url(kDefaultURL
);
3220 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
3221 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
3222 ASSERT_TRUE(spdy_stream
.get() != nullptr);
3223 EXPECT_EQ(0u, spdy_stream
->stream_id());
3225 StreamCreatingDelegate
delegate(spdy_stream
, session_
);
3226 spdy_stream
->SetDelegate(&delegate
);
3228 scoped_ptr
<SpdyHeaderBlock
> headers(
3229 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
3230 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
3231 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
3233 EXPECT_EQ(0u, spdy_stream
->stream_id());
3235 base::RunLoop().RunUntilIdle();
3237 EXPECT_EQ(1u, spdy_stream
->stream_id());
3239 // Cause the stream to be reset, which should cause another stream
3241 data
.CompleteRead();
3242 base::RunLoop().RunUntilIdle();
3244 EXPECT_FALSE(spdy_stream
);
3245 EXPECT_TRUE(delegate
.StreamIsClosed());
3246 EXPECT_EQ(0u, session_
->num_active_streams());
3247 EXPECT_EQ(1u, session_
->num_created_streams());
3249 data
.CompleteRead();
3250 base::RunLoop().RunUntilIdle();
3251 EXPECT_FALSE(session_
);
3254 TEST_P(SpdySessionTest
, UpdateStreamsSendWindowSize
) {
3255 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3257 SettingsMap new_settings
;
3258 int32 window_size
= 1;
3259 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
3260 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, window_size
);
3262 // Set up the socket so we read a SETTINGS frame that sets
3263 // INITIAL_WINDOW_SIZE.
3264 scoped_ptr
<SpdyFrame
> settings_frame(
3265 spdy_util_
.ConstructSpdySettings(new_settings
));
3266 MockRead reads
[] = {
3267 CreateMockRead(*settings_frame
, 0),
3268 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3269 MockRead(ASYNC
, 0, 2) // EOF
3272 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
3273 MockWrite writes
[] = {
3274 CreateMockWrite(*settings_ack
, 3),
3277 session_deps_
.host_resolver
->set_synchronous_mode(true);
3279 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3280 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3282 CreateNetworkSession();
3283 CreateInsecureSpdySession();
3284 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
3285 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
3286 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
3287 TestCompletionCallback callback1
;
3288 EXPECT_NE(spdy_stream1
->send_window_size(), window_size
);
3290 // Process the SETTINGS frame.
3291 base::RunLoop().RunUntilIdle();
3292 EXPECT_EQ(session_
->stream_initial_send_window_size(), window_size
);
3293 EXPECT_EQ(spdy_stream1
->send_window_size(), window_size
);
3295 // Release the first one, this will allow the second to be created.
3296 spdy_stream1
->Cancel();
3297 EXPECT_FALSE(spdy_stream1
);
3299 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
3300 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
3301 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
3302 EXPECT_EQ(spdy_stream2
->send_window_size(), window_size
);
3303 spdy_stream2
->Cancel();
3304 EXPECT_FALSE(spdy_stream2
);
3306 EXPECT_TRUE(session_
);
3307 data
.CompleteRead();
3308 base::RunLoop().RunUntilIdle();
3309 EXPECT_FALSE(session_
);
3312 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3313 // adjust the session receive window size. In addition,
3314 // SpdySession::IncreaseRecvWindowSize should trigger
3315 // sending a WINDOW_UPDATE frame for a large enough delta.
3316 TEST_P(SpdySessionTest
, AdjustRecvWindowSize
) {
3317 session_deps_
.host_resolver
->set_synchronous_mode(true);
3319 const int32 initial_window_size
=
3320 SpdySession::GetDefaultInitialWindowSize(GetParam());
3321 const int32 delta_window_size
= 100;
3323 MockRead reads
[] = {
3324 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
3326 scoped_ptr
<SpdyFrame
> window_update(spdy_util_
.ConstructSpdyWindowUpdate(
3327 kSessionFlowControlStreamId
, initial_window_size
+ delta_window_size
));
3328 MockWrite writes
[] = {
3329 CreateMockWrite(*window_update
, 0),
3331 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3332 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3334 CreateNetworkSession();
3335 CreateInsecureSpdySession();
3336 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3337 session_
->flow_control_state());
3339 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3340 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3342 session_
->IncreaseRecvWindowSize(delta_window_size
);
3343 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3344 session_
->session_recv_window_size_
);
3345 EXPECT_EQ(delta_window_size
, session_
->session_unacked_recv_window_bytes_
);
3347 // Should trigger sending a WINDOW_UPDATE frame.
3348 session_
->IncreaseRecvWindowSize(initial_window_size
);
3349 EXPECT_EQ(initial_window_size
+ delta_window_size
+ initial_window_size
,
3350 session_
->session_recv_window_size_
);
3351 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3353 base::RunLoop().RunUntilIdle();
3355 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3356 session_
->in_io_loop_
= true;
3357 session_
->DecreaseRecvWindowSize(initial_window_size
+ delta_window_size
+
3358 initial_window_size
);
3359 session_
->in_io_loop_
= false;
3360 EXPECT_EQ(0, session_
->session_recv_window_size_
);
3361 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3363 EXPECT_TRUE(session_
);
3364 data
.CompleteRead();
3365 base::RunLoop().RunUntilIdle();
3366 EXPECT_FALSE(session_
);
3369 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3370 // adjust the session send window size when the "enable_spdy_31" flag
3372 TEST_P(SpdySessionTest
, AdjustSendWindowSize
) {
3373 session_deps_
.host_resolver
->set_synchronous_mode(true);
3375 MockRead reads
[] = {
3376 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3378 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
3379 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3381 CreateNetworkSession();
3382 session_
= CreateFakeSpdySession(spdy_session_pool_
, key_
);
3383 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3384 session_
->flow_control_state());
3386 const int32 initial_window_size
=
3387 SpdySession::GetDefaultInitialWindowSize(GetParam());
3388 const int32 delta_window_size
= 100;
3390 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3392 session_
->IncreaseSendWindowSize(delta_window_size
);
3393 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3394 session_
->session_send_window_size_
);
3396 session_
->DecreaseSendWindowSize(delta_window_size
);
3397 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3400 // Incoming data for an inactive stream should not cause the session
3401 // receive window size to decrease, but it should cause the unacked
3402 // bytes to increase.
3403 TEST_P(SpdySessionTest
, SessionFlowControlInactiveStream
) {
3404 session_deps_
.host_resolver
->set_synchronous_mode(true);
3406 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(1, false));
3407 MockRead reads
[] = {
3408 CreateMockRead(*resp
, 0),
3409 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3410 MockRead(ASYNC
, 0, 2) // EOF
3412 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
3413 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3415 CreateNetworkSession();
3416 CreateInsecureSpdySession();
3417 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3418 session_
->flow_control_state());
3420 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3421 session_
->session_recv_window_size_
);
3422 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3424 base::RunLoop().RunUntilIdle();
3426 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3427 session_
->session_recv_window_size_
);
3428 EXPECT_EQ(kUploadDataSize
, session_
->session_unacked_recv_window_bytes_
);
3430 EXPECT_TRUE(session_
);
3431 data
.CompleteRead();
3432 base::RunLoop().RunUntilIdle();
3433 EXPECT_FALSE(session_
);
3436 // The frame header is not included in flow control, but frame payload
3437 // (including optional pad length and padding) is.
3438 TEST_P(SpdySessionTest
, SessionFlowControlPadding
) {
3439 // Padding only exists in HTTP/2.
3440 if (GetParam() < kProtoHTTP2MinimumVersion
)
3443 session_deps_
.host_resolver
->set_synchronous_mode(true);
3445 const int padding_length
= 42;
3446 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(
3447 1, kUploadData
, kUploadDataSize
, false, padding_length
));
3448 MockRead reads
[] = {
3449 CreateMockRead(*resp
, 0),
3450 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3451 MockRead(ASYNC
, 0, 2) // EOF
3453 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
3454 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3456 CreateNetworkSession();
3457 CreateInsecureSpdySession();
3458 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3459 session_
->flow_control_state());
3461 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3462 session_
->session_recv_window_size_
);
3463 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3465 base::RunLoop().RunUntilIdle();
3467 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3468 session_
->session_recv_window_size_
);
3469 EXPECT_EQ(kUploadDataSize
+ padding_length
,
3470 session_
->session_unacked_recv_window_bytes_
);
3472 data
.CompleteRead();
3473 base::RunLoop().RunUntilIdle();
3474 EXPECT_FALSE(session_
);
3477 // Peer sends more data than stream level receiving flow control window.
3478 TEST_P(SpdySessionTest
, StreamFlowControlTooMuchData
) {
3479 const int32 stream_max_recv_window_size
= 1024;
3480 const int32 data_frame_size
= 2 * stream_max_recv_window_size
;
3482 scoped_ptr
<SpdyFrame
> req(
3483 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3484 scoped_ptr
<SpdyFrame
> rst(
3485 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
3486 MockWrite writes
[] = {
3487 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 4),
3490 scoped_ptr
<SpdyFrame
> resp(
3491 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3492 const std::string
payload(data_frame_size
, 'a');
3493 scoped_ptr
<SpdyFrame
> data_frame(spdy_util_
.ConstructSpdyBodyFrame(
3494 1, payload
.data(), data_frame_size
, false));
3495 MockRead reads
[] = {
3496 CreateMockRead(*resp
, 1),
3497 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
3498 CreateMockRead(*data_frame
, 3),
3499 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
3500 MockRead(ASYNC
, 0, 6),
3503 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3504 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3505 CreateNetworkSession();
3507 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
3508 pool_peer
.SetStreamInitialRecvWindowSize(stream_max_recv_window_size
);
3509 CreateInsecureSpdySession();
3510 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM
, session_
->flow_control_state());
3512 GURL
url(kDefaultURL
);
3513 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
3514 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, LOWEST
, BoundNetLog());
3515 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3517 test::StreamDelegateDoNothing
delegate(spdy_stream
);
3518 spdy_stream
->SetDelegate(&delegate
);
3520 scoped_ptr
<SpdyHeaderBlock
> headers(
3521 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
3522 EXPECT_EQ(ERR_IO_PENDING
, spdy_stream
->SendRequestHeaders(
3523 headers
.Pass(), NO_MORE_DATA_TO_SEND
));
3525 // Request and response.
3526 base::RunLoop().RunUntilIdle();
3527 EXPECT_EQ(1u, spdy_stream
->stream_id());
3529 // Too large data frame causes flow control error, should close stream.
3530 data
.CompleteRead();
3531 base::RunLoop().RunUntilIdle();
3532 EXPECT_FALSE(spdy_stream
);
3534 EXPECT_TRUE(session_
);
3535 data
.CompleteRead();
3536 base::RunLoop().RunUntilIdle();
3537 EXPECT_FALSE(session_
);
3540 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3541 // deltas in the receiving window size when checking incoming frames for flow
3542 // control errors at session level.
3543 TEST_P(SpdySessionTest
, SessionFlowControlTooMuchDataTwoDataFrames
) {
3544 const int32 session_max_recv_window_size
= 500;
3545 const int32 first_data_frame_size
= 200;
3546 const int32 second_data_frame_size
= 400;
3548 // First data frame should not trigger a WINDOW_UPDATE.
3549 ASSERT_GT(session_max_recv_window_size
/ 2, first_data_frame_size
);
3550 // Second data frame would be fine had there been a WINDOW_UPDATE.
3551 ASSERT_GT(session_max_recv_window_size
, second_data_frame_size
);
3552 // But in fact, the two data frames together overflow the receiving window at
3554 ASSERT_LT(session_max_recv_window_size
,
3555 first_data_frame_size
+ second_data_frame_size
);
3557 session_deps_
.host_resolver
->set_synchronous_mode(true);
3559 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3560 0, GOAWAY_FLOW_CONTROL_ERROR
,
3561 "delta_window_size is 400 in DecreaseRecvWindowSize, which is larger "
3562 "than the receive window size of 500"));
3563 MockWrite writes
[] = {
3564 CreateMockWrite(*goaway
, 4),
3567 const std::string
first_data_frame(first_data_frame_size
, 'a');
3568 scoped_ptr
<SpdyFrame
> first(spdy_util_
.ConstructSpdyBodyFrame(
3569 1, first_data_frame
.data(), first_data_frame_size
, false));
3570 const std::string
second_data_frame(second_data_frame_size
, 'b');
3571 scoped_ptr
<SpdyFrame
> second(spdy_util_
.ConstructSpdyBodyFrame(
3572 1, second_data_frame
.data(), second_data_frame_size
, false));
3573 MockRead reads
[] = {
3574 CreateMockRead(*first
, 0),
3575 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3576 CreateMockRead(*second
, 2),
3577 MockRead(ASYNC
, 0, 3),
3579 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3580 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3582 CreateNetworkSession();
3583 CreateInsecureSpdySession();
3584 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3585 session_
->flow_control_state());
3586 // Setting session level receiving window size to smaller than initial is not
3587 // possible via SpdySessionPoolPeer.
3588 session_
->session_recv_window_size_
= session_max_recv_window_size
;
3590 // First data frame is immediately consumed and does not trigger
3592 base::RunLoop().RunUntilIdle();
3593 EXPECT_EQ(first_data_frame_size
,
3594 session_
->session_unacked_recv_window_bytes_
);
3595 EXPECT_EQ(session_max_recv_window_size
, session_
->session_recv_window_size_
);
3596 EXPECT_EQ(SpdySession::STATE_AVAILABLE
, session_
->availability_state_
);
3598 // Second data frame overflows receiving window, causes session to close.
3599 data
.CompleteRead();
3600 base::RunLoop().RunUntilIdle();
3601 EXPECT_EQ(SpdySession::STATE_DRAINING
, session_
->availability_state_
);
3604 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3605 // deltas in the receiving window size when checking incoming data frames for
3606 // flow control errors at stream level.
3607 TEST_P(SpdySessionTest
, StreamFlowControlTooMuchDataTwoDataFrames
) {
3608 const int32 stream_max_recv_window_size
= 500;
3609 const int32 first_data_frame_size
= 200;
3610 const int32 second_data_frame_size
= 400;
3612 // First data frame should not trigger a WINDOW_UPDATE.
3613 ASSERT_GT(stream_max_recv_window_size
/ 2, first_data_frame_size
);
3614 // Second data frame would be fine had there been a WINDOW_UPDATE.
3615 ASSERT_GT(stream_max_recv_window_size
, second_data_frame_size
);
3616 // But in fact, they should overflow the receiving window at stream level.
3617 ASSERT_LT(stream_max_recv_window_size
,
3618 first_data_frame_size
+ second_data_frame_size
);
3620 scoped_ptr
<SpdyFrame
> req(
3621 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3622 scoped_ptr
<SpdyFrame
> rst(
3623 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
3624 MockWrite writes
[] = {
3625 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 6),
3628 scoped_ptr
<SpdyFrame
> resp(
3629 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3630 const std::string
first_data_frame(first_data_frame_size
, 'a');
3631 scoped_ptr
<SpdyFrame
> first(spdy_util_
.ConstructSpdyBodyFrame(
3632 1, first_data_frame
.data(), first_data_frame_size
, false));
3633 const std::string
second_data_frame(second_data_frame_size
, 'b');
3634 scoped_ptr
<SpdyFrame
> second(spdy_util_
.ConstructSpdyBodyFrame(
3635 1, second_data_frame
.data(), second_data_frame_size
, false));
3636 MockRead reads
[] = {
3637 CreateMockRead(*resp
, 1),
3638 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
3639 CreateMockRead(*first
, 3),
3640 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
3641 CreateMockRead(*second
, 5),
3642 MockRead(ASYNC
, ERR_IO_PENDING
, 7),
3643 MockRead(ASYNC
, 0, 8),
3646 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3647 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3649 CreateNetworkSession();
3650 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
3651 pool_peer
.SetStreamInitialRecvWindowSize(stream_max_recv_window_size
);
3653 CreateInsecureSpdySession();
3654 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM
, session_
->flow_control_state());
3656 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
3657 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
3658 test::StreamDelegateDoNothing
delegate(spdy_stream
);
3659 spdy_stream
->SetDelegate(&delegate
);
3661 scoped_ptr
<SpdyHeaderBlock
> headers(
3662 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
3663 EXPECT_EQ(ERR_IO_PENDING
, spdy_stream
->SendRequestHeaders(
3664 headers
.Pass(), NO_MORE_DATA_TO_SEND
));
3666 // Request and response.
3667 base::RunLoop().RunUntilIdle();
3668 EXPECT_TRUE(spdy_stream
->IsLocallyClosed());
3669 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3671 // First data frame.
3672 data
.CompleteRead();
3673 base::RunLoop().RunUntilIdle();
3674 EXPECT_TRUE(spdy_stream
->IsLocallyClosed());
3675 EXPECT_EQ(stream_max_recv_window_size
- first_data_frame_size
,
3676 spdy_stream
->recv_window_size());
3678 // Consume first data frame. This does not trigger a WINDOW_UPDATE.
3679 std::string received_data
= delegate
.TakeReceivedData();
3680 EXPECT_EQ(static_cast<size_t>(first_data_frame_size
), received_data
.size());
3681 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3683 // Second data frame overflows receiving window, causes the stream to close.
3684 data
.CompleteRead();
3685 base::RunLoop().RunUntilIdle();
3686 EXPECT_FALSE(spdy_stream
.get());
3689 EXPECT_TRUE(session_
);
3690 data
.CompleteRead();
3691 base::RunLoop().RunUntilIdle();
3692 EXPECT_FALSE(session_
);
3695 // A delegate that drops any received data.
3696 class DropReceivedDataDelegate
: public test::StreamDelegateSendImmediate
{
3698 DropReceivedDataDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3699 base::StringPiece data
)
3700 : StreamDelegateSendImmediate(stream
, data
) {}
3702 ~DropReceivedDataDelegate() override
{}
3704 // Drop any received data.
3705 void OnDataReceived(scoped_ptr
<SpdyBuffer
> buffer
) override
{}
3708 // Send data back and forth but use a delegate that drops its received
3709 // data. The receive window should still increase to its original
3710 // value, i.e. we shouldn't "leak" receive window bytes.
3711 TEST_P(SpdySessionTest
, SessionFlowControlNoReceiveLeaks
) {
3712 const char kStreamUrl
[] = "http://www.example.org/";
3714 const int32 msg_data_size
= 100;
3715 const std::string
msg_data(msg_data_size
, 'a');
3717 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3718 kStreamUrl
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
3719 scoped_ptr
<SpdyFrame
> msg(
3720 spdy_util_
.ConstructSpdyBodyFrame(
3721 1, msg_data
.data(), msg_data_size
, false));
3722 MockWrite writes
[] = {
3723 CreateMockWrite(*req
, 0),
3724 CreateMockWrite(*msg
, 2),
3727 scoped_ptr
<SpdyFrame
> resp(
3728 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3729 scoped_ptr
<SpdyFrame
> echo(
3730 spdy_util_
.ConstructSpdyBodyFrame(
3731 1, msg_data
.data(), msg_data_size
, false));
3732 scoped_ptr
<SpdyFrame
> window_update(
3733 spdy_util_
.ConstructSpdyWindowUpdate(
3734 kSessionFlowControlStreamId
, msg_data_size
));
3735 MockRead reads
[] = {
3736 CreateMockRead(*resp
, 1),
3737 CreateMockRead(*echo
, 3),
3738 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
3739 MockRead(ASYNC
, 0, 5) // EOF
3742 // Create SpdySession and SpdyStream and send the request.
3743 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3744 session_deps_
.host_resolver
->set_synchronous_mode(true);
3745 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3747 CreateNetworkSession();
3748 CreateInsecureSpdySession();
3750 GURL
url(kStreamUrl
);
3751 base::WeakPtr
<SpdyStream
> stream
= CreateStreamSynchronously(
3752 SPDY_BIDIRECTIONAL_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
3753 ASSERT_TRUE(stream
.get() != nullptr);
3754 EXPECT_EQ(0u, stream
->stream_id());
3756 DropReceivedDataDelegate
delegate(stream
, msg_data
);
3757 stream
->SetDelegate(&delegate
);
3759 scoped_ptr
<SpdyHeaderBlock
> headers(
3760 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3761 EXPECT_EQ(ERR_IO_PENDING
,
3762 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3763 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3765 const int32 initial_window_size
=
3766 SpdySession::GetDefaultInitialWindowSize(GetParam());
3767 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3768 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3770 base::RunLoop().RunUntilIdle();
3772 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3773 EXPECT_EQ(msg_data_size
, session_
->session_unacked_recv_window_bytes_
);
3776 EXPECT_FALSE(stream
);
3778 EXPECT_EQ(OK
, delegate
.WaitForClose());
3780 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3781 EXPECT_EQ(msg_data_size
, session_
->session_unacked_recv_window_bytes_
);
3783 data
.CompleteRead();
3784 base::RunLoop().RunUntilIdle();
3785 EXPECT_FALSE(session_
);
3788 // Send data back and forth but close the stream before its data frame
3789 // can be written to the socket. The send window should then increase
3790 // to its original value, i.e. we shouldn't "leak" send window bytes.
3791 TEST_P(SpdySessionTest
, SessionFlowControlNoSendLeaks
) {
3792 const char kStreamUrl
[] = "http://www.example.org/";
3794 const int32 msg_data_size
= 100;
3795 const std::string
msg_data(msg_data_size
, 'a');
3797 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3798 kStreamUrl
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
3799 MockWrite writes
[] = {
3800 CreateMockWrite(*req
, 0),
3803 scoped_ptr
<SpdyFrame
> resp(
3804 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3805 MockRead reads
[] = {
3806 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3807 CreateMockRead(*resp
, 2),
3808 MockRead(ASYNC
, 0, 3) // EOF
3811 // Create SpdySession and SpdyStream and send the request.
3812 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3813 session_deps_
.host_resolver
->set_synchronous_mode(true);
3814 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3816 CreateNetworkSession();
3817 CreateInsecureSpdySession();
3819 GURL
url(kStreamUrl
);
3820 base::WeakPtr
<SpdyStream
> stream
= CreateStreamSynchronously(
3821 SPDY_BIDIRECTIONAL_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
3822 ASSERT_TRUE(stream
.get() != nullptr);
3823 EXPECT_EQ(0u, stream
->stream_id());
3825 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3826 stream
->SetDelegate(&delegate
);
3828 scoped_ptr
<SpdyHeaderBlock
> headers(
3829 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3830 EXPECT_EQ(ERR_IO_PENDING
,
3831 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3832 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3834 const int32 initial_window_size
=
3835 SpdySession::GetDefaultInitialWindowSize(GetParam());
3836 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3839 base::RunLoop().RunUntilIdle();
3841 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3843 // Read response, but do not run the message loop, so that the body is not
3844 // written to the socket.
3845 data
.CompleteRead();
3847 EXPECT_EQ(initial_window_size
- msg_data_size
,
3848 session_
->session_send_window_size_
);
3850 // Closing the stream should increase the session's send window.
3852 EXPECT_FALSE(stream
);
3854 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3856 EXPECT_EQ(OK
, delegate
.WaitForClose());
3858 base::RunLoop().RunUntilIdle();
3859 EXPECT_FALSE(session_
);
3861 EXPECT_TRUE(data
.AllWriteDataConsumed());
3862 EXPECT_TRUE(data
.AllReadDataConsumed());
3865 // Send data back and forth; the send and receive windows should
3866 // change appropriately.
3867 TEST_P(SpdySessionTest
, SessionFlowControlEndToEnd
) {
3868 const char kStreamUrl
[] = "http://www.example.org/";
3870 const int32 msg_data_size
= 100;
3871 const std::string
msg_data(msg_data_size
, 'a');
3873 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3874 kStreamUrl
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
3875 scoped_ptr
<SpdyFrame
> msg(
3876 spdy_util_
.ConstructSpdyBodyFrame(
3877 1, msg_data
.data(), msg_data_size
, false));
3878 MockWrite writes
[] = {
3879 CreateMockWrite(*req
, 0),
3880 CreateMockWrite(*msg
, 2),
3883 scoped_ptr
<SpdyFrame
> resp(
3884 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3885 scoped_ptr
<SpdyFrame
> echo(
3886 spdy_util_
.ConstructSpdyBodyFrame(
3887 1, msg_data
.data(), msg_data_size
, false));
3888 scoped_ptr
<SpdyFrame
> window_update(
3889 spdy_util_
.ConstructSpdyWindowUpdate(
3890 kSessionFlowControlStreamId
, msg_data_size
));
3891 MockRead reads
[] = {
3892 CreateMockRead(*resp
, 1),
3893 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3894 CreateMockRead(*echo
, 4),
3895 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
3896 CreateMockRead(*window_update
, 6),
3897 MockRead(ASYNC
, ERR_IO_PENDING
, 7),
3898 MockRead(ASYNC
, 0, 8) // EOF
3901 // Create SpdySession and SpdyStream and send the request.
3902 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3903 session_deps_
.host_resolver
->set_synchronous_mode(true);
3904 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3906 CreateNetworkSession();
3907 CreateInsecureSpdySession();
3909 GURL
url(kStreamUrl
);
3910 base::WeakPtr
<SpdyStream
> stream
= CreateStreamSynchronously(
3911 SPDY_BIDIRECTIONAL_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
3912 ASSERT_TRUE(stream
.get() != nullptr);
3913 EXPECT_EQ(0u, stream
->stream_id());
3915 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3916 stream
->SetDelegate(&delegate
);
3918 scoped_ptr
<SpdyHeaderBlock
> headers(
3919 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3920 EXPECT_EQ(ERR_IO_PENDING
,
3921 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3922 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3924 const int32 initial_window_size
=
3925 SpdySession::GetDefaultInitialWindowSize(GetParam());
3926 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3927 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3928 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3930 // Send request and message.
3931 base::RunLoop().RunUntilIdle();
3933 EXPECT_EQ(initial_window_size
- msg_data_size
,
3934 session_
->session_send_window_size_
);
3935 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3936 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3939 data
.CompleteRead();
3940 base::RunLoop().RunUntilIdle();
3942 EXPECT_EQ(initial_window_size
- msg_data_size
,
3943 session_
->session_send_window_size_
);
3944 EXPECT_EQ(initial_window_size
- msg_data_size
,
3945 session_
->session_recv_window_size_
);
3946 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3948 // Read window update.
3949 data
.CompleteRead();
3950 base::RunLoop().RunUntilIdle();
3952 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3953 EXPECT_EQ(initial_window_size
- msg_data_size
,
3954 session_
->session_recv_window_size_
);
3955 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3957 EXPECT_EQ(msg_data
, delegate
.TakeReceivedData());
3959 // Draining the delegate's read queue should increase the session's
3961 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3962 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3963 EXPECT_EQ(msg_data_size
, session_
->session_unacked_recv_window_bytes_
);
3966 EXPECT_FALSE(stream
);
3968 EXPECT_EQ(OK
, delegate
.WaitForClose());
3970 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3971 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3972 EXPECT_EQ(msg_data_size
, session_
->session_unacked_recv_window_bytes_
);
3974 data
.CompleteRead();
3975 base::RunLoop().RunUntilIdle();
3976 EXPECT_FALSE(session_
);
3979 // Given a stall function and an unstall function, runs a test to make
3980 // sure that a stream resumes after unstall.
3981 void SpdySessionTest::RunResumeAfterUnstallTest(
3982 const base::Callback
<void(SpdyStream
*)>& stall_function
,
3983 const base::Callback
<void(SpdyStream
*, int32
)>& unstall_function
) {
3984 const char kStreamUrl
[] = "http://www.example.org/";
3985 GURL
url(kStreamUrl
);
3987 session_deps_
.host_resolver
->set_synchronous_mode(true);
3989 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3990 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
3991 scoped_ptr
<SpdyFrame
> body(
3992 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
3993 MockWrite writes
[] = {
3994 CreateMockWrite(*req
, 0),
3995 CreateMockWrite(*body
, 1),
3998 scoped_ptr
<SpdyFrame
> resp(
3999 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4000 scoped_ptr
<SpdyFrame
> echo(
4001 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4002 MockRead reads
[] = {
4003 CreateMockRead(*resp
, 2), MockRead(ASYNC
, 0, 3) // EOF
4006 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4007 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4009 CreateNetworkSession();
4010 CreateInsecureSpdySession();
4011 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4012 session_
->flow_control_state());
4014 base::WeakPtr
<SpdyStream
> stream
= CreateStreamSynchronously(
4015 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, LOWEST
, BoundNetLog());
4016 ASSERT_TRUE(stream
.get() != nullptr);
4018 test::StreamDelegateWithBody
delegate(stream
, kBodyDataStringPiece
);
4019 stream
->SetDelegate(&delegate
);
4021 EXPECT_FALSE(stream
->HasUrlFromHeaders());
4022 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4024 scoped_ptr
<SpdyHeaderBlock
> headers(
4025 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4026 EXPECT_EQ(ERR_IO_PENDING
,
4027 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
4028 EXPECT_TRUE(stream
->HasUrlFromHeaders());
4029 EXPECT_EQ(kStreamUrl
, stream
->GetUrlFromHeaders().spec());
4031 stall_function
.Run(stream
.get());
4033 base::RunLoop().RunUntilIdle();
4035 EXPECT_TRUE(stream
->send_stalled_by_flow_control());
4037 unstall_function
.Run(stream
.get(), kBodyDataSize
);
4039 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4041 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
4043 EXPECT_TRUE(delegate
.send_headers_completed());
4044 EXPECT_EQ("200", delegate
.GetResponseHeaderValue(":status"));
4045 EXPECT_EQ(std::string(), delegate
.TakeReceivedData());
4046 EXPECT_FALSE(session_
);
4047 EXPECT_TRUE(data
.AllWriteDataConsumed());
4050 // Run the resume-after-unstall test with all possible stall and
4051 // unstall sequences.
4053 TEST_P(SpdySessionTest
, ResumeAfterUnstallSession
) {
4054 RunResumeAfterUnstallTest(
4055 base::Bind(&SpdySessionTest::StallSessionOnly
,
4056 base::Unretained(this)),
4057 base::Bind(&SpdySessionTest::UnstallSessionOnly
,
4058 base::Unretained(this)));
4062 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4063 TEST_P(SpdySessionTest
, ResumeAfterUnstallStream
) {
4064 RunResumeAfterUnstallTest(
4065 base::Bind(&SpdySessionTest::StallStreamOnly
,
4066 base::Unretained(this)),
4067 base::Bind(&SpdySessionTest::UnstallStreamOnly
,
4068 base::Unretained(this)));
4071 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallSessionStream
) {
4072 RunResumeAfterUnstallTest(
4073 base::Bind(&SpdySessionTest::StallSessionStream
,
4074 base::Unretained(this)),
4075 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4076 base::Unretained(this)));
4079 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallSessionStream
) {
4080 RunResumeAfterUnstallTest(
4081 base::Bind(&SpdySessionTest::StallStreamSession
,
4082 base::Unretained(this)),
4083 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4084 base::Unretained(this)));
4087 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallStreamSession
) {
4088 RunResumeAfterUnstallTest(
4089 base::Bind(&SpdySessionTest::StallStreamSession
,
4090 base::Unretained(this)),
4091 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4092 base::Unretained(this)));
4095 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallStreamSession
) {
4096 RunResumeAfterUnstallTest(
4097 base::Bind(&SpdySessionTest::StallSessionStream
,
4098 base::Unretained(this)),
4099 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4100 base::Unretained(this)));
4103 // Cause a stall by reducing the flow control send window to 0. The
4104 // streams should resume in priority order when that window is then
4106 TEST_P(SpdySessionTest
, ResumeByPriorityAfterSendWindowSizeIncrease
) {
4107 const char kStreamUrl
[] = "http://www.example.org/";
4108 GURL
url(kStreamUrl
);
4110 session_deps_
.host_resolver
->set_synchronous_mode(true);
4112 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4113 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4114 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4115 kStreamUrl
, 3, kBodyDataSize
, MEDIUM
, nullptr, 0));
4116 scoped_ptr
<SpdyFrame
> body1(
4117 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
4118 scoped_ptr
<SpdyFrame
> body2(
4119 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4120 MockWrite writes
[] = {
4121 CreateMockWrite(*req1
, 0),
4122 CreateMockWrite(*req2
, 1),
4123 CreateMockWrite(*body2
, 2),
4124 CreateMockWrite(*body1
, 3),
4127 scoped_ptr
<SpdyFrame
> resp1(
4128 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4129 scoped_ptr
<SpdyFrame
> resp2(
4130 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
4131 MockRead reads
[] = {
4132 CreateMockRead(*resp1
, 4),
4133 CreateMockRead(*resp2
, 5),
4134 MockRead(ASYNC
, 0, 6) // EOF
4137 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4138 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4140 CreateNetworkSession();
4141 CreateInsecureSpdySession();
4142 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4143 session_
->flow_control_state());
4145 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
4146 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, LOWEST
, BoundNetLog());
4147 ASSERT_TRUE(stream1
.get() != nullptr);
4149 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4150 stream1
->SetDelegate(&delegate1
);
4152 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4154 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
4155 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, MEDIUM
, BoundNetLog());
4156 ASSERT_TRUE(stream2
.get() != nullptr);
4158 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4159 stream2
->SetDelegate(&delegate2
);
4161 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4163 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4164 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4168 scoped_ptr
<SpdyHeaderBlock
> headers1(
4169 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4170 EXPECT_EQ(ERR_IO_PENDING
,
4171 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4172 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4173 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4175 base::RunLoop().RunUntilIdle();
4176 EXPECT_EQ(1u, stream1
->stream_id());
4177 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4179 scoped_ptr
<SpdyHeaderBlock
> headers2(
4180 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4181 EXPECT_EQ(ERR_IO_PENDING
,
4182 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4183 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4184 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4186 base::RunLoop().RunUntilIdle();
4187 EXPECT_EQ(3u, stream2
->stream_id());
4188 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4190 // This should unstall only stream2.
4191 UnstallSessionSend(kBodyDataSize
);
4193 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4194 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4196 base::RunLoop().RunUntilIdle();
4198 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4199 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4201 // This should then unstall stream1.
4202 UnstallSessionSend(kBodyDataSize
);
4204 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4205 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4207 base::RunLoop().RunUntilIdle();
4209 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4210 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4212 EXPECT_TRUE(delegate1
.send_headers_completed());
4213 EXPECT_EQ("200", delegate1
.GetResponseHeaderValue(":status"));
4214 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4216 EXPECT_TRUE(delegate2
.send_headers_completed());
4217 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4218 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4220 EXPECT_FALSE(session_
);
4221 EXPECT_TRUE(data
.AllWriteDataConsumed());
4222 EXPECT_TRUE(data
.AllReadDataConsumed());
4225 // Delegate that closes a given stream after sending its body.
4226 class StreamClosingDelegate
: public test::StreamDelegateWithBody
{
4228 StreamClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
4229 base::StringPiece data
)
4230 : StreamDelegateWithBody(stream
, data
) {}
4232 ~StreamClosingDelegate() override
{}
4234 void set_stream_to_close(const base::WeakPtr
<SpdyStream
>& stream_to_close
) {
4235 stream_to_close_
= stream_to_close
;
4238 void OnDataSent() override
{
4239 test::StreamDelegateWithBody::OnDataSent();
4240 if (stream_to_close_
.get()) {
4241 stream_to_close_
->Close();
4242 EXPECT_FALSE(stream_to_close_
);
4247 base::WeakPtr
<SpdyStream
> stream_to_close_
;
4250 // Cause a stall by reducing the flow control send window to
4251 // 0. Unstalling the session should properly handle deleted streams.
4252 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedStreams
) {
4253 const char kStreamUrl
[] = "http://www.example.org/";
4254 GURL
url(kStreamUrl
);
4256 session_deps_
.host_resolver
->set_synchronous_mode(true);
4258 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4259 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4260 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4261 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, nullptr, 0));
4262 scoped_ptr
<SpdyFrame
> req3(spdy_util_
.ConstructSpdyPost(
4263 kStreamUrl
, 5, kBodyDataSize
, LOWEST
, nullptr, 0));
4264 scoped_ptr
<SpdyFrame
> body2(
4265 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4266 MockWrite writes
[] = {
4267 CreateMockWrite(*req1
, 0),
4268 CreateMockWrite(*req2
, 1),
4269 CreateMockWrite(*req3
, 2),
4270 CreateMockWrite(*body2
, 3),
4273 scoped_ptr
<SpdyFrame
> resp2(
4274 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
4275 MockRead reads
[] = {
4276 CreateMockRead(*resp2
, 4),
4277 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4278 MockRead(ASYNC
, 0, 6) // EOF
4281 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4282 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4284 CreateNetworkSession();
4285 CreateInsecureSpdySession();
4286 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4287 session_
->flow_control_state());
4289 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
4290 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, LOWEST
, BoundNetLog());
4291 ASSERT_TRUE(stream1
.get() != nullptr);
4293 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4294 stream1
->SetDelegate(&delegate1
);
4296 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4298 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
4299 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, LOWEST
, BoundNetLog());
4300 ASSERT_TRUE(stream2
.get() != nullptr);
4302 StreamClosingDelegate
delegate2(stream2
, kBodyDataStringPiece
);
4303 stream2
->SetDelegate(&delegate2
);
4305 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4307 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
4308 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, LOWEST
, BoundNetLog());
4309 ASSERT_TRUE(stream3
.get() != nullptr);
4311 test::StreamDelegateWithBody
delegate3(stream3
, kBodyDataStringPiece
);
4312 stream3
->SetDelegate(&delegate3
);
4314 EXPECT_FALSE(stream3
->HasUrlFromHeaders());
4316 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4317 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4318 EXPECT_FALSE(stream3
->send_stalled_by_flow_control());
4322 scoped_ptr
<SpdyHeaderBlock
> headers1(
4323 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4324 EXPECT_EQ(ERR_IO_PENDING
,
4325 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4326 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4327 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4329 base::RunLoop().RunUntilIdle();
4330 EXPECT_EQ(1u, stream1
->stream_id());
4331 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4333 scoped_ptr
<SpdyHeaderBlock
> headers2(
4334 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4335 EXPECT_EQ(ERR_IO_PENDING
,
4336 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4337 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4338 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4340 base::RunLoop().RunUntilIdle();
4341 EXPECT_EQ(3u, stream2
->stream_id());
4342 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4344 scoped_ptr
<SpdyHeaderBlock
> headers3(
4345 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4346 EXPECT_EQ(ERR_IO_PENDING
,
4347 stream3
->SendRequestHeaders(headers3
.Pass(), MORE_DATA_TO_SEND
));
4348 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
4349 EXPECT_EQ(kStreamUrl
, stream3
->GetUrlFromHeaders().spec());
4351 base::RunLoop().RunUntilIdle();
4352 EXPECT_EQ(5u, stream3
->stream_id());
4353 EXPECT_TRUE(stream3
->send_stalled_by_flow_control());
4355 SpdyStreamId stream_id1
= stream1
->stream_id();
4356 SpdyStreamId stream_id2
= stream2
->stream_id();
4357 SpdyStreamId stream_id3
= stream3
->stream_id();
4359 // Close stream1 preemptively.
4360 session_
->CloseActiveStream(stream_id1
, ERR_CONNECTION_CLOSED
);
4361 EXPECT_FALSE(stream1
);
4363 EXPECT_FALSE(session_
->IsStreamActive(stream_id1
));
4364 EXPECT_TRUE(session_
->IsStreamActive(stream_id2
));
4365 EXPECT_TRUE(session_
->IsStreamActive(stream_id3
));
4367 // Unstall stream2, which should then close stream3.
4368 delegate2
.set_stream_to_close(stream3
);
4369 UnstallSessionSend(kBodyDataSize
);
4371 base::RunLoop().RunUntilIdle();
4372 EXPECT_FALSE(stream3
);
4374 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4375 EXPECT_FALSE(session_
->IsStreamActive(stream_id1
));
4376 EXPECT_TRUE(session_
->IsStreamActive(stream_id2
));
4377 EXPECT_FALSE(session_
->IsStreamActive(stream_id3
));
4379 data
.CompleteRead();
4380 base::RunLoop().RunUntilIdle();
4381 EXPECT_FALSE(stream2
);
4382 EXPECT_FALSE(session_
);
4384 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4385 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4386 EXPECT_EQ(OK
, delegate3
.WaitForClose());
4388 EXPECT_TRUE(delegate1
.send_headers_completed());
4389 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4391 EXPECT_TRUE(delegate2
.send_headers_completed());
4392 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4393 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4395 EXPECT_TRUE(delegate3
.send_headers_completed());
4396 EXPECT_EQ(std::string(), delegate3
.TakeReceivedData());
4398 EXPECT_TRUE(data
.AllWriteDataConsumed());
4401 // Cause a stall by reducing the flow control send window to
4402 // 0. Unstalling the session should properly handle the session itself
4404 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedSession
) {
4405 const char kStreamUrl
[] = "http://www.example.org/";
4406 GURL
url(kStreamUrl
);
4408 session_deps_
.host_resolver
->set_synchronous_mode(true);
4410 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4411 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4412 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4413 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, nullptr, 0));
4414 scoped_ptr
<SpdyFrame
> body1(
4415 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4416 MockWrite writes
[] = {
4417 CreateMockWrite(*req1
, 0),
4418 CreateMockWrite(*req2
, 1),
4421 MockRead reads
[] = {
4422 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
4425 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4426 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4428 CreateNetworkSession();
4429 CreateInsecureSpdySession();
4430 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4431 session_
->flow_control_state());
4433 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
4434 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, LOWEST
, BoundNetLog());
4435 ASSERT_TRUE(stream1
.get() != nullptr);
4437 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4438 stream1
->SetDelegate(&delegate1
);
4440 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4442 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
4443 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, LOWEST
, BoundNetLog());
4444 ASSERT_TRUE(stream2
.get() != nullptr);
4446 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4447 stream2
->SetDelegate(&delegate2
);
4449 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4451 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4452 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4456 scoped_ptr
<SpdyHeaderBlock
> headers1(
4457 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4458 EXPECT_EQ(ERR_IO_PENDING
,
4459 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4460 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4461 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4463 base::RunLoop().RunUntilIdle();
4464 EXPECT_EQ(1u, stream1
->stream_id());
4465 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4467 scoped_ptr
<SpdyHeaderBlock
> headers2(
4468 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4469 EXPECT_EQ(ERR_IO_PENDING
,
4470 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4471 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4472 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4474 base::RunLoop().RunUntilIdle();
4475 EXPECT_EQ(3u, stream2
->stream_id());
4476 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4478 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
4481 UnstallSessionSend(kBodyDataSize
);
4483 // Close the session (since we can't do it from within the delegate
4484 // method, since it's in the stream's loop).
4485 session_
->CloseSessionOnError(ERR_CONNECTION_CLOSED
, "Closing session");
4486 data
.CompleteRead();
4487 base::RunLoop().RunUntilIdle();
4488 EXPECT_FALSE(session_
);
4490 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
4492 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4493 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4495 EXPECT_TRUE(delegate1
.send_headers_completed());
4496 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4498 EXPECT_TRUE(delegate2
.send_headers_completed());
4499 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4501 EXPECT_TRUE(data
.AllWriteDataConsumed());
4504 TEST_P(SpdySessionTest
, GoAwayOnSessionFlowControlError
) {
4505 scoped_ptr
<SpdyFrame
> req(
4506 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4507 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
4508 0, GOAWAY_FLOW_CONTROL_ERROR
,
4509 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4510 "the receive window size of 1"));
4511 MockWrite writes
[] = {
4512 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 4),
4515 scoped_ptr
<SpdyFrame
> resp(
4516 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4517 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4518 MockRead reads
[] = {
4519 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4520 CreateMockRead(*resp
, 2),
4521 CreateMockRead(*body
, 3),
4524 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4525 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4527 CreateNetworkSession();
4528 CreateInsecureSpdySession();
4530 GURL
url(kDefaultURL
);
4531 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
4532 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url
, LOWEST
, BoundNetLog());
4533 ASSERT_TRUE(spdy_stream
.get() != nullptr);
4534 test::StreamDelegateDoNothing
delegate(spdy_stream
);
4535 spdy_stream
->SetDelegate(&delegate
);
4537 scoped_ptr
<SpdyHeaderBlock
> headers(
4538 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
4539 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4542 base::RunLoop().RunUntilIdle();
4544 // Put session on the edge of overflowing it's recv window.
4545 session_
->session_recv_window_size_
= 1;
4547 // Read response headers & body. Body overflows the session window, and a
4548 // goaway is written.
4549 data
.CompleteRead();
4550 base::RunLoop().RunUntilIdle();
4552 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR
, delegate
.WaitForClose());
4553 EXPECT_FALSE(session_
);
4556 TEST_P(SpdySessionTest
, SplitHeaders
) {
4557 GURL
kStreamUrl("http://www.example.org/foo.dat");
4558 SpdyHeaderBlock headers
;
4559 spdy_util_
.AddUrlToHeaderBlock(kStreamUrl
.spec(), &headers
);
4560 headers
["alpha"] = "beta";
4562 SpdyHeaderBlock request_headers
;
4563 SpdyHeaderBlock response_headers
;
4565 SplitPushedHeadersToRequestAndResponse(
4566 headers
, spdy_util_
.spdy_version(), &request_headers
, &response_headers
);
4568 SpdyHeaderBlock::const_iterator it
= response_headers
.find("alpha");
4569 std::string alpha_val
=
4570 (it
== response_headers
.end()) ? std::string() : it
->second
;
4571 EXPECT_EQ("beta", alpha_val
);
4574 GetUrlFromHeaderBlock(request_headers
, spdy_util_
.spdy_version(), true);
4575 EXPECT_EQ(kStreamUrl
, request_url
);
4578 // Regression. Sorta. Push streams and client streams were sharing a single
4579 // limit for a long time.
4580 TEST_P(SpdySessionTest
, PushedStreamShouldNotCountToClientConcurrencyLimit
) {
4581 SettingsMap new_settings
;
4582 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4583 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, 2);
4584 scoped_ptr
<SpdyFrame
> settings_frame(
4585 spdy_util_
.ConstructSpdySettings(new_settings
));
4586 scoped_ptr
<SpdyFrame
> pushed(spdy_util_
.ConstructSpdyPush(
4587 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4588 MockRead reads
[] = {
4589 CreateMockRead(*settings_frame
, 0),
4590 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4591 CreateMockRead(*pushed
, 4),
4592 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4593 MockRead(ASYNC
, 0, 6),
4596 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
4597 scoped_ptr
<SpdyFrame
> req(
4598 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4599 MockWrite writes
[] = {
4600 CreateMockWrite(*settings_ack
, 1), CreateMockWrite(*req
, 2),
4603 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4604 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4606 CreateNetworkSession();
4607 CreateInsecureSpdySession();
4609 // Read the settings frame.
4610 base::RunLoop().RunUntilIdle();
4612 GURL
url1(kDefaultURL
);
4613 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4614 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url1
, LOWEST
, BoundNetLog());
4615 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4616 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4617 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4618 spdy_stream1
->SetDelegate(&delegate1
);
4620 EXPECT_EQ(0u, session_
->num_active_streams());
4621 EXPECT_EQ(1u, session_
->num_created_streams());
4622 EXPECT_EQ(0u, session_
->num_pushed_streams());
4623 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4625 scoped_ptr
<SpdyHeaderBlock
> headers(
4626 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4627 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4628 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4630 // Run until 1st stream is activated.
4631 EXPECT_EQ(0u, delegate1
.stream_id());
4632 base::RunLoop().RunUntilIdle();
4633 EXPECT_EQ(1u, delegate1
.stream_id());
4634 EXPECT_EQ(1u, session_
->num_active_streams());
4635 EXPECT_EQ(0u, session_
->num_created_streams());
4636 EXPECT_EQ(0u, session_
->num_pushed_streams());
4637 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4639 // Run until pushed stream is created.
4640 data
.CompleteRead();
4641 base::RunLoop().RunUntilIdle();
4642 EXPECT_EQ(2u, session_
->num_active_streams());
4643 EXPECT_EQ(0u, session_
->num_created_streams());
4644 EXPECT_EQ(1u, session_
->num_pushed_streams());
4645 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4647 // Second stream should not be stalled, although we have 2 active streams, but
4648 // one of them is push stream and should not be taken into account when we
4649 // create streams on the client.
4650 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
4651 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url1
, LOWEST
, BoundNetLog());
4652 EXPECT_TRUE(spdy_stream2
);
4653 EXPECT_EQ(2u, session_
->num_active_streams());
4654 EXPECT_EQ(1u, session_
->num_created_streams());
4655 EXPECT_EQ(1u, session_
->num_pushed_streams());
4656 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4659 data
.CompleteRead();
4660 base::RunLoop().RunUntilIdle();
4661 EXPECT_FALSE(session_
);
4664 TEST_P(SpdySessionTest
, RejectPushedStreamExceedingConcurrencyLimit
) {
4665 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4666 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4667 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
4668 nullptr, 0, 4, 1, "http://www.example.org/b.dat"));
4669 MockRead reads
[] = {
4670 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4671 CreateMockRead(*push_a
, 2),
4672 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4673 CreateMockRead(*push_b
, 4),
4674 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
4675 MockRead(ASYNC
, 0, 7),
4678 scoped_ptr
<SpdyFrame
> req(
4679 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4680 scoped_ptr
<SpdyFrame
> rst(
4681 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4682 MockWrite writes
[] = {
4683 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5),
4686 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4687 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4689 CreateNetworkSession();
4690 CreateInsecureSpdySession();
4691 session_
->set_max_concurrent_pushed_streams(1);
4693 GURL
url1(kDefaultURL
);
4694 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4695 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url1
, LOWEST
, BoundNetLog());
4696 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4697 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4698 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4699 spdy_stream1
->SetDelegate(&delegate1
);
4701 EXPECT_EQ(0u, session_
->num_active_streams());
4702 EXPECT_EQ(1u, session_
->num_created_streams());
4703 EXPECT_EQ(0u, session_
->num_pushed_streams());
4704 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4706 scoped_ptr
<SpdyHeaderBlock
> headers(
4707 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4708 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4709 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4711 // Run until 1st stream is activated.
4712 EXPECT_EQ(0u, delegate1
.stream_id());
4713 base::RunLoop().RunUntilIdle();
4714 EXPECT_EQ(1u, delegate1
.stream_id());
4715 EXPECT_EQ(1u, session_
->num_active_streams());
4716 EXPECT_EQ(0u, session_
->num_created_streams());
4717 EXPECT_EQ(0u, session_
->num_pushed_streams());
4718 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4720 // Run until pushed stream is created.
4721 data
.CompleteRead();
4722 base::RunLoop().RunUntilIdle();
4723 EXPECT_EQ(2u, session_
->num_active_streams());
4724 EXPECT_EQ(0u, session_
->num_created_streams());
4725 EXPECT_EQ(1u, session_
->num_pushed_streams());
4726 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4728 // Reset incoming pushed stream.
4729 data
.CompleteRead();
4730 base::RunLoop().RunUntilIdle();
4731 EXPECT_EQ(2u, session_
->num_active_streams());
4732 EXPECT_EQ(0u, session_
->num_created_streams());
4733 EXPECT_EQ(1u, session_
->num_pushed_streams());
4734 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4737 data
.CompleteRead();
4738 base::RunLoop().RunUntilIdle();
4739 EXPECT_FALSE(session_
);
4742 TEST_P(SpdySessionTest
, IgnoreReservedRemoteStreamsCount
) {
4743 // Streams in reserved remote state exist only in HTTP/2.
4744 if (spdy_util_
.spdy_version() < HTTP2
)
4747 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4748 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4749 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4750 spdy_util_
.AddUrlToHeaderBlock("http://www.example.org/b.dat",
4751 push_headers
.get());
4752 scoped_ptr
<SpdyFrame
> push_b(
4753 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 4, 1));
4754 scoped_ptr
<SpdyFrame
> headers_b(
4755 spdy_util_
.ConstructSpdyPushHeaders(4, nullptr, 0));
4756 MockRead reads
[] = {
4757 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4758 CreateMockRead(*push_a
, 2),
4759 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4760 CreateMockRead(*push_b
, 4),
4761 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4762 CreateMockRead(*headers_b
, 6),
4763 MockRead(ASYNC
, ERR_IO_PENDING
, 8),
4764 MockRead(ASYNC
, 0, 9),
4767 scoped_ptr
<SpdyFrame
> req(
4768 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4769 scoped_ptr
<SpdyFrame
> rst(
4770 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4771 MockWrite writes
[] = {
4772 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 7),
4775 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4776 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4778 CreateNetworkSession();
4779 CreateInsecureSpdySession();
4780 session_
->set_max_concurrent_pushed_streams(1);
4782 GURL
url1(kDefaultURL
);
4783 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4784 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url1
, LOWEST
, BoundNetLog());
4785 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4786 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4787 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4788 spdy_stream1
->SetDelegate(&delegate1
);
4790 EXPECT_EQ(0u, session_
->num_active_streams());
4791 EXPECT_EQ(1u, session_
->num_created_streams());
4792 EXPECT_EQ(0u, session_
->num_pushed_streams());
4793 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4795 scoped_ptr
<SpdyHeaderBlock
> headers(
4796 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4797 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4798 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4800 // Run until 1st stream is activated.
4801 EXPECT_EQ(0u, delegate1
.stream_id());
4802 base::RunLoop().RunUntilIdle();
4803 EXPECT_EQ(1u, delegate1
.stream_id());
4804 EXPECT_EQ(1u, session_
->num_active_streams());
4805 EXPECT_EQ(0u, session_
->num_created_streams());
4806 EXPECT_EQ(0u, session_
->num_pushed_streams());
4807 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4809 // Run until pushed stream is created.
4810 data
.CompleteRead();
4811 base::RunLoop().RunUntilIdle();
4812 EXPECT_EQ(2u, session_
->num_active_streams());
4813 EXPECT_EQ(0u, session_
->num_created_streams());
4814 EXPECT_EQ(1u, session_
->num_pushed_streams());
4815 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4817 // Accept promised stream. It should not count towards pushed stream limit.
4818 data
.CompleteRead();
4819 base::RunLoop().RunUntilIdle();
4820 EXPECT_EQ(3u, session_
->num_active_streams());
4821 EXPECT_EQ(0u, session_
->num_created_streams());
4822 EXPECT_EQ(2u, session_
->num_pushed_streams());
4823 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4825 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4826 // while we accept only one.
4827 data
.CompleteRead();
4828 base::RunLoop().RunUntilIdle();
4829 EXPECT_EQ(2u, session_
->num_active_streams());
4830 EXPECT_EQ(0u, session_
->num_created_streams());
4831 EXPECT_EQ(1u, session_
->num_pushed_streams());
4832 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4835 data
.CompleteRead();
4836 base::RunLoop().RunUntilIdle();
4837 EXPECT_FALSE(session_
);
4840 TEST_P(SpdySessionTest
, CancelReservedStreamOnHeadersReceived
) {
4841 // Streams in reserved remote state exist only in HTTP/2.
4842 if (spdy_util_
.spdy_version() < HTTP2
)
4845 const char kPushedUrl
[] = "http://www.example.org/a.dat";
4846 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4847 spdy_util_
.AddUrlToHeaderBlock(kPushedUrl
, push_headers
.get());
4848 scoped_ptr
<SpdyFrame
> push_promise(
4849 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 2, 1));
4850 scoped_ptr
<SpdyFrame
> headers_frame(
4851 spdy_util_
.ConstructSpdyPushHeaders(2, nullptr, 0));
4852 MockRead reads
[] = {
4853 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4854 CreateMockRead(*push_promise
, 2),
4855 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4856 CreateMockRead(*headers_frame
, 4),
4857 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
4858 MockRead(ASYNC
, 0, 7),
4861 scoped_ptr
<SpdyFrame
> req(
4862 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4863 scoped_ptr
<SpdyFrame
> rst(
4864 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
4865 MockWrite writes
[] = {
4866 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5),
4869 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4870 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4872 CreateNetworkSession();
4873 CreateInsecureSpdySession();
4875 GURL
url1(kDefaultURL
);
4876 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4877 SPDY_REQUEST_RESPONSE_STREAM
, session_
, url1
, LOWEST
, BoundNetLog());
4878 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4879 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4880 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4881 spdy_stream1
->SetDelegate(&delegate1
);
4883 EXPECT_EQ(0u, session_
->num_active_streams());
4884 EXPECT_EQ(1u, session_
->num_created_streams());
4885 EXPECT_EQ(0u, session_
->num_pushed_streams());
4886 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4888 scoped_ptr
<SpdyHeaderBlock
> headers(
4889 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4890 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4891 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4893 // Run until 1st stream is activated.
4894 EXPECT_EQ(0u, delegate1
.stream_id());
4895 base::RunLoop().RunUntilIdle();
4896 EXPECT_EQ(1u, delegate1
.stream_id());
4897 EXPECT_EQ(1u, session_
->num_active_streams());
4898 EXPECT_EQ(0u, session_
->num_created_streams());
4899 EXPECT_EQ(0u, session_
->num_pushed_streams());
4900 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4902 // Run until pushed stream is created.
4903 data
.CompleteRead();
4904 base::RunLoop().RunUntilIdle();
4905 EXPECT_EQ(2u, session_
->num_active_streams());
4906 EXPECT_EQ(0u, session_
->num_created_streams());
4907 EXPECT_EQ(1u, session_
->num_pushed_streams());
4908 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4910 base::WeakPtr
<SpdyStream
> pushed_stream
;
4912 session_
->GetPushStream(GURL(kPushedUrl
), &pushed_stream
, BoundNetLog());
4914 ASSERT_TRUE(pushed_stream
.get() != nullptr);
4915 test::StreamDelegateCloseOnHeaders
delegate2(pushed_stream
);
4916 pushed_stream
->SetDelegate(&delegate2
);
4918 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4919 // that all our counters are in consistent state.
4920 data
.CompleteRead();
4921 base::RunLoop().RunUntilIdle();
4922 EXPECT_EQ(1u, session_
->num_active_streams());
4923 EXPECT_EQ(0u, session_
->num_created_streams());
4924 EXPECT_EQ(0u, session_
->num_pushed_streams());
4925 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4928 data
.CompleteRead();
4929 base::RunLoop().RunUntilIdle();
4930 EXPECT_TRUE(data
.AllWriteDataConsumed());
4931 EXPECT_TRUE(data
.AllReadDataConsumed());
4934 TEST_P(SpdySessionTest
, RejectInvalidUnknownFrames
) {
4935 session_deps_
.host_resolver
->set_synchronous_mode(true);
4937 MockRead reads
[] = {
4938 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
4941 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
4942 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4944 CreateNetworkSession();
4945 CreateInsecureSpdySession();
4947 session_
->stream_hi_water_mark_
= 5;
4948 // Low client (odd) ids are fine.
4949 EXPECT_TRUE(session_
->OnUnknownFrame(3, 0));
4950 // Client id exceeding watermark.
4951 EXPECT_FALSE(session_
->OnUnknownFrame(9, 0));
4953 session_
->last_accepted_push_stream_id_
= 6;
4954 // Low server (even) ids are fine.
4955 EXPECT_TRUE(session_
->OnUnknownFrame(2, 0));
4956 // Server id exceeding last accepted id.
4957 EXPECT_FALSE(session_
->OnUnknownFrame(8, 0));
4960 TEST(MapFramerErrorToProtocolError
, MapsValues
) {
4962 SPDY_ERROR_INVALID_CONTROL_FRAME
,
4963 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4965 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS
,
4966 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
4968 SPDY_ERROR_GOAWAY_FRAME_CORRUPT
,
4969 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT
));
4970 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME
,
4971 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME
));
4974 TEST(MapFramerErrorToNetError
, MapsValue
) {
4975 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR
,
4976 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4977 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
4978 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE
));
4979 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
4980 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE
));
4982 ERR_SPDY_FRAME_SIZE_ERROR
,
4983 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
));
4986 TEST(MapRstStreamStatusToProtocolError
, MapsValues
) {
4987 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR
,
4988 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR
));
4989 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR
,
4990 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR
));
4991 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM
,
4992 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM
));
4993 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY
,
4994 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY
));
4995 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED
,
4996 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED
));
4999 TEST(MapNetErrorToGoAwayStatus
, MapsValue
) {
5000 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY
,
5001 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
));
5002 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR
,
5003 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR
));
5004 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
,
5005 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR
));
5006 CHECK_EQ(GOAWAY_COMPRESSION_ERROR
,
5007 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR
));
5008 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR
,
5009 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR
));
5010 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED
));
5013 TEST(CanPoolTest
, CanPool
) {
5014 // Load a cert that is valid for:
5019 TransportSecurityState tss
;
5021 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5022 "spdy_pooling.pem");
5024 EXPECT_TRUE(SpdySession::CanPool(
5025 &tss
, ssl_info
, "www.example.org", "www.example.org"));
5026 EXPECT_TRUE(SpdySession::CanPool(
5027 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5028 EXPECT_TRUE(SpdySession::CanPool(
5029 &tss
, ssl_info
, "www.example.org", "mail.example.com"));
5030 EXPECT_FALSE(SpdySession::CanPool(
5031 &tss
, ssl_info
, "www.example.org", "mail.google.com"));
5034 TEST(CanPoolTest
, CanNotPoolWithCertErrors
) {
5035 // Load a cert that is valid for:
5040 TransportSecurityState tss
;
5042 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5043 "spdy_pooling.pem");
5044 ssl_info
.cert_status
= CERT_STATUS_REVOKED
;
5046 EXPECT_FALSE(SpdySession::CanPool(
5047 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5050 TEST(CanPoolTest
, CanNotPoolWithClientCerts
) {
5051 // Load a cert that is valid for:
5056 TransportSecurityState tss
;
5058 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5059 "spdy_pooling.pem");
5060 ssl_info
.client_cert_sent
= true;
5062 EXPECT_FALSE(SpdySession::CanPool(
5063 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5066 TEST(CanPoolTest
, CanNotPoolAcrossETLDsWithChannelID
) {
5067 // Load a cert that is valid for:
5072 TransportSecurityState tss
;
5074 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5075 "spdy_pooling.pem");
5076 ssl_info
.channel_id_sent
= true;
5078 EXPECT_TRUE(SpdySession::CanPool(
5079 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5080 EXPECT_FALSE(SpdySession::CanPool(
5081 &tss
, ssl_info
, "www.example.org", "www.example.com"));
5084 TEST(CanPoolTest
, CanNotPoolWithBadPins
) {
5085 uint8 primary_pin
= 1;
5086 uint8 backup_pin
= 2;
5088 TransportSecurityState tss
;
5089 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5092 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5093 "spdy_pooling.pem");
5094 ssl_info
.is_issued_by_known_root
= true;
5095 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(bad_pin
));
5097 EXPECT_FALSE(SpdySession::CanPool(
5098 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5101 TEST(CanPoolTest
, CanPoolWithAcceptablePins
) {
5102 uint8 primary_pin
= 1;
5103 uint8 backup_pin
= 2;
5104 TransportSecurityState tss
;
5105 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5108 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5109 "spdy_pooling.pem");
5110 ssl_info
.is_issued_by_known_root
= true;
5111 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(primary_pin
));
5113 EXPECT_TRUE(SpdySession::CanPool(
5114 &tss
, ssl_info
, "www.example.org", "mail.example.org"));