1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/spdy/spdy_session.h"
7 #include "base/base64.h"
9 #include "base/callback.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/test/histogram_tester.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/ip_endpoint.h"
15 #include "net/base/request_priority.h"
16 #include "net/base/test_data_directory.h"
17 #include "net/base/test_data_stream.h"
18 #include "net/log/test_net_log.h"
19 #include "net/log/test_net_log_entry.h"
20 #include "net/log/test_net_log_util.h"
21 #include "net/socket/client_socket_pool_manager.h"
22 #include "net/socket/next_proto.h"
23 #include "net/socket/socket_test_util.h"
24 #include "net/spdy/spdy_http_utils.h"
25 #include "net/spdy/spdy_session_pool.h"
26 #include "net/spdy/spdy_session_test_util.h"
27 #include "net/spdy/spdy_stream.h"
28 #include "net/spdy/spdy_stream_test_util.h"
29 #include "net/spdy/spdy_test_util_common.h"
30 #include "net/spdy/spdy_test_utils.h"
31 #include "net/test/cert_test_util.h"
32 #include "testing/platform_test.h"
38 const char kBodyData
[] = "Body data";
39 const size_t kBodyDataSize
= arraysize(kBodyData
);
40 const base::StringPiece
kBodyDataStringPiece(kBodyData
, kBodyDataSize
);
42 static base::TimeDelta g_time_delta
;
43 base::TimeTicks
TheNearFuture() {
44 return base::TimeTicks::Now() + g_time_delta
;
47 base::TimeTicks
SlowReads() {
49 base::TimeDelta::FromMilliseconds(2 * kYieldAfterDurationMilliseconds
);
50 return base::TimeTicks::Now() + g_time_delta
;
55 class SpdySessionTest
: public PlatformTest
,
56 public ::testing::WithParamInterface
<NextProto
> {
58 // Functions used with RunResumeAfterUnstallTest().
60 void StallSessionOnly(SpdyStream
* stream
) { StallSessionSend(); }
62 void StallStreamOnly(SpdyStream
* stream
) { StallStreamSend(stream
); }
64 void StallSessionStream(SpdyStream
* stream
) {
66 StallStreamSend(stream
);
69 void StallStreamSession(SpdyStream
* stream
) {
70 StallStreamSend(stream
);
74 void UnstallSessionOnly(SpdyStream
* stream
, int32 delta_window_size
) {
75 UnstallSessionSend(delta_window_size
);
78 void UnstallStreamOnly(SpdyStream
* stream
, int32 delta_window_size
) {
79 UnstallStreamSend(stream
, delta_window_size
);
82 void UnstallSessionStream(SpdyStream
* stream
, int32 delta_window_size
) {
83 UnstallSessionSend(delta_window_size
);
84 UnstallStreamSend(stream
, delta_window_size
);
87 void UnstallStreamSession(SpdyStream
* stream
, int32 delta_window_size
) {
88 UnstallStreamSend(stream
, delta_window_size
);
89 UnstallSessionSend(delta_window_size
);
94 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
95 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
96 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
97 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
98 spdy_util_(GetParam()),
99 session_deps_(GetParam()),
100 spdy_session_pool_(nullptr),
101 test_url_(kDefaultURL
),
102 test_host_port_pair_(HostPortPair::FromURL(test_url_
)),
103 key_(test_host_port_pair_
,
104 ProxyServer::Direct(),
105 PRIVACY_MODE_DISABLED
) {}
107 virtual ~SpdySessionTest() {
108 // Important to restore the per-pool limit first, since the pool limit must
109 // always be greater than group limit, and the tests reduce both limits.
110 ClientSocketPoolManager::set_max_sockets_per_pool(
111 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
112 ClientSocketPoolManager::set_max_sockets_per_group(
113 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
116 void SetUp() override
{
117 g_time_delta
= base::TimeDelta();
118 session_deps_
.net_log
= log_
.bound().net_log();
121 void CreateNetworkSession() {
122 DCHECK(!http_session_
);
123 DCHECK(!spdy_session_pool_
);
125 SpdySessionDependencies::SpdyCreateSession(&session_deps_
);
126 spdy_session_pool_
= http_session_
->spdy_session_pool();
129 void CreateInsecureSpdySession() {
132 ::net::CreateInsecureSpdySession(http_session_
, key_
, log_
.bound());
135 void StallSessionSend() {
136 // Reduce the send window size to 0 to stall.
137 while (session_
->session_send_window_size_
> 0) {
138 session_
->DecreaseSendWindowSize(std::min(
139 kMaxSpdyFrameChunkSize
, session_
->session_send_window_size_
));
143 void UnstallSessionSend(int32 delta_window_size
) {
144 session_
->IncreaseSendWindowSize(delta_window_size
);
147 void StallStreamSend(SpdyStream
* stream
) {
148 // Reduce the send window size to 0 to stall.
149 while (stream
->send_window_size() > 0) {
150 stream
->DecreaseSendWindowSize(
151 std::min(kMaxSpdyFrameChunkSize
, stream
->send_window_size()));
155 void UnstallStreamSend(SpdyStream
* stream
, int32 delta_window_size
) {
156 stream
->IncreaseSendWindowSize(delta_window_size
);
159 void RunResumeAfterUnstallTest(
160 const base::Callback
<void(SpdyStream
*)>& stall_function
,
161 const base::Callback
<void(SpdyStream
*, int32
)>& unstall_function
);
163 // Original socket limits. Some tests set these. Safest to always restore
164 // them once each test has been run.
165 int old_max_group_sockets_
;
166 int old_max_pool_sockets_
;
168 SpdyTestUtil spdy_util_
;
169 SpdySessionDependencies session_deps_
;
170 scoped_refptr
<HttpNetworkSession
> http_session_
;
171 base::WeakPtr
<SpdySession
> session_
;
172 SpdySessionPool
* spdy_session_pool_
;
174 HostPortPair test_host_port_pair_
;
176 BoundTestNetLog log_
;
179 INSTANTIATE_TEST_CASE_P(NextProto
,
181 testing::Values(kProtoSPDY31
,
184 // Try to create a SPDY session that will fail during
185 // initialization. Nothing should blow up.
186 TEST_P(SpdySessionTest
, InitialReadError
) {
187 CreateNetworkSession();
189 session_
= TryCreateFakeSpdySessionExpectingFailure(spdy_session_pool_
, key_
,
190 ERR_CONNECTION_CLOSED
);
191 EXPECT_TRUE(session_
);
193 base::RunLoop().RunUntilIdle();
194 EXPECT_FALSE(session_
);
199 // A helper class that vends a callback that, when fired, destroys a
200 // given SpdyStreamRequest.
201 class StreamRequestDestroyingCallback
: public TestCompletionCallbackBase
{
203 StreamRequestDestroyingCallback() {}
205 ~StreamRequestDestroyingCallback() override
{}
207 void SetRequestToDestroy(scoped_ptr
<SpdyStreamRequest
> request
) {
208 request_
= request
.Pass();
211 CompletionCallback
MakeCallback() {
212 return base::Bind(&StreamRequestDestroyingCallback::OnComplete
,
213 base::Unretained(this));
217 void OnComplete(int result
) {
222 scoped_ptr
<SpdyStreamRequest
> request_
;
227 // Request kInitialMaxConcurrentStreams streams. Request two more
228 // streams, but have the callback for one destroy the second stream
229 // request. Close the session. Nothing should blow up. This is a
230 // regression test for http://crbug.com/250841 .
231 TEST_P(SpdySessionTest
, PendingStreamCancellingAnother
) {
232 session_deps_
.host_resolver
->set_synchronous_mode(true);
234 MockRead reads
[] = {MockRead(ASYNC
, 0, 0), };
236 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
237 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
239 CreateNetworkSession();
240 CreateInsecureSpdySession();
242 // Create the maximum number of concurrent streams.
243 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
244 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
245 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
246 ASSERT_TRUE(spdy_stream
!= nullptr);
249 SpdyStreamRequest request1
;
250 scoped_ptr
<SpdyStreamRequest
> request2(new SpdyStreamRequest
);
252 StreamRequestDestroyingCallback callback1
;
255 request1
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
256 MEDIUM
, BoundNetLog(), callback1
.MakeCallback()));
258 // |callback2| is never called.
259 TestCompletionCallback callback2
;
260 ASSERT_EQ(ERR_IO_PENDING
, request2
->StartRequest(
261 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
262 MEDIUM
, BoundNetLog(), callback2
.callback()));
264 callback1
.SetRequestToDestroy(request2
.Pass());
266 session_
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
268 EXPECT_EQ(ERR_ABORTED
, callback1
.WaitForResult());
271 // A session receiving a GOAWAY frame with no active streams should close.
272 TEST_P(SpdySessionTest
, GoAwayWithNoActiveStreams
) {
273 session_deps_
.host_resolver
->set_synchronous_mode(true);
275 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
277 CreateMockRead(*goaway
, 0),
279 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
280 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
282 CreateNetworkSession();
283 CreateInsecureSpdySession();
285 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
287 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
289 // Read and process the GOAWAY frame.
290 base::RunLoop().RunUntilIdle();
291 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
292 EXPECT_FALSE(session_
);
295 // A session receiving a GOAWAY frame immediately with no active
296 // streams should then close.
297 TEST_P(SpdySessionTest
, GoAwayImmediatelyWithNoActiveStreams
) {
298 session_deps_
.host_resolver
->set_synchronous_mode(true);
300 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
302 CreateMockRead(*goaway
, 0, SYNCHRONOUS
), MockRead(ASYNC
, 0, 1) // EOF
304 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
305 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
307 CreateNetworkSession();
309 session_
= TryCreateInsecureSpdySessionExpectingFailure(
310 http_session_
, key_
, ERR_CONNECTION_CLOSED
, BoundNetLog());
311 base::RunLoop().RunUntilIdle();
313 EXPECT_FALSE(session_
);
314 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
315 EXPECT_FALSE(data
.AllReadDataConsumed());
318 // A session receiving a GOAWAY frame with active streams should close
319 // when the last active stream is closed.
320 TEST_P(SpdySessionTest
, GoAwayWithActiveStreams
) {
321 session_deps_
.host_resolver
->set_synchronous_mode(true);
323 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
325 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
326 CreateMockRead(*goaway
, 3),
327 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
328 MockRead(ASYNC
, 0, 5) // EOF
330 scoped_ptr
<SpdyFrame
> req1(
331 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
332 scoped_ptr
<SpdyFrame
> req2(
333 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
334 MockWrite writes
[] = {
335 CreateMockWrite(*req1
, 0),
336 CreateMockWrite(*req2
, 1),
338 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
339 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
341 CreateNetworkSession();
342 CreateInsecureSpdySession();
344 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
346 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
347 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
348 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
349 spdy_stream1
->SetDelegate(&delegate1
);
351 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
352 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
353 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
354 spdy_stream2
->SetDelegate(&delegate2
);
356 scoped_ptr
<SpdyHeaderBlock
> headers(
357 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
358 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
360 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
361 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
362 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
363 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
365 base::RunLoop().RunUntilIdle();
367 EXPECT_EQ(1u, spdy_stream1
->stream_id());
368 EXPECT_EQ(3u, spdy_stream2
->stream_id());
370 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
372 // Read and process the GOAWAY frame.
374 base::RunLoop().RunUntilIdle();
376 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
378 EXPECT_FALSE(session_
->IsStreamActive(3));
379 EXPECT_FALSE(spdy_stream2
);
380 EXPECT_TRUE(session_
->IsStreamActive(1));
382 EXPECT_TRUE(session_
->IsGoingAway());
384 // Should close the session.
385 spdy_stream1
->Close();
386 EXPECT_FALSE(spdy_stream1
);
388 EXPECT_TRUE(session_
);
390 base::RunLoop().RunUntilIdle();
391 EXPECT_FALSE(session_
);
394 // Have a session receive two GOAWAY frames, with the last one causing
395 // the last active stream to be closed. The session should then be
396 // closed after the second GOAWAY frame.
397 TEST_P(SpdySessionTest
, GoAwayTwice
) {
398 session_deps_
.host_resolver
->set_synchronous_mode(true);
400 scoped_ptr
<SpdyFrame
> goaway1(spdy_util_
.ConstructSpdyGoAway(1));
401 scoped_ptr
<SpdyFrame
> goaway2(spdy_util_
.ConstructSpdyGoAway(0));
403 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
404 CreateMockRead(*goaway1
, 3),
405 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
406 CreateMockRead(*goaway2
, 5),
407 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
408 MockRead(ASYNC
, 0, 7) // EOF
410 scoped_ptr
<SpdyFrame
> req1(
411 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
412 scoped_ptr
<SpdyFrame
> req2(
413 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
414 MockWrite writes
[] = {
415 CreateMockWrite(*req1
, 0),
416 CreateMockWrite(*req2
, 1),
418 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
419 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
421 CreateNetworkSession();
422 CreateInsecureSpdySession();
424 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
426 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
427 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
428 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
429 spdy_stream1
->SetDelegate(&delegate1
);
431 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
432 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
433 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
434 spdy_stream2
->SetDelegate(&delegate2
);
436 scoped_ptr
<SpdyHeaderBlock
> headers(
437 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
438 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
440 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
441 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
442 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
443 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
445 base::RunLoop().RunUntilIdle();
447 EXPECT_EQ(1u, spdy_stream1
->stream_id());
448 EXPECT_EQ(3u, spdy_stream2
->stream_id());
450 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
452 // Read and process the first GOAWAY frame.
454 base::RunLoop().RunUntilIdle();
456 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
458 EXPECT_FALSE(session_
->IsStreamActive(3));
459 EXPECT_FALSE(spdy_stream2
);
460 EXPECT_TRUE(session_
->IsStreamActive(1));
461 EXPECT_TRUE(session_
->IsGoingAway());
463 // Read and process the second GOAWAY frame, which should close the
466 base::RunLoop().RunUntilIdle();
467 EXPECT_FALSE(session_
);
470 // Have a session with active streams receive a GOAWAY frame and then
471 // close it. It should handle the close properly (i.e., not try to
472 // make itself unavailable in its pool twice).
473 TEST_P(SpdySessionTest
, GoAwayWithActiveStreamsThenClose
) {
474 session_deps_
.host_resolver
->set_synchronous_mode(true);
476 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
478 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
479 CreateMockRead(*goaway
, 3),
480 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
481 MockRead(ASYNC
, 0, 5) // EOF
483 scoped_ptr
<SpdyFrame
> req1(
484 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
485 scoped_ptr
<SpdyFrame
> req2(
486 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
487 MockWrite writes
[] = {
488 CreateMockWrite(*req1
, 0),
489 CreateMockWrite(*req2
, 1),
491 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
492 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
494 CreateNetworkSession();
495 CreateInsecureSpdySession();
497 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
499 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
500 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
501 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
502 spdy_stream1
->SetDelegate(&delegate1
);
504 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
505 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
506 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
507 spdy_stream2
->SetDelegate(&delegate2
);
509 scoped_ptr
<SpdyHeaderBlock
> headers(
510 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
511 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
513 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
514 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
515 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
516 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
518 base::RunLoop().RunUntilIdle();
520 EXPECT_EQ(1u, spdy_stream1
->stream_id());
521 EXPECT_EQ(3u, spdy_stream2
->stream_id());
523 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
525 // Read and process the GOAWAY frame.
527 base::RunLoop().RunUntilIdle();
529 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
531 EXPECT_FALSE(session_
->IsStreamActive(3));
532 EXPECT_FALSE(spdy_stream2
);
533 EXPECT_TRUE(session_
->IsStreamActive(1));
534 EXPECT_TRUE(session_
->IsGoingAway());
536 session_
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
537 EXPECT_FALSE(spdy_stream1
);
540 base::RunLoop().RunUntilIdle();
541 EXPECT_FALSE(session_
);
544 // Process a joint read buffer which causes the session to begin draining, and
545 // then processes a GOAWAY. The session should gracefully drain. Regression test
546 // for crbug.com/379469
547 TEST_P(SpdySessionTest
, GoAwayWhileDraining
) {
548 session_deps_
.host_resolver
->set_synchronous_mode(true);
550 scoped_ptr
<SpdyFrame
> req(
551 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
552 MockWrite writes
[] = {
553 CreateMockWrite(*req
, 0),
556 scoped_ptr
<SpdyFrame
> resp(
557 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
558 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
559 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
560 size_t joint_size
= goaway
->size() * 2 + body
->size();
562 // Compose interleaved |goaway| and |body| frames into a single read.
563 scoped_ptr
<char[]> buffer(new char[joint_size
]);
566 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
567 out
+= goaway
->size();
568 memcpy(&buffer
[out
], body
->data(), body
->size());
570 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
571 out
+= goaway
->size();
572 ASSERT_EQ(out
, joint_size
);
574 SpdyFrame
joint_frames(buffer
.get(), joint_size
, false);
577 CreateMockRead(*resp
, 1), CreateMockRead(joint_frames
, 2),
578 MockRead(ASYNC
, 0, 3) // EOF
581 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
582 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
584 CreateNetworkSession();
585 CreateInsecureSpdySession();
587 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
588 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
589 test::StreamDelegateDoNothing
delegate(spdy_stream
);
590 spdy_stream
->SetDelegate(&delegate
);
592 scoped_ptr
<SpdyHeaderBlock
> headers(
593 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
594 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
595 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
597 base::RunLoop().RunUntilIdle();
599 // Stream and session closed gracefully.
600 EXPECT_TRUE(delegate
.StreamIsClosed());
601 EXPECT_EQ(OK
, delegate
.WaitForClose());
602 EXPECT_EQ(kUploadData
, delegate
.TakeReceivedData());
603 EXPECT_FALSE(session_
);
606 // Try to create a stream after receiving a GOAWAY frame. It should
608 TEST_P(SpdySessionTest
, CreateStreamAfterGoAway
) {
609 session_deps_
.host_resolver
->set_synchronous_mode(true);
611 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
613 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
614 CreateMockRead(*goaway
, 2),
615 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
616 MockRead(ASYNC
, 0, 4) // EOF
618 scoped_ptr
<SpdyFrame
> req(
619 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
620 MockWrite writes
[] = {
621 CreateMockWrite(*req
, 0),
623 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
624 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
626 CreateNetworkSession();
627 CreateInsecureSpdySession();
629 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
631 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
632 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
633 test::StreamDelegateDoNothing
delegate(spdy_stream
);
634 spdy_stream
->SetDelegate(&delegate
);
636 scoped_ptr
<SpdyHeaderBlock
> headers(
637 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
638 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
639 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
641 base::RunLoop().RunUntilIdle();
643 EXPECT_EQ(1u, spdy_stream
->stream_id());
645 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
647 // Read and process the GOAWAY frame.
649 base::RunLoop().RunUntilIdle();
651 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
652 EXPECT_TRUE(session_
->IsStreamActive(1));
654 SpdyStreamRequest stream_request
;
655 int rv
= stream_request
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
,
656 test_url_
, MEDIUM
, BoundNetLog(),
657 CompletionCallback());
658 EXPECT_EQ(ERR_FAILED
, rv
);
660 EXPECT_TRUE(session_
);
662 base::RunLoop().RunUntilIdle();
663 EXPECT_FALSE(session_
);
666 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
667 // the stream being refused.
668 TEST_P(SpdySessionTest
, SynStreamAfterGoAway
) {
669 session_deps_
.host_resolver
->set_synchronous_mode(true);
671 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
672 scoped_ptr
<SpdyFrame
> push(
673 spdy_util_
.ConstructSpdyPush(nullptr, 0, 2, 1, kDefaultURL
));
675 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
676 CreateMockRead(*goaway
, 2),
677 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
678 CreateMockRead(*push
, 4),
679 MockRead(ASYNC
, 0, 6) // EOF
681 scoped_ptr
<SpdyFrame
> req(
682 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
683 scoped_ptr
<SpdyFrame
> rst(
684 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
685 MockWrite writes
[] = {CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5)};
686 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
687 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
689 CreateNetworkSession();
690 CreateInsecureSpdySession();
692 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
694 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
695 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
696 test::StreamDelegateDoNothing
delegate(spdy_stream
);
697 spdy_stream
->SetDelegate(&delegate
);
699 scoped_ptr
<SpdyHeaderBlock
> headers(
700 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
701 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
702 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
704 base::RunLoop().RunUntilIdle();
706 EXPECT_EQ(1u, spdy_stream
->stream_id());
708 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
710 // Read and process the GOAWAY frame.
712 base::RunLoop().RunUntilIdle();
714 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
715 EXPECT_TRUE(session_
->IsStreamActive(1));
717 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
720 base::RunLoop().RunUntilIdle();
721 EXPECT_FALSE(session_
);
724 // A session observing a network change with active streams should close
725 // when the last active stream is closed.
726 TEST_P(SpdySessionTest
, NetworkChangeWithActiveStreams
) {
727 session_deps_
.host_resolver
->set_synchronous_mode(true);
730 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
732 scoped_ptr
<SpdyFrame
> req1(
733 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
734 MockWrite writes
[] = {
735 CreateMockWrite(*req1
, 0),
737 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
738 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
740 CreateNetworkSession();
741 CreateInsecureSpdySession();
743 EXPECT_EQ(spdy_util_
.spdy_version(), session_
->GetProtocolVersion());
745 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
746 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
747 test::StreamDelegateDoNothing
delegate(spdy_stream
);
748 spdy_stream
->SetDelegate(&delegate
);
750 scoped_ptr
<SpdyHeaderBlock
> headers(
751 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
753 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
754 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
756 base::RunLoop().RunUntilIdle();
758 EXPECT_EQ(1u, spdy_stream
->stream_id());
760 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
762 spdy_session_pool_
->OnIPAddressChanged();
764 // The SpdySessionPool behavior differs based on how the OSs reacts to
765 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
766 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
767 // For OSs where the TCP connections will close upon relevant network
768 // changes, SpdySessionPool doesn't need to force them to close, so in these
769 // cases verify the session has become unavailable but remains open and the
770 // pre-existing stream is still active.
771 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
773 EXPECT_TRUE(session_
->IsGoingAway());
775 EXPECT_TRUE(session_
->IsStreamActive(1));
777 // Should close the session.
778 spdy_stream
->Close();
780 EXPECT_FALSE(spdy_stream
);
783 base::RunLoop().RunUntilIdle();
784 EXPECT_FALSE(session_
);
787 TEST_P(SpdySessionTest
, ClientPing
) {
788 session_deps_
.enable_ping
= true;
789 session_deps_
.host_resolver
->set_synchronous_mode(true);
791 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(1, true));
793 CreateMockRead(*read_ping
, 1),
794 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
795 MockRead(ASYNC
, 0, 3) // EOF
797 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
798 MockWrite writes
[] = {
799 CreateMockWrite(*write_ping
, 0),
801 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
802 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
804 CreateNetworkSession();
805 CreateInsecureSpdySession();
807 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
808 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
809 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
810 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
811 spdy_stream1
->SetDelegate(&delegate
);
813 base::TimeTicks before_ping_time
= base::TimeTicks::Now();
815 session_
->set_connection_at_risk_of_loss_time(
816 base::TimeDelta::FromSeconds(-1));
817 session_
->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
819 session_
->SendPrefacePingIfNoneInFlight();
821 base::RunLoop().RunUntilIdle();
823 session_
->CheckPingStatus(before_ping_time
);
825 EXPECT_EQ(0, session_
->pings_in_flight());
826 EXPECT_GE(session_
->next_ping_id(), 1U);
827 EXPECT_FALSE(session_
->check_ping_status_pending());
828 EXPECT_GE(session_
->last_activity_time(), before_ping_time
);
831 base::RunLoop().RunUntilIdle();
833 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
835 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
836 EXPECT_FALSE(session_
);
839 TEST_P(SpdySessionTest
, ServerPing
) {
840 session_deps_
.host_resolver
->set_synchronous_mode(true);
842 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(2, false));
844 CreateMockRead(*read_ping
),
845 MockRead(SYNCHRONOUS
, 0, 0) // EOF
847 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(2, true));
848 MockWrite writes
[] = {
849 CreateMockWrite(*write_ping
),
851 StaticSocketDataProvider
data(
852 reads
, arraysize(reads
), writes
, arraysize(writes
));
853 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
855 CreateNetworkSession();
856 CreateInsecureSpdySession();
858 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
859 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
860 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
861 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
862 spdy_stream1
->SetDelegate(&delegate
);
864 // Flush the read completion task.
865 base::RunLoop().RunUntilIdle();
867 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
869 EXPECT_FALSE(session_
);
870 EXPECT_FALSE(spdy_stream1
);
873 // Cause a ping to be sent out while producing a write. The write loop
874 // should handle this properly, i.e. another DoWriteLoop task should
875 // not be posted. This is a regression test for
876 // http://crbug.com/261043 .
877 TEST_P(SpdySessionTest
, PingAndWriteLoop
) {
878 session_deps_
.enable_ping
= true;
879 session_deps_
.time_func
= TheNearFuture
;
881 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
882 scoped_ptr
<SpdyFrame
> req(
883 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
884 MockWrite writes
[] = {
885 CreateMockWrite(*req
, 0),
886 CreateMockWrite(*write_ping
, 1),
890 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
893 session_deps_
.host_resolver
->set_synchronous_mode(true);
895 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
896 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
898 CreateNetworkSession();
899 CreateInsecureSpdySession();
901 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
902 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
903 test::StreamDelegateDoNothing
delegate(spdy_stream
);
904 spdy_stream
->SetDelegate(&delegate
);
906 scoped_ptr
<SpdyHeaderBlock
> headers(
907 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
908 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
910 // Shift time so that a ping will be sent out.
911 g_time_delta
= base::TimeDelta::FromSeconds(11);
913 base::RunLoop().RunUntilIdle();
914 session_
->CloseSessionOnError(ERR_ABORTED
, "Aborting");
917 base::RunLoop().RunUntilIdle();
918 EXPECT_FALSE(session_
);
921 TEST_P(SpdySessionTest
, StreamIdSpaceExhausted
) {
922 const SpdyStreamId kLastStreamId
= 0x7fffffff;
923 session_deps_
.host_resolver
->set_synchronous_mode(true);
925 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
926 // fixed to allow for two stream ID assignments, and three concurrent
927 // streams. Four streams are started, and two are activated. Verify the
928 // session goes away, and that the created (but not activated) and
929 // stalled streams are aborted. Also verify the activated streams complete,
930 // at which point the session closes.
932 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyGet(
933 nullptr, 0, false, kLastStreamId
- 2, MEDIUM
, true));
934 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyGet(
935 nullptr, 0, false, kLastStreamId
, MEDIUM
, true));
937 MockWrite writes
[] = {
938 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
941 scoped_ptr
<SpdyFrame
> resp1(
942 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId
- 2));
943 scoped_ptr
<SpdyFrame
> resp2(
944 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId
));
946 scoped_ptr
<SpdyFrame
> body1(
947 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
- 2, true));
948 scoped_ptr
<SpdyFrame
> body2(
949 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
, true));
952 CreateMockRead(*resp1
, 2),
953 CreateMockRead(*resp2
, 3),
954 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
955 CreateMockRead(*body1
, 5),
956 CreateMockRead(*body2
, 6),
957 MockRead(ASYNC
, 0, 7) // EOF
960 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
961 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
963 CreateNetworkSession();
964 CreateInsecureSpdySession();
966 // Fix stream_hi_water_mark_ to allow for two stream activations.
967 session_
->stream_hi_water_mark_
= kLastStreamId
- 2;
968 // Fix max_concurrent_streams to allow for three stream creations.
969 session_
->max_concurrent_streams_
= 3;
971 // Create three streams synchronously, and begin a fourth (which is stalled).
972 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
973 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
974 test::StreamDelegateDoNothing
delegate1(stream1
);
975 stream1
->SetDelegate(&delegate1
);
977 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
978 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
979 test::StreamDelegateDoNothing
delegate2(stream2
);
980 stream2
->SetDelegate(&delegate2
);
982 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
983 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
984 test::StreamDelegateDoNothing
delegate3(stream3
);
985 stream3
->SetDelegate(&delegate3
);
987 SpdyStreamRequest request4
;
988 TestCompletionCallback callback4
;
991 request4
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
,
992 MEDIUM
, BoundNetLog(), callback4
.callback()));
994 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
995 EXPECT_EQ(0u, session_
->num_active_streams());
996 EXPECT_EQ(3u, session_
->num_created_streams());
997 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(MEDIUM
));
999 // Activate stream 1. One ID remains available.
1000 stream1
->SendRequestHeaders(
1001 scoped_ptr
<SpdyHeaderBlock
>(
1002 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
)),
1003 NO_MORE_DATA_TO_SEND
);
1004 base::RunLoop().RunUntilIdle();
1006 EXPECT_EQ(kLastStreamId
- 2u, stream1
->stream_id());
1007 EXPECT_EQ(1u, session_
->num_active_streams());
1008 EXPECT_EQ(2u, session_
->num_created_streams());
1009 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(MEDIUM
));
1011 // Activate stream 2. ID space is exhausted.
1012 stream2
->SendRequestHeaders(
1013 scoped_ptr
<SpdyHeaderBlock
>(
1014 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
)),
1015 NO_MORE_DATA_TO_SEND
);
1016 base::RunLoop().RunUntilIdle();
1018 // Active streams remain active.
1019 EXPECT_EQ(kLastStreamId
, stream2
->stream_id());
1020 EXPECT_EQ(2u, session_
->num_active_streams());
1022 // Session is going away. Created and stalled streams were aborted.
1023 EXPECT_EQ(SpdySession::STATE_GOING_AWAY
, session_
->availability_state_
);
1024 EXPECT_EQ(ERR_ABORTED
, delegate3
.WaitForClose());
1025 EXPECT_EQ(ERR_ABORTED
, callback4
.WaitForResult());
1026 EXPECT_EQ(0u, session_
->num_created_streams());
1027 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(MEDIUM
));
1029 // Read responses on remaining active streams.
1030 data
.CompleteRead();
1031 base::RunLoop().RunUntilIdle();
1032 EXPECT_EQ(OK
, delegate1
.WaitForClose());
1033 EXPECT_EQ(kUploadData
, delegate1
.TakeReceivedData());
1034 EXPECT_EQ(OK
, delegate2
.WaitForClose());
1035 EXPECT_EQ(kUploadData
, delegate2
.TakeReceivedData());
1037 // Session was destroyed.
1038 EXPECT_FALSE(session_
);
1041 // Verifies that an unstalled pending stream creation racing with a new stream
1042 // creation doesn't violate the maximum stream concurrency. Regression test for
1043 // crbug.com/373858.
1044 TEST_P(SpdySessionTest
, UnstallRacesWithStreamCreation
) {
1045 session_deps_
.host_resolver
->set_synchronous_mode(true);
1047 MockRead reads
[] = {
1048 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1051 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1052 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1054 CreateNetworkSession();
1055 CreateInsecureSpdySession();
1057 // Fix max_concurrent_streams to allow for one open stream.
1058 session_
->max_concurrent_streams_
= 1;
1060 // Create two streams: one synchronously, and one which stalls.
1061 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
1062 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1064 SpdyStreamRequest request2
;
1065 TestCompletionCallback callback2
;
1068 request2
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
,
1069 MEDIUM
, BoundNetLog(), callback2
.callback()));
1071 EXPECT_EQ(1u, session_
->num_created_streams());
1072 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(MEDIUM
));
1074 // Cancel the first stream. A callback to unstall the second stream was
1075 // posted. Don't run it yet.
1078 EXPECT_EQ(0u, session_
->num_created_streams());
1079 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(MEDIUM
));
1081 // Create a third stream prior to the second stream's callback.
1082 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
1083 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1085 EXPECT_EQ(1u, session_
->num_created_streams());
1086 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(MEDIUM
));
1088 // Now run the message loop. The unstalled stream will re-stall itself.
1089 base::RunLoop().RunUntilIdle();
1090 EXPECT_EQ(1u, session_
->num_created_streams());
1091 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(MEDIUM
));
1093 // Cancel the third stream and run the message loop. Verify that the second
1094 // stream creation now completes.
1096 base::RunLoop().RunUntilIdle();
1098 EXPECT_EQ(1u, session_
->num_created_streams());
1099 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(MEDIUM
));
1100 EXPECT_EQ(OK
, callback2
.WaitForResult());
1103 TEST_P(SpdySessionTest
, DeleteExpiredPushStreams
) {
1104 session_deps_
.host_resolver
->set_synchronous_mode(true);
1105 session_deps_
.time_func
= TheNearFuture
;
1107 scoped_ptr
<SpdyFrame
> req(
1108 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
1109 scoped_ptr
<SpdyFrame
> rst(
1110 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
1111 MockWrite writes
[] = {CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5)};
1113 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
1114 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
1115 scoped_ptr
<SpdyFrame
> push_a_body(
1116 spdy_util_
.ConstructSpdyBodyFrame(2, false));
1117 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1118 // iterators inside. See http://crbug.com/443490
1119 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
1120 nullptr, 0, 4, 1, "http://www.example.org/0.dat"));
1121 MockRead reads
[] = {
1122 CreateMockRead(*push_a
, 1),
1123 CreateMockRead(*push_a_body
, 2),
1124 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
1125 CreateMockRead(*push_b
, 4),
1126 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
1127 MockRead(ASYNC
, 0, 7) // EOF
1130 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1131 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1133 CreateNetworkSession();
1134 CreateInsecureSpdySession();
1136 // Process the principal request, and the first push stream request & body.
1137 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1138 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1139 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1140 spdy_stream
->SetDelegate(&delegate
);
1142 scoped_ptr
<SpdyHeaderBlock
> headers(
1143 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1144 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1146 base::RunLoop().RunUntilIdle();
1148 // Verify that there is one unclaimed push stream.
1149 EXPECT_EQ(1u, session_
->num_unclaimed_pushed_streams());
1150 SpdySession::PushedStreamMap::iterator iter
=
1151 session_
->unclaimed_pushed_streams_
.find(
1152 GURL("http://www.example.org/a.dat"));
1153 EXPECT_TRUE(session_
->unclaimed_pushed_streams_
.end() != iter
);
1155 if (session_
->flow_control_state_
==
1156 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1157 // Unclaimed push body consumed bytes from the session window.
1159 SpdySession::GetDefaultInitialWindowSize(GetParam()) - kUploadDataSize
,
1160 session_
->session_recv_window_size_
);
1161 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
1164 // Shift time to expire the push stream. Read the second SYN_STREAM,
1165 // and verify a RST_STREAM was written.
1166 g_time_delta
= base::TimeDelta::FromSeconds(301);
1167 data
.CompleteRead();
1168 base::RunLoop().RunUntilIdle();
1170 // Verify that the second pushed stream evicted the first pushed stream.
1171 EXPECT_EQ(1u, session_
->num_unclaimed_pushed_streams());
1172 iter
= session_
->unclaimed_pushed_streams_
.find(
1173 GURL("http://www.example.org/0.dat"));
1174 EXPECT_TRUE(session_
->unclaimed_pushed_streams_
.end() != iter
);
1176 if (session_
->flow_control_state_
==
1177 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1178 // Verify that the session window reclaimed the evicted stream body.
1179 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
1180 session_
->session_recv_window_size_
);
1181 EXPECT_EQ(kUploadDataSize
, session_
->session_unacked_recv_window_bytes_
);
1184 // Read and process EOF.
1185 EXPECT_TRUE(session_
);
1186 data
.CompleteRead();
1187 base::RunLoop().RunUntilIdle();
1188 EXPECT_FALSE(session_
);
1191 TEST_P(SpdySessionTest
, FailedPing
) {
1192 session_deps_
.host_resolver
->set_synchronous_mode(true);
1194 MockRead reads
[] = {
1195 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1197 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
1198 scoped_ptr
<SpdyFrame
> goaway(
1199 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Failed ping."));
1200 MockWrite writes
[] = {CreateMockWrite(*write_ping
), CreateMockWrite(*goaway
)};
1202 StaticSocketDataProvider
data(
1203 reads
, arraysize(reads
), writes
, arraysize(writes
));
1204 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1206 CreateNetworkSession();
1207 CreateInsecureSpdySession();
1209 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1210 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1211 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1212 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, nullptr);
1213 spdy_stream1
->SetDelegate(&delegate
);
1215 session_
->set_connection_at_risk_of_loss_time(
1216 base::TimeDelta::FromSeconds(0));
1217 session_
->set_hung_interval(base::TimeDelta::FromSeconds(0));
1219 // Send a PING frame.
1220 session_
->WritePingFrame(1, false);
1221 EXPECT_LT(0, session_
->pings_in_flight());
1222 EXPECT_GE(session_
->next_ping_id(), 1U);
1223 EXPECT_TRUE(session_
->check_ping_status_pending());
1225 // Assert session is not closed.
1226 EXPECT_TRUE(session_
->IsAvailable());
1228 session_
->num_active_streams() + session_
->num_created_streams());
1229 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1231 // We set last time we have received any data in 1 sec less than now.
1232 // CheckPingStatus will trigger timeout because hung interval is zero.
1233 base::TimeTicks now
= base::TimeTicks::Now();
1234 session_
->last_activity_time_
= now
- base::TimeDelta::FromSeconds(1);
1235 session_
->CheckPingStatus(now
);
1236 base::RunLoop().RunUntilIdle();
1238 EXPECT_FALSE(session_
);
1239 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1240 EXPECT_FALSE(spdy_stream1
);
1243 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1244 // settings frame increasing the max concurrent streams by 1. Make
1245 // sure nothing blows up. This is a regression test for
1246 // http://crbug.com/57331 .
1247 TEST_P(SpdySessionTest
, OnSettings
) {
1248 session_deps_
.host_resolver
->set_synchronous_mode(true);
1250 const SpdySettingsIds kSpdySettingsIds
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1253 std::vector
<MockWrite
> writes
;
1254 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1255 if (GetParam() == kProtoHTTP2
) {
1256 writes
.push_back(CreateMockWrite(*settings_ack
, ++seq
));
1259 SettingsMap new_settings
;
1260 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1261 new_settings
[kSpdySettingsIds
] =
1262 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1263 scoped_ptr
<SpdyFrame
> settings_frame(
1264 spdy_util_
.ConstructSpdySettings(new_settings
));
1265 MockRead reads
[] = {
1266 CreateMockRead(*settings_frame
, 0),
1267 MockRead(ASYNC
, ERR_IO_PENDING
, ++seq
),
1268 MockRead(ASYNC
, 0, ++seq
),
1271 SequencedSocketData
data(reads
, arraysize(reads
), vector_as_array(&writes
),
1273 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1275 CreateNetworkSession();
1276 CreateInsecureSpdySession();
1278 // Create the maximum number of concurrent streams.
1279 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1280 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1281 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1282 ASSERT_TRUE(spdy_stream
!= nullptr);
1285 StreamReleaserCallback stream_releaser
;
1286 SpdyStreamRequest request
;
1287 ASSERT_EQ(ERR_IO_PENDING
,
1288 request
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
1289 MEDIUM
, BoundNetLog(),
1290 stream_releaser
.MakeCallback(&request
)));
1292 base::RunLoop().RunUntilIdle();
1294 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1296 data
.CompleteRead();
1297 base::RunLoop().RunUntilIdle();
1298 EXPECT_FALSE(session_
);
1300 EXPECT_TRUE(data
.AllWriteDataConsumed());
1301 EXPECT_TRUE(data
.AllReadDataConsumed());
1304 // Start with a persisted value for max concurrent streams. Receive a
1305 // settings frame increasing the max concurrent streams by 1 and which
1306 // also clears the persisted data. Verify that persisted data is
1308 TEST_P(SpdySessionTest
, ClearSettings
) {
1309 if (spdy_util_
.spdy_version() >= HTTP2
) {
1310 // HTTP/2 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1311 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in HTTP/2.
1314 session_deps_
.host_resolver
->set_synchronous_mode(true);
1316 SettingsMap new_settings
;
1317 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1318 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1319 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1320 scoped_ptr
<SpdyFrame
> settings_frame(
1321 spdy_util_
.ConstructSpdySettings(new_settings
));
1322 uint8 flags
= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
1323 test::SetFrameFlags(settings_frame
.get(), flags
, spdy_util_
.spdy_version());
1324 MockRead reads
[] = {
1325 CreateMockRead(*settings_frame
, 0),
1326 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
1327 MockRead(ASYNC
, 0, 2),
1330 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
1331 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1333 CreateNetworkSession();
1335 // Initialize the SpdySetting with the default.
1336 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1337 test_host_port_pair_
,
1338 SETTINGS_MAX_CONCURRENT_STREAMS
,
1339 SETTINGS_FLAG_PLEASE_PERSIST
,
1340 kInitialMaxConcurrentStreams
);
1343 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1344 test_host_port_pair_
).empty());
1346 CreateInsecureSpdySession();
1348 // Create the maximum number of concurrent streams.
1349 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1350 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1351 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1352 ASSERT_TRUE(spdy_stream
!= nullptr);
1355 StreamReleaserCallback stream_releaser
;
1357 SpdyStreamRequest request
;
1358 ASSERT_EQ(ERR_IO_PENDING
,
1359 request
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
1360 MEDIUM
, BoundNetLog(),
1361 stream_releaser
.MakeCallback(&request
)));
1363 base::RunLoop().RunUntilIdle();
1365 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1367 // Make sure that persisted data is cleared.
1369 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1370 test_host_port_pair_
).empty());
1372 // Make sure session's max_concurrent_streams is correct.
1373 EXPECT_EQ(kInitialMaxConcurrentStreams
+ 1,
1374 session_
->max_concurrent_streams());
1376 data
.CompleteRead();
1377 base::RunLoop().RunUntilIdle();
1378 EXPECT_FALSE(session_
);
1381 // Start with max concurrent streams set to 1. Request two streams.
1382 // When the first completes, have the callback close its stream, which
1383 // should trigger the second stream creation. Then cancel that one
1384 // immediately. Don't crash. This is a regression test for
1385 // http://crbug.com/63532 .
1386 TEST_P(SpdySessionTest
, CancelPendingCreateStream
) {
1387 session_deps_
.host_resolver
->set_synchronous_mode(true);
1389 MockRead reads
[] = {
1390 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1393 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1394 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1396 CreateNetworkSession();
1398 // Initialize the SpdySetting with 1 max concurrent streams.
1399 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1400 test_host_port_pair_
,
1401 SETTINGS_MAX_CONCURRENT_STREAMS
,
1402 SETTINGS_FLAG_PLEASE_PERSIST
,
1405 CreateInsecureSpdySession();
1407 // Leave room for only one more stream to be created.
1408 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
1409 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1410 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1411 ASSERT_TRUE(spdy_stream
!= nullptr);
1414 // Create 2 more streams. First will succeed. Second will be pending.
1415 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1416 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1417 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1419 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1420 // a valgrind error if the callback is invoked when it's not supposed to be.
1421 scoped_ptr
<TestCompletionCallback
> callback(new TestCompletionCallback
);
1423 SpdyStreamRequest request
;
1424 ASSERT_EQ(ERR_IO_PENDING
,
1425 request
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
1426 MEDIUM
, BoundNetLog(), callback
->callback()));
1428 // Release the first one, this will allow the second to be created.
1429 spdy_stream1
->Cancel();
1430 EXPECT_FALSE(spdy_stream1
);
1432 request
.CancelRequest();
1435 // Should not crash when running the pending callback.
1436 base::RunLoop().RunUntilIdle();
1439 TEST_P(SpdySessionTest
, SendInitialDataOnNewSession
) {
1440 session_deps_
.host_resolver
->set_synchronous_mode(true);
1442 MockRead reads
[] = {
1443 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1446 SettingsMap settings
;
1447 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1448 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
1449 scoped_ptr
<SpdyFrame
> settings_frame(
1450 spdy_util_
.ConstructSpdySettings(settings
));
1451 std::vector
<MockWrite
> writes
;
1452 if (GetParam() == kProtoHTTP2
) {
1455 kHttp2ConnectionHeaderPrefix
,
1456 kHttp2ConnectionHeaderPrefixSize
));
1458 writes
.push_back(CreateMockWrite(*settings_frame
));
1460 SettingsMap server_settings
;
1461 const uint32 initial_max_concurrent_streams
= 1;
1462 server_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1463 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED
,
1464 initial_max_concurrent_streams
);
1465 scoped_ptr
<SpdyFrame
> server_settings_frame(
1466 spdy_util_
.ConstructSpdySettings(server_settings
));
1467 if (GetParam() <= kProtoSPDY31
) {
1468 writes
.push_back(CreateMockWrite(*server_settings_frame
));
1471 StaticSocketDataProvider
data(reads
, arraysize(reads
),
1472 vector_as_array(&writes
), writes
.size());
1473 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1475 CreateNetworkSession();
1477 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1478 test_host_port_pair_
,
1479 SETTINGS_MAX_CONCURRENT_STREAMS
,
1480 SETTINGS_FLAG_PLEASE_PERSIST
,
1481 initial_max_concurrent_streams
);
1483 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
1484 pool_peer
.SetEnableSendingInitialData(true);
1486 CreateInsecureSpdySession();
1488 base::RunLoop().RunUntilIdle();
1489 EXPECT_TRUE(data
.AllWriteDataConsumed());
1492 TEST_P(SpdySessionTest
, ClearSettingsStorageOnIPAddressChanged
) {
1493 CreateNetworkSession();
1495 base::WeakPtr
<HttpServerProperties
> test_http_server_properties
=
1496 spdy_session_pool_
->http_server_properties();
1497 SettingsFlagsAndValue
flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST
, 2);
1498 test_http_server_properties
->SetSpdySetting(
1499 test_host_port_pair_
,
1500 SETTINGS_MAX_CONCURRENT_STREAMS
,
1501 SETTINGS_FLAG_PLEASE_PERSIST
,
1503 EXPECT_NE(0u, test_http_server_properties
->GetSpdySettings(
1504 test_host_port_pair_
).size());
1505 spdy_session_pool_
->OnIPAddressChanged();
1506 EXPECT_EQ(0u, test_http_server_properties
->GetSpdySettings(
1507 test_host_port_pair_
).size());
1510 TEST_P(SpdySessionTest
, Initialize
) {
1511 session_deps_
.host_resolver
->set_synchronous_mode(true);
1513 MockRead reads
[] = {
1514 MockRead(ASYNC
, 0, 0) // EOF
1517 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1518 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1520 CreateNetworkSession();
1521 CreateInsecureSpdySession();
1522 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1524 // Flush the read completion task.
1525 base::RunLoop().RunUntilIdle();
1527 TestNetLogEntry::List entries
;
1528 log_
.GetEntries(&entries
);
1529 EXPECT_LT(0u, entries
.size());
1531 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1532 int pos
= ExpectLogContainsSomewhere(
1533 entries
, 0, NetLog::TYPE_HTTP2_SESSION_INITIALIZED
, NetLog::PHASE_NONE
);
1536 TestNetLogEntry entry
= entries
[pos
];
1537 NetLog::Source socket_source
;
1538 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry
.params
.get(),
1540 EXPECT_TRUE(socket_source
.IsValid());
1541 EXPECT_NE(log_
.bound().source().id
, socket_source
.id
);
1544 TEST_P(SpdySessionTest
, NetLogOnSessionGoaway
) {
1545 session_deps_
.host_resolver
->set_synchronous_mode(true);
1547 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
1548 MockRead reads
[] = {
1549 CreateMockRead(*goaway
),
1550 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1553 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1554 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1556 CreateNetworkSession();
1557 CreateInsecureSpdySession();
1558 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1560 // Flush the read completion task.
1561 base::RunLoop().RunUntilIdle();
1563 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1564 EXPECT_FALSE(session_
);
1566 // Check that the NetLog was filled reasonably.
1567 TestNetLogEntry::List entries
;
1568 log_
.GetEntries(&entries
);
1569 EXPECT_LT(0u, entries
.size());
1571 // Check that we logged SPDY_SESSION_CLOSE correctly.
1572 int pos
= ExpectLogContainsSomewhere(
1573 entries
, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE
, NetLog::PHASE_NONE
);
1575 if (pos
< static_cast<int>(entries
.size())) {
1576 TestNetLogEntry entry
= entries
[pos
];
1578 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1579 EXPECT_EQ(OK
, error_code
);
1585 TEST_P(SpdySessionTest
, NetLogOnSessionEOF
) {
1586 session_deps_
.host_resolver
->set_synchronous_mode(true);
1588 MockRead reads
[] = {
1589 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1592 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
1593 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1595 CreateNetworkSession();
1596 CreateInsecureSpdySession();
1597 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1599 // Flush the read completion task.
1600 base::RunLoop().RunUntilIdle();
1602 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1603 EXPECT_FALSE(session_
);
1605 // Check that the NetLog was filled reasonably.
1606 TestNetLogEntry::List entries
;
1607 log_
.GetEntries(&entries
);
1608 EXPECT_LT(0u, entries
.size());
1610 // Check that we logged SPDY_SESSION_CLOSE correctly.
1611 int pos
= ExpectLogContainsSomewhere(
1612 entries
, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE
, NetLog::PHASE_NONE
);
1614 if (pos
< static_cast<int>(entries
.size())) {
1615 TestNetLogEntry entry
= entries
[pos
];
1617 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1618 EXPECT_EQ(ERR_CONNECTION_CLOSED
, error_code
);
1624 TEST_P(SpdySessionTest
, SynCompressionHistograms
) {
1625 session_deps_
.enable_compression
= true;
1627 scoped_ptr
<SpdyFrame
> req(
1628 spdy_util_
.ConstructSpdyGet(nullptr, 0, true, 1, MEDIUM
, true));
1629 MockWrite writes
[] = {
1630 CreateMockWrite(*req
, 0),
1632 MockRead reads
[] = {
1633 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
1635 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1636 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1638 CreateNetworkSession();
1639 CreateInsecureSpdySession();
1641 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1642 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1643 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1644 spdy_stream
->SetDelegate(&delegate
);
1646 scoped_ptr
<SpdyHeaderBlock
> headers(
1647 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1648 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1649 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
1651 // Write request headers & capture resulting histogram update.
1652 base::HistogramTester histogram_tester
;
1654 base::RunLoop().RunUntilIdle();
1655 // Regression test of compression performance under the request fixture.
1656 switch (spdy_util_
.spdy_version()) {
1658 histogram_tester
.ExpectBucketCount(
1659 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1662 histogram_tester
.ExpectBucketCount(
1663 "Net.SpdySynStreamCompressionPercentage", 81, 1);
1669 // Read and process EOF.
1670 EXPECT_TRUE(session_
);
1671 data
.CompleteRead();
1672 base::RunLoop().RunUntilIdle();
1673 EXPECT_FALSE(session_
);
1676 // Queue up a low-priority SYN_STREAM followed by a high-priority
1677 // one. The high priority one should still send first and receive
1679 TEST_P(SpdySessionTest
, OutOfOrderSynStreams
) {
1680 // Construct the request.
1681 scoped_ptr
<SpdyFrame
> req_highest(
1682 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, HIGHEST
, true));
1683 scoped_ptr
<SpdyFrame
> req_lowest(
1684 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST
, true));
1685 MockWrite writes
[] = {
1686 CreateMockWrite(*req_highest
, 0),
1687 CreateMockWrite(*req_lowest
, 1),
1690 scoped_ptr
<SpdyFrame
> resp_highest(
1691 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
1692 scoped_ptr
<SpdyFrame
> body_highest(
1693 spdy_util_
.ConstructSpdyBodyFrame(1, true));
1694 scoped_ptr
<SpdyFrame
> resp_lowest(
1695 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
1696 scoped_ptr
<SpdyFrame
> body_lowest(
1697 spdy_util_
.ConstructSpdyBodyFrame(3, true));
1698 MockRead reads
[] = {
1699 CreateMockRead(*resp_highest
, 2),
1700 CreateMockRead(*body_highest
, 3),
1701 CreateMockRead(*resp_lowest
, 4),
1702 CreateMockRead(*body_lowest
, 5),
1703 MockRead(ASYNC
, 0, 6) // EOF
1706 session_deps_
.host_resolver
->set_synchronous_mode(true);
1708 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1709 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1711 CreateNetworkSession();
1712 CreateInsecureSpdySession();
1714 base::WeakPtr
<SpdyStream
> spdy_stream_lowest
= CreateStreamSynchronously(
1715 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
1716 ASSERT_TRUE(spdy_stream_lowest
);
1717 EXPECT_EQ(0u, spdy_stream_lowest
->stream_id());
1718 test::StreamDelegateDoNothing
delegate_lowest(spdy_stream_lowest
);
1719 spdy_stream_lowest
->SetDelegate(&delegate_lowest
);
1721 base::WeakPtr
<SpdyStream
> spdy_stream_highest
=
1722 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
, session_
,
1723 test_url_
, HIGHEST
, BoundNetLog());
1724 ASSERT_TRUE(spdy_stream_highest
);
1725 EXPECT_EQ(0u, spdy_stream_highest
->stream_id());
1726 test::StreamDelegateDoNothing
delegate_highest(spdy_stream_highest
);
1727 spdy_stream_highest
->SetDelegate(&delegate_highest
);
1729 // Queue the lower priority one first.
1731 scoped_ptr
<SpdyHeaderBlock
> headers_lowest(
1732 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1733 spdy_stream_lowest
->SendRequestHeaders(
1734 headers_lowest
.Pass(), NO_MORE_DATA_TO_SEND
);
1735 EXPECT_TRUE(spdy_stream_lowest
->HasUrlFromHeaders());
1737 scoped_ptr
<SpdyHeaderBlock
> headers_highest(
1738 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1739 spdy_stream_highest
->SendRequestHeaders(
1740 headers_highest
.Pass(), NO_MORE_DATA_TO_SEND
);
1741 EXPECT_TRUE(spdy_stream_highest
->HasUrlFromHeaders());
1743 base::RunLoop().RunUntilIdle();
1745 EXPECT_FALSE(spdy_stream_lowest
);
1746 EXPECT_FALSE(spdy_stream_highest
);
1747 EXPECT_EQ(3u, delegate_lowest
.stream_id());
1748 EXPECT_EQ(1u, delegate_highest
.stream_id());
1751 TEST_P(SpdySessionTest
, CancelStream
) {
1752 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1753 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1754 scoped_ptr
<SpdyFrame
> req2(
1755 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
1756 MockWrite writes
[] = {
1757 CreateMockWrite(*req2
, 0),
1760 scoped_ptr
<SpdyFrame
> resp2(
1761 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
1762 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1763 MockRead reads
[] = {
1764 CreateMockRead(*resp2
, 1),
1765 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
1766 CreateMockRead(*body2
, 3),
1767 MockRead(ASYNC
, 0, 4) // EOF
1770 session_deps_
.host_resolver
->set_synchronous_mode(true);
1772 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1773 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1775 CreateNetworkSession();
1776 CreateInsecureSpdySession();
1778 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1779 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
, session_
,
1780 test_url_
, HIGHEST
, BoundNetLog());
1781 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1782 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1783 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
1784 spdy_stream1
->SetDelegate(&delegate1
);
1786 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
1787 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
1788 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
1789 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1790 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
1791 spdy_stream2
->SetDelegate(&delegate2
);
1793 scoped_ptr
<SpdyHeaderBlock
> headers(
1794 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1795 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1796 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1798 scoped_ptr
<SpdyHeaderBlock
> headers2(
1799 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1800 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1801 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1803 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1805 spdy_stream1
->Cancel();
1806 EXPECT_FALSE(spdy_stream1
);
1808 EXPECT_EQ(0u, delegate1
.stream_id());
1810 base::RunLoop().RunUntilIdle();
1812 EXPECT_EQ(0u, delegate1
.stream_id());
1813 EXPECT_EQ(1u, delegate2
.stream_id());
1815 spdy_stream2
->Cancel();
1816 EXPECT_FALSE(spdy_stream2
);
1819 // Create two streams that are set to re-close themselves on close,
1820 // and then close the session. Nothing should blow up. Also a
1821 // regression test for http://crbug.com/139518 .
1822 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedSelfClosingStreams
) {
1823 session_deps_
.host_resolver
->set_synchronous_mode(true);
1826 // No actual data will be sent.
1827 MockWrite writes
[] = {
1828 MockWrite(ASYNC
, 0, 1) // EOF
1831 MockRead reads
[] = {
1832 MockRead(ASYNC
, 0, 0) // EOF
1834 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1835 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1837 CreateNetworkSession();
1838 CreateInsecureSpdySession();
1840 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1841 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, HIGHEST
, BoundNetLog());
1842 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1843 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1845 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
1846 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
1847 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
1848 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1850 test::ClosingDelegate
delegate1(spdy_stream1
);
1851 spdy_stream1
->SetDelegate(&delegate1
);
1853 test::ClosingDelegate
delegate2(spdy_stream2
);
1854 spdy_stream2
->SetDelegate(&delegate2
);
1856 scoped_ptr
<SpdyHeaderBlock
> headers(
1857 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1858 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1859 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1861 scoped_ptr
<SpdyHeaderBlock
> headers2(
1862 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1863 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1864 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1866 // Ensure that the streams have not yet been activated and assigned an id.
1867 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1868 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1870 // Ensure we don't crash while closing the session.
1871 session_
->CloseSessionOnError(ERR_ABORTED
, std::string());
1873 EXPECT_FALSE(spdy_stream1
);
1874 EXPECT_FALSE(spdy_stream2
);
1876 EXPECT_TRUE(delegate1
.StreamIsClosed());
1877 EXPECT_TRUE(delegate2
.StreamIsClosed());
1879 base::RunLoop().RunUntilIdle();
1880 EXPECT_FALSE(session_
);
1883 // Create two streams that are set to close each other on close, and
1884 // then close the session. Nothing should blow up.
1885 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedMutuallyClosingStreams
) {
1886 session_deps_
.host_resolver
->set_synchronous_mode(true);
1888 SequencedSocketData
data(nullptr, 0, nullptr, 0);
1889 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1891 CreateNetworkSession();
1892 CreateInsecureSpdySession();
1894 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1895 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, HIGHEST
, BoundNetLog());
1896 ASSERT_TRUE(spdy_stream1
);
1897 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1899 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
1900 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
1901 ASSERT_TRUE(spdy_stream2
);
1902 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1904 // Make |spdy_stream1| close |spdy_stream2|.
1905 test::ClosingDelegate
delegate1(spdy_stream2
);
1906 spdy_stream1
->SetDelegate(&delegate1
);
1908 // Make |spdy_stream2| close |spdy_stream1|.
1909 test::ClosingDelegate
delegate2(spdy_stream1
);
1910 spdy_stream2
->SetDelegate(&delegate2
);
1912 scoped_ptr
<SpdyHeaderBlock
> headers(
1913 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1914 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1915 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1917 scoped_ptr
<SpdyHeaderBlock
> headers2(
1918 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1919 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1920 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1922 // Ensure that the streams have not yet been activated and assigned an id.
1923 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1924 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1926 // Ensure we don't crash while closing the session.
1927 session_
->CloseSessionOnError(ERR_ABORTED
, std::string());
1929 EXPECT_FALSE(spdy_stream1
);
1930 EXPECT_FALSE(spdy_stream2
);
1932 EXPECT_TRUE(delegate1
.StreamIsClosed());
1933 EXPECT_TRUE(delegate2
.StreamIsClosed());
1935 base::RunLoop().RunUntilIdle();
1936 EXPECT_FALSE(session_
);
1939 // Create two streams that are set to re-close themselves on close,
1940 // activate them, and then close the session. Nothing should blow up.
1941 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedSelfClosingStreams
) {
1942 session_deps_
.host_resolver
->set_synchronous_mode(true);
1944 scoped_ptr
<SpdyFrame
> req1(
1945 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
1946 scoped_ptr
<SpdyFrame
> req2(
1947 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
1948 MockWrite writes
[] = {
1949 CreateMockWrite(*req1
, 0),
1950 CreateMockWrite(*req2
, 1),
1953 MockRead reads
[] = {
1954 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
1957 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
1958 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1960 CreateNetworkSession();
1961 CreateInsecureSpdySession();
1963 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
1964 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1965 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
1966 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1968 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
1969 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
1970 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
1971 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1973 test::ClosingDelegate
delegate1(spdy_stream1
);
1974 spdy_stream1
->SetDelegate(&delegate1
);
1976 test::ClosingDelegate
delegate2(spdy_stream2
);
1977 spdy_stream2
->SetDelegate(&delegate2
);
1979 scoped_ptr
<SpdyHeaderBlock
> headers(
1980 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1981 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1982 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1984 scoped_ptr
<SpdyHeaderBlock
> headers2(
1985 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
1986 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1987 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1989 // Ensure that the streams have not yet been activated and assigned an id.
1990 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1991 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1993 base::RunLoop().RunUntilIdle();
1995 EXPECT_EQ(1u, spdy_stream1
->stream_id());
1996 EXPECT_EQ(3u, spdy_stream2
->stream_id());
1998 // Ensure we don't crash while closing the session.
1999 session_
->CloseSessionOnError(ERR_ABORTED
, std::string());
2001 EXPECT_FALSE(spdy_stream1
);
2002 EXPECT_FALSE(spdy_stream2
);
2004 EXPECT_TRUE(delegate1
.StreamIsClosed());
2005 EXPECT_TRUE(delegate2
.StreamIsClosed());
2007 EXPECT_TRUE(session_
);
2008 data
.CompleteRead();
2009 base::RunLoop().RunUntilIdle();
2010 EXPECT_FALSE(session_
);
2013 // Create two streams that are set to close each other on close,
2014 // activate them, and then close the session. Nothing should blow up.
2015 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedMutuallyClosingStreams
) {
2016 session_deps_
.host_resolver
->set_synchronous_mode(true);
2018 scoped_ptr
<SpdyFrame
> req1(
2019 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2020 scoped_ptr
<SpdyFrame
> req2(
2021 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM
, true));
2022 MockWrite writes
[] = {
2023 CreateMockWrite(*req1
, 0),
2024 CreateMockWrite(*req2
, 1),
2027 MockRead reads
[] = {
2028 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
2031 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2032 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2034 CreateNetworkSession();
2035 CreateInsecureSpdySession();
2037 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2038 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2039 ASSERT_TRUE(spdy_stream1
);
2040 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2042 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
2043 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2044 ASSERT_TRUE(spdy_stream2
);
2045 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2047 // Make |spdy_stream1| close |spdy_stream2|.
2048 test::ClosingDelegate
delegate1(spdy_stream2
);
2049 spdy_stream1
->SetDelegate(&delegate1
);
2051 // Make |spdy_stream2| close |spdy_stream1|.
2052 test::ClosingDelegate
delegate2(spdy_stream1
);
2053 spdy_stream2
->SetDelegate(&delegate2
);
2055 scoped_ptr
<SpdyHeaderBlock
> headers(
2056 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2057 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2058 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2060 scoped_ptr
<SpdyHeaderBlock
> headers2(
2061 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2062 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2063 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2065 // Ensure that the streams have not yet been activated and assigned an id.
2066 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2067 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2069 base::RunLoop().RunUntilIdle();
2071 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2072 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2074 // Ensure we don't crash while closing the session.
2075 session_
->CloseSessionOnError(ERR_ABORTED
, std::string());
2077 EXPECT_FALSE(spdy_stream1
);
2078 EXPECT_FALSE(spdy_stream2
);
2080 EXPECT_TRUE(delegate1
.StreamIsClosed());
2081 EXPECT_TRUE(delegate2
.StreamIsClosed());
2083 EXPECT_TRUE(session_
);
2084 data
.CompleteRead();
2085 base::RunLoop().RunUntilIdle();
2086 EXPECT_FALSE(session_
);
2089 // Delegate that closes a given session when the stream is closed.
2090 class SessionClosingDelegate
: public test::StreamDelegateDoNothing
{
2092 SessionClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
2093 const base::WeakPtr
<SpdySession
>& session_to_close
)
2094 : StreamDelegateDoNothing(stream
),
2095 session_to_close_(session_to_close
) {}
2097 ~SessionClosingDelegate() override
{}
2099 void OnClose(int status
) override
{
2100 session_to_close_
->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR
, "Error");
2104 base::WeakPtr
<SpdySession
> session_to_close_
;
2107 // Close an activated stream that closes its session. Nothing should
2108 // blow up. This is a regression test for https://crbug.com/263691.
2109 TEST_P(SpdySessionTest
, CloseActivatedStreamThatClosesSession
) {
2110 session_deps_
.host_resolver
->set_synchronous_mode(true);
2112 scoped_ptr
<SpdyFrame
> req(
2113 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2114 scoped_ptr
<SpdyFrame
> rst(
2115 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2116 scoped_ptr
<SpdyFrame
> goaway(
2117 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Error"));
2118 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2119 // despite being queued second.
2120 MockWrite writes
[] = {
2121 CreateMockWrite(*req
, 0),
2122 CreateMockWrite(*goaway
, 1),
2123 CreateMockWrite(*rst
, 3),
2126 MockRead reads
[] = {
2127 MockRead(ASYNC
, 0, 2) // EOF
2129 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2130 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2132 CreateNetworkSession();
2133 CreateInsecureSpdySession();
2135 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
2136 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2137 ASSERT_TRUE(spdy_stream
.get() != nullptr);
2138 EXPECT_EQ(0u, spdy_stream
->stream_id());
2140 SessionClosingDelegate
delegate(spdy_stream
, session_
);
2141 spdy_stream
->SetDelegate(&delegate
);
2143 scoped_ptr
<SpdyHeaderBlock
> headers(
2144 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2145 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2146 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
2148 EXPECT_EQ(0u, spdy_stream
->stream_id());
2150 base::RunLoop().RunUntilIdle();
2152 EXPECT_EQ(1u, spdy_stream
->stream_id());
2154 // Ensure we don't crash while closing the stream (which closes the
2156 spdy_stream
->Cancel();
2158 EXPECT_FALSE(spdy_stream
);
2159 EXPECT_TRUE(delegate
.StreamIsClosed());
2161 // Write the RST_STREAM & GOAWAY.
2162 base::RunLoop().RunUntilIdle();
2163 EXPECT_TRUE(data
.AllWriteDataConsumed());
2164 EXPECT_TRUE(data
.AllReadDataConsumed());
2167 TEST_P(SpdySessionTest
, VerifyDomainAuthentication
) {
2168 session_deps_
.host_resolver
->set_synchronous_mode(true);
2170 SequencedSocketData
data(nullptr, 0, nullptr, 0);
2171 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2173 // Load a cert that is valid for:
2177 base::FilePath certs_dir
= GetTestCertsDirectory();
2178 scoped_refptr
<X509Certificate
> test_cert(
2179 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2180 ASSERT_NE(static_cast<X509Certificate
*>(nullptr), test_cert
.get());
2182 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2183 ssl
.cert
= test_cert
;
2184 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2186 CreateNetworkSession();
2188 session_
= CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2190 EXPECT_TRUE(session_
->VerifyDomainAuthentication("www.example.org"));
2191 EXPECT_TRUE(session_
->VerifyDomainAuthentication("mail.example.org"));
2192 EXPECT_TRUE(session_
->VerifyDomainAuthentication("mail.example.com"));
2193 EXPECT_FALSE(session_
->VerifyDomainAuthentication("mail.google.com"));
2196 TEST_P(SpdySessionTest
, ConnectionPooledWithTlsChannelId
) {
2197 session_deps_
.host_resolver
->set_synchronous_mode(true);
2199 SequencedSocketData
data(nullptr, 0, nullptr, 0);
2200 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2202 // Load a cert that is valid for:
2206 base::FilePath certs_dir
= GetTestCertsDirectory();
2207 scoped_refptr
<X509Certificate
> test_cert(
2208 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2209 ASSERT_NE(static_cast<X509Certificate
*>(nullptr), test_cert
.get());
2211 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2212 ssl
.channel_id_sent
= true;
2213 ssl
.cert
= test_cert
;
2214 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2216 CreateNetworkSession();
2218 session_
= CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2220 EXPECT_TRUE(session_
->VerifyDomainAuthentication("www.example.org"));
2221 EXPECT_TRUE(session_
->VerifyDomainAuthentication("mail.example.org"));
2222 EXPECT_FALSE(session_
->VerifyDomainAuthentication("mail.example.com"));
2223 EXPECT_FALSE(session_
->VerifyDomainAuthentication("mail.google.com"));
2226 TEST_P(SpdySessionTest
, CloseTwoStalledCreateStream
) {
2227 // TODO(rtenneti): Define a helper class/methods and move the common code in
2229 SettingsMap new_settings
;
2230 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
2231 const uint32 max_concurrent_streams
= 1;
2232 new_settings
[kSpdySettingsIds1
] =
2233 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
2235 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
2236 scoped_ptr
<SpdyFrame
> req1(
2237 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
2238 scoped_ptr
<SpdyFrame
> req2(
2239 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST
, true));
2240 scoped_ptr
<SpdyFrame
> req3(
2241 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 5, LOWEST
, true));
2242 MockWrite writes
[] = {
2243 CreateMockWrite(*settings_ack
, 1),
2244 CreateMockWrite(*req1
, 2),
2245 CreateMockWrite(*req2
, 5),
2246 CreateMockWrite(*req3
, 8),
2249 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2251 scoped_ptr
<SpdyFrame
> settings_frame(
2252 spdy_util_
.ConstructSpdySettings(new_settings
));
2254 scoped_ptr
<SpdyFrame
> resp1(
2255 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2256 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2258 scoped_ptr
<SpdyFrame
> resp2(
2259 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
2260 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
2262 scoped_ptr
<SpdyFrame
> resp3(
2263 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 5));
2264 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
2266 MockRead reads
[] = {
2267 CreateMockRead(*settings_frame
, 0),
2268 CreateMockRead(*resp1
, 3),
2269 CreateMockRead(*body1
, 4),
2270 CreateMockRead(*resp2
, 6),
2271 CreateMockRead(*body2
, 7),
2272 CreateMockRead(*resp3
, 9),
2273 CreateMockRead(*body3
, 10),
2274 MockRead(ASYNC
, ERR_IO_PENDING
, 11),
2275 MockRead(ASYNC
, 0, 12) // EOF
2278 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2279 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2281 CreateNetworkSession();
2282 CreateInsecureSpdySession();
2284 // Read the settings frame.
2285 base::RunLoop().RunUntilIdle();
2287 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2288 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
2289 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2290 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2291 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2292 spdy_stream1
->SetDelegate(&delegate1
);
2294 TestCompletionCallback callback2
;
2295 SpdyStreamRequest request2
;
2298 request2
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
,
2299 LOWEST
, BoundNetLog(), callback2
.callback()));
2301 TestCompletionCallback callback3
;
2302 SpdyStreamRequest request3
;
2305 request3
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
,
2306 LOWEST
, BoundNetLog(), callback3
.callback()));
2308 EXPECT_EQ(0u, session_
->num_active_streams());
2309 EXPECT_EQ(1u, session_
->num_created_streams());
2310 EXPECT_EQ(2u, session_
->pending_create_stream_queue_size(LOWEST
));
2312 scoped_ptr
<SpdyHeaderBlock
> headers(
2313 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2314 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2315 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2317 // Run until 1st stream is activated and then closed.
2318 EXPECT_EQ(0u, delegate1
.stream_id());
2319 base::RunLoop().RunUntilIdle();
2320 EXPECT_FALSE(spdy_stream1
);
2321 EXPECT_EQ(1u, delegate1
.stream_id());
2323 EXPECT_EQ(0u, session_
->num_active_streams());
2324 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(LOWEST
));
2326 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2327 // create the 2nd stream.
2328 base::RunLoop().RunUntilIdle();
2330 EXPECT_EQ(0u, session_
->num_active_streams());
2331 EXPECT_EQ(1u, session_
->num_created_streams());
2332 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(LOWEST
));
2334 base::WeakPtr
<SpdyStream
> stream2
= request2
.ReleaseStream();
2335 test::StreamDelegateDoNothing
delegate2(stream2
);
2336 stream2
->SetDelegate(&delegate2
);
2337 scoped_ptr
<SpdyHeaderBlock
> headers2(
2338 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2339 stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2340 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
2342 // Run until 2nd stream is activated and then closed.
2343 EXPECT_EQ(0u, delegate2
.stream_id());
2344 base::RunLoop().RunUntilIdle();
2345 EXPECT_FALSE(stream2
);
2346 EXPECT_EQ(3u, delegate2
.stream_id());
2348 EXPECT_EQ(0u, session_
->num_active_streams());
2349 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2351 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2352 // create the 3rd stream.
2353 base::RunLoop().RunUntilIdle();
2355 EXPECT_EQ(0u, session_
->num_active_streams());
2356 EXPECT_EQ(1u, session_
->num_created_streams());
2357 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2359 base::WeakPtr
<SpdyStream
> stream3
= request3
.ReleaseStream();
2360 test::StreamDelegateDoNothing
delegate3(stream3
);
2361 stream3
->SetDelegate(&delegate3
);
2362 scoped_ptr
<SpdyHeaderBlock
> headers3(
2363 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2364 stream3
->SendRequestHeaders(headers3
.Pass(), NO_MORE_DATA_TO_SEND
);
2365 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
2367 // Run until 2nd stream is activated and then closed.
2368 EXPECT_EQ(0u, delegate3
.stream_id());
2369 base::RunLoop().RunUntilIdle();
2370 EXPECT_FALSE(stream3
);
2371 EXPECT_EQ(5u, delegate3
.stream_id());
2373 EXPECT_EQ(0u, session_
->num_active_streams());
2374 EXPECT_EQ(0u, session_
->num_created_streams());
2375 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2377 data
.CompleteRead();
2378 base::RunLoop().RunUntilIdle();
2381 TEST_P(SpdySessionTest
, CancelTwoStalledCreateStream
) {
2382 session_deps_
.host_resolver
->set_synchronous_mode(true);
2384 MockRead reads
[] = {
2385 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2388 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2389 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2391 CreateNetworkSession();
2392 CreateInsecureSpdySession();
2394 // Leave room for only one more stream to be created.
2395 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
2396 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
2397 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2398 ASSERT_TRUE(spdy_stream
!= nullptr);
2401 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2402 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
2403 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2404 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2406 TestCompletionCallback callback2
;
2407 SpdyStreamRequest request2
;
2408 ASSERT_EQ(ERR_IO_PENDING
, request2
.StartRequest(
2409 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
2410 LOWEST
, BoundNetLog(), callback2
.callback()));
2412 TestCompletionCallback callback3
;
2413 SpdyStreamRequest request3
;
2414 ASSERT_EQ(ERR_IO_PENDING
, request3
.StartRequest(
2415 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
,
2416 LOWEST
, BoundNetLog(), callback3
.callback()));
2418 EXPECT_EQ(0u, session_
->num_active_streams());
2419 EXPECT_EQ(kInitialMaxConcurrentStreams
, session_
->num_created_streams());
2420 EXPECT_EQ(2u, session_
->pending_create_stream_queue_size(LOWEST
));
2422 // Cancel the first stream; this will allow the second stream to be created.
2423 EXPECT_TRUE(spdy_stream1
);
2424 spdy_stream1
->Cancel();
2425 EXPECT_FALSE(spdy_stream1
);
2427 EXPECT_EQ(OK
, callback2
.WaitForResult());
2428 EXPECT_EQ(0u, session_
->num_active_streams());
2429 EXPECT_EQ(kInitialMaxConcurrentStreams
, session_
->num_created_streams());
2430 EXPECT_EQ(1u, session_
->pending_create_stream_queue_size(LOWEST
));
2432 // Cancel the second stream; this will allow the third stream to be created.
2433 base::WeakPtr
<SpdyStream
> spdy_stream2
= request2
.ReleaseStream();
2434 spdy_stream2
->Cancel();
2435 EXPECT_FALSE(spdy_stream2
);
2437 EXPECT_EQ(OK
, callback3
.WaitForResult());
2438 EXPECT_EQ(0u, session_
->num_active_streams());
2439 EXPECT_EQ(kInitialMaxConcurrentStreams
, session_
->num_created_streams());
2440 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2442 // Cancel the third stream.
2443 base::WeakPtr
<SpdyStream
> spdy_stream3
= request3
.ReleaseStream();
2444 spdy_stream3
->Cancel();
2445 EXPECT_FALSE(spdy_stream3
);
2446 EXPECT_EQ(0u, session_
->num_active_streams());
2447 EXPECT_EQ(kInitialMaxConcurrentStreams
- 1, session_
->num_created_streams());
2448 EXPECT_EQ(0u, session_
->pending_create_stream_queue_size(LOWEST
));
2451 // Test that SpdySession::DoReadLoop reads data from the socket
2452 // without yielding. This test makes 32k - 1 bytes of data available
2453 // on the socket for reading. It then verifies that it has read all
2454 // the available data without yielding.
2455 TEST_P(SpdySessionTest
, ReadDataWithoutYielding
) {
2456 session_deps_
.host_resolver
->set_synchronous_mode(true);
2458 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2460 scoped_ptr
<SpdyFrame
> req1(
2461 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2462 MockWrite writes
[] = {
2463 CreateMockWrite(*req1
, 0),
2466 // Build buffer of size kYieldAfterBytesRead / 4
2467 // (-spdy_data_frame_size).
2468 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead
);
2469 const int kPayloadSize
=
2470 kYieldAfterBytesRead
/ 4 - framer
.GetControlFrameHeaderSize();
2471 TestDataStream test_stream
;
2472 scoped_refptr
<IOBuffer
> payload(new IOBuffer(kPayloadSize
));
2473 char* payload_data
= payload
->data();
2474 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2476 scoped_ptr
<SpdyFrame
> partial_data_frame(
2477 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2478 scoped_ptr
<SpdyFrame
> finish_data_frame(
2479 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
- 1, DATA_FLAG_FIN
));
2481 scoped_ptr
<SpdyFrame
> resp1(
2482 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2484 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2486 MockRead reads
[] = {
2487 CreateMockRead(*resp1
, 1),
2488 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2489 CreateMockRead(*partial_data_frame
, 3),
2490 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2491 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2492 CreateMockRead(*finish_data_frame
, 6, SYNCHRONOUS
),
2493 MockRead(ASYNC
, 0, 7) // EOF
2496 // Create SpdySession and SpdyStream and send the request.
2497 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2498 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2500 CreateNetworkSession();
2501 CreateInsecureSpdySession();
2503 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2504 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2505 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2506 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2507 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2508 spdy_stream1
->SetDelegate(&delegate1
);
2510 scoped_ptr
<SpdyHeaderBlock
> headers1(
2511 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2512 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2513 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2515 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2517 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2519 // Run until 1st read.
2520 EXPECT_EQ(0u, delegate1
.stream_id());
2521 base::RunLoop().RunUntilIdle();
2522 EXPECT_EQ(1u, delegate1
.stream_id());
2523 EXPECT_EQ(0u, observer
.executed_count());
2525 // Read all the data and verify SpdySession::DoReadLoop has not
2527 data
.CompleteRead();
2528 base::RunLoop().RunUntilIdle();
2529 EXPECT_FALSE(spdy_stream1
);
2531 // Verify task observer's executed_count is zero, which indicates DoRead read
2532 // all the available data.
2533 EXPECT_EQ(0u, observer
.executed_count());
2534 EXPECT_TRUE(data
.AllWriteDataConsumed());
2535 EXPECT_TRUE(data
.AllReadDataConsumed());
2538 // Test that SpdySession::DoReadLoop yields if more than
2539 // |kYieldAfterDurationMilliseconds| has passed. This test uses a mock time
2540 // function that makes the response frame look very slow to read.
2541 TEST_P(SpdySessionTest
, TestYieldingSlowReads
) {
2542 session_deps_
.host_resolver
->set_synchronous_mode(true);
2543 session_deps_
.time_func
= SlowReads
;
2545 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2547 scoped_ptr
<SpdyFrame
> req1(
2548 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2549 MockWrite writes
[] = {
2550 CreateMockWrite(*req1
, 0),
2553 scoped_ptr
<SpdyFrame
> resp1(
2554 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2556 MockRead reads
[] = {
2557 CreateMockRead(*resp1
, 1), MockRead(ASYNC
, 0, 2) // EOF
2560 // Create SpdySession and SpdyStream and send the request.
2561 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2562 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2564 CreateNetworkSession();
2565 CreateInsecureSpdySession();
2567 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2568 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2569 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2570 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2571 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2572 spdy_stream1
->SetDelegate(&delegate1
);
2574 scoped_ptr
<SpdyHeaderBlock
> headers1(
2575 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2576 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2577 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2579 // Set up the TaskObserver to verify that SpdySession::DoReadLoop posts a
2581 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2583 EXPECT_EQ(0u, delegate1
.stream_id());
2584 EXPECT_EQ(0u, observer
.executed_count());
2586 // Read all the data and verify that SpdySession::DoReadLoop has posted a
2588 base::RunLoop().RunUntilIdle();
2589 EXPECT_EQ(1u, delegate1
.stream_id());
2590 EXPECT_FALSE(spdy_stream1
);
2592 // Verify task that the observer's executed_count is 1, which indicates DoRead
2593 // has posted only one task and thus yielded though there is data available
2595 EXPECT_EQ(1u, observer
.executed_count());
2596 EXPECT_TRUE(data
.AllWriteDataConsumed());
2597 EXPECT_TRUE(data
.AllReadDataConsumed());
2600 // Test that SpdySession::DoReadLoop yields while reading the
2601 // data. This test makes 32k + 1 bytes of data available on the socket
2602 // for reading. It then verifies that DoRead has yielded even though
2603 // there is data available for it to read (i.e, socket()->Read didn't
2604 // return ERR_IO_PENDING during socket reads).
2605 TEST_P(SpdySessionTest
, TestYieldingDuringReadData
) {
2606 session_deps_
.host_resolver
->set_synchronous_mode(true);
2608 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2610 scoped_ptr
<SpdyFrame
> req1(
2611 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2612 MockWrite writes
[] = {
2613 CreateMockWrite(*req1
, 0),
2616 // Build buffer of size kYieldAfterBytesRead / 4
2617 // (-spdy_data_frame_size).
2618 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead
);
2619 const int kPayloadSize
=
2620 kYieldAfterBytesRead
/ 4 - framer
.GetControlFrameHeaderSize();
2621 TestDataStream test_stream
;
2622 scoped_refptr
<IOBuffer
> payload(new IOBuffer(kPayloadSize
));
2623 char* payload_data
= payload
->data();
2624 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2626 scoped_ptr
<SpdyFrame
> partial_data_frame(
2627 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2628 scoped_ptr
<SpdyFrame
> finish_data_frame(
2629 framer
.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN
));
2631 scoped_ptr
<SpdyFrame
> resp1(
2632 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2634 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2635 MockRead reads
[] = {
2636 CreateMockRead(*resp1
, 1),
2637 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2638 CreateMockRead(*partial_data_frame
, 3),
2639 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2640 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2641 CreateMockRead(*partial_data_frame
, 6, SYNCHRONOUS
),
2642 CreateMockRead(*finish_data_frame
, 7, SYNCHRONOUS
),
2643 MockRead(ASYNC
, 0, 8) // EOF
2646 // Create SpdySession and SpdyStream and send the request.
2647 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2648 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2650 CreateNetworkSession();
2651 CreateInsecureSpdySession();
2653 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2654 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2655 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2656 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2657 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2658 spdy_stream1
->SetDelegate(&delegate1
);
2660 scoped_ptr
<SpdyHeaderBlock
> headers1(
2661 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2662 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2663 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2665 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a task.
2666 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2668 // Run until 1st read.
2669 EXPECT_EQ(0u, delegate1
.stream_id());
2670 base::RunLoop().RunUntilIdle();
2671 EXPECT_EQ(1u, delegate1
.stream_id());
2672 EXPECT_EQ(0u, observer
.executed_count());
2674 // Read all the data and verify SpdySession::DoReadLoop has posted a task.
2675 data
.CompleteRead();
2676 base::RunLoop().RunUntilIdle();
2677 EXPECT_FALSE(spdy_stream1
);
2679 // Verify task observer's executed_count is 1, which indicates DoRead has
2680 // posted only one task and thus yielded though there is data available for it
2682 EXPECT_EQ(1u, observer
.executed_count());
2683 EXPECT_TRUE(data
.AllWriteDataConsumed());
2684 EXPECT_TRUE(data
.AllReadDataConsumed());
2687 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2688 // + async, by doing the following MockReads.
2690 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2691 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2693 // The above reads 26K synchronously. Since that is less that 32K, we
2694 // will attempt to read again. However, that DoRead() will return
2695 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2696 // yield. When we come back, DoRead() will read the results from the
2697 // async read, and rest of the data synchronously.
2698 TEST_P(SpdySessionTest
, TestYieldingDuringAsyncReadData
) {
2699 session_deps_
.host_resolver
->set_synchronous_mode(true);
2701 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2703 scoped_ptr
<SpdyFrame
> req1(
2704 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2705 MockWrite writes
[] = {
2706 CreateMockWrite(*req1
, 0),
2709 // Build buffer of size kYieldAfterBytesRead / 4
2710 // (-spdy_data_frame_size).
2711 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead
);
2712 TestDataStream test_stream
;
2713 const int kEightKPayloadSize
=
2714 kYieldAfterBytesRead
/ 4 - framer
.GetControlFrameHeaderSize();
2715 scoped_refptr
<IOBuffer
> eightk_payload(new IOBuffer(kEightKPayloadSize
));
2716 char* eightk_payload_data
= eightk_payload
->data();
2717 test_stream
.GetBytes(eightk_payload_data
, kEightKPayloadSize
);
2719 // Build buffer of 2k size.
2720 TestDataStream test_stream2
;
2721 const int kTwoKPayloadSize
= kEightKPayloadSize
- 6 * 1024;
2722 scoped_refptr
<IOBuffer
> twok_payload(new IOBuffer(kTwoKPayloadSize
));
2723 char* twok_payload_data
= twok_payload
->data();
2724 test_stream2
.GetBytes(twok_payload_data
, kTwoKPayloadSize
);
2726 scoped_ptr
<SpdyFrame
> eightk_data_frame(framer
.CreateDataFrame(
2727 1, eightk_payload_data
, kEightKPayloadSize
, DATA_FLAG_NONE
));
2728 scoped_ptr
<SpdyFrame
> twok_data_frame(framer
.CreateDataFrame(
2729 1, twok_payload_data
, kTwoKPayloadSize
, DATA_FLAG_NONE
));
2730 scoped_ptr
<SpdyFrame
> finish_data_frame(framer
.CreateDataFrame(
2731 1, "h", 1, DATA_FLAG_FIN
));
2733 scoped_ptr
<SpdyFrame
> resp1(
2734 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2736 MockRead reads
[] = {
2737 CreateMockRead(*resp1
, 1),
2738 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2739 CreateMockRead(*eightk_data_frame
, 3),
2740 CreateMockRead(*eightk_data_frame
, 4, SYNCHRONOUS
),
2741 CreateMockRead(*eightk_data_frame
, 5, SYNCHRONOUS
),
2742 CreateMockRead(*twok_data_frame
, 6, SYNCHRONOUS
),
2743 CreateMockRead(*eightk_data_frame
, 7, ASYNC
),
2744 CreateMockRead(*eightk_data_frame
, 8, SYNCHRONOUS
),
2745 CreateMockRead(*eightk_data_frame
, 9, SYNCHRONOUS
),
2746 CreateMockRead(*eightk_data_frame
, 10, SYNCHRONOUS
),
2747 CreateMockRead(*twok_data_frame
, 11, SYNCHRONOUS
),
2748 CreateMockRead(*finish_data_frame
, 12, SYNCHRONOUS
),
2749 MockRead(ASYNC
, 0, 13) // EOF
2752 // Create SpdySession and SpdyStream and send the request.
2753 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2754 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2756 CreateNetworkSession();
2757 CreateInsecureSpdySession();
2759 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2760 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2761 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2762 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2763 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2764 spdy_stream1
->SetDelegate(&delegate1
);
2766 scoped_ptr
<SpdyHeaderBlock
> headers1(
2767 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2768 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2769 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2771 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2772 // posting of tasks.
2773 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2775 // Run until 1st read.
2776 EXPECT_EQ(0u, delegate1
.stream_id());
2777 base::RunLoop().RunUntilIdle();
2778 EXPECT_EQ(1u, delegate1
.stream_id());
2779 EXPECT_EQ(0u, observer
.executed_count());
2781 // Read all the data and verify SpdySession::DoReadLoop has posted a
2783 data
.CompleteRead();
2784 base::RunLoop().RunUntilIdle();
2785 EXPECT_FALSE(spdy_stream1
);
2787 // Verify task observer's executed_count is 1, which indicates DoRead has
2788 // posted only one task and thus yielded though there is data available for
2790 EXPECT_EQ(1u, observer
.executed_count());
2791 EXPECT_TRUE(data
.AllWriteDataConsumed());
2792 EXPECT_TRUE(data
.AllReadDataConsumed());
2795 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2796 // nothing blows up.
2797 TEST_P(SpdySessionTest
, GoAwayWhileInDoReadLoop
) {
2798 session_deps_
.host_resolver
->set_synchronous_mode(true);
2800 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2802 scoped_ptr
<SpdyFrame
> req1(
2803 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
2804 MockWrite writes
[] = {
2805 CreateMockWrite(*req1
, 0),
2808 scoped_ptr
<SpdyFrame
> resp1(
2809 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
2810 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2811 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
2813 MockRead reads
[] = {
2814 CreateMockRead(*resp1
, 1),
2815 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
2816 CreateMockRead(*body1
, 3),
2817 CreateMockRead(*goaway
, 4),
2820 // Create SpdySession and SpdyStream and send the request.
2821 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
2822 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2824 CreateNetworkSession();
2825 CreateInsecureSpdySession();
2827 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
2828 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
2829 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2830 spdy_stream1
->SetDelegate(&delegate1
);
2831 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
2832 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2834 scoped_ptr
<SpdyHeaderBlock
> headers1(
2835 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
2836 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2837 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2839 // Run until 1st read.
2840 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2841 base::RunLoop().RunUntilIdle();
2842 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2844 // Run until GoAway.
2845 data
.CompleteRead();
2846 base::RunLoop().RunUntilIdle();
2847 EXPECT_FALSE(spdy_stream1
);
2848 EXPECT_TRUE(data
.AllWriteDataConsumed());
2849 EXPECT_TRUE(data
.AllReadDataConsumed());
2850 EXPECT_FALSE(session_
);
2853 // Within this framework, a SpdySession should be initialized with
2854 // flow control disabled for protocol version 2, with flow control
2855 // enabled only for streams for protocol version 3, and with flow
2856 // control enabled for streams and sessions for higher versions.
2857 TEST_P(SpdySessionTest
, ProtocolNegotiation
) {
2858 session_deps_
.host_resolver
->set_synchronous_mode(true);
2860 MockRead reads
[] = {
2861 MockRead(SYNCHRONOUS
, 0, 0) // EOF
2863 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2864 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2866 CreateNetworkSession();
2867 session_
= CreateFakeSpdySession(spdy_session_pool_
, key_
);
2869 EXPECT_EQ(spdy_util_
.spdy_version(),
2870 session_
->buffered_spdy_framer_
->protocol_version());
2871 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
2872 session_
->flow_control_state());
2873 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
2874 session_
->session_send_window_size_
);
2875 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
2876 session_
->session_recv_window_size_
);
2877 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
2880 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2881 // pointers to the idle session are currently held.
2882 TEST_P(SpdySessionTest
, CloseOneIdleConnection
) {
2883 ClientSocketPoolManager::set_max_sockets_per_group(
2884 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2885 ClientSocketPoolManager::set_max_sockets_per_pool(
2886 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2888 MockRead reads
[] = {
2889 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2891 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2892 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2893 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2895 CreateNetworkSession();
2897 TransportClientSocketPool
* pool
=
2898 http_session_
->GetTransportSocketPool(
2899 HttpNetworkSession::NORMAL_SOCKET_POOL
);
2901 // Create an idle SPDY session.
2902 CreateInsecureSpdySession();
2903 EXPECT_FALSE(pool
->IsStalled());
2905 // Trying to create a new connection should cause the pool to be stalled, and
2906 // post a task asynchronously to try and close the session.
2907 TestCompletionCallback callback2
;
2908 HostPortPair
host_port2("2.com", 80);
2909 scoped_refptr
<TransportSocketParams
> params2(
2910 new TransportSocketParams(
2911 host_port2
, false, false, OnHostResolutionCallback(),
2912 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
2913 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
2914 EXPECT_EQ(ERR_IO_PENDING
,
2915 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
2916 callback2
.callback(), pool
, BoundNetLog()));
2917 EXPECT_TRUE(pool
->IsStalled());
2919 // The socket pool should close the connection asynchronously and establish a
2921 EXPECT_EQ(OK
, callback2
.WaitForResult());
2922 EXPECT_FALSE(pool
->IsStalled());
2923 EXPECT_FALSE(session_
);
2926 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2927 // pointers to the idle session are currently held, in the case the SPDY session
2929 TEST_P(SpdySessionTest
, CloseOneIdleConnectionWithAlias
) {
2930 ClientSocketPoolManager::set_max_sockets_per_group(
2931 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2932 ClientSocketPoolManager::set_max_sockets_per_pool(
2933 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2935 MockRead reads
[] = {
2936 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2938 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
2939 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2940 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2942 session_deps_
.host_resolver
->set_synchronous_mode(true);
2943 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
2944 "1.com", "192.168.0.2", std::string());
2945 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
2946 "2.com", "192.168.0.2", std::string());
2947 // Not strictly needed.
2948 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
2949 "3.com", "192.168.0.3", std::string());
2951 CreateNetworkSession();
2953 TransportClientSocketPool
* pool
=
2954 http_session_
->GetTransportSocketPool(
2955 HttpNetworkSession::NORMAL_SOCKET_POOL
);
2957 // Create an idle SPDY session.
2958 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2959 PRIVACY_MODE_DISABLED
);
2960 base::WeakPtr
<SpdySession
> session1
=
2961 ::net::CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
2962 EXPECT_FALSE(pool
->IsStalled());
2964 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
2965 SpdySessionKey
key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
2966 PRIVACY_MODE_DISABLED
);
2967 HostResolver::RequestInfo
info(key2
.host_port_pair());
2968 AddressList addresses
;
2969 // Pre-populate the DNS cache, since a synchronous resolution is required in
2970 // order to create the alias.
2971 session_deps_
.host_resolver
->Resolve(info
, DEFAULT_PRIORITY
, &addresses
,
2972 CompletionCallback(), nullptr,
2974 // Get a session for |key2|, which should return the session created earlier.
2975 base::WeakPtr
<SpdySession
> session2
=
2976 spdy_session_pool_
->FindAvailableSession(key2
, BoundNetLog());
2977 ASSERT_EQ(session1
.get(), session2
.get());
2978 EXPECT_FALSE(pool
->IsStalled());
2980 // Trying to create a new connection should cause the pool to be stalled, and
2981 // post a task asynchronously to try and close the session.
2982 TestCompletionCallback callback3
;
2983 HostPortPair
host_port3("3.com", 80);
2984 scoped_refptr
<TransportSocketParams
> params3(
2985 new TransportSocketParams(
2986 host_port3
, false, false, OnHostResolutionCallback(),
2987 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
2988 scoped_ptr
<ClientSocketHandle
> connection3(new ClientSocketHandle
);
2989 EXPECT_EQ(ERR_IO_PENDING
,
2990 connection3
->Init(host_port3
.ToString(), params3
, DEFAULT_PRIORITY
,
2991 callback3
.callback(), pool
, BoundNetLog()));
2992 EXPECT_TRUE(pool
->IsStalled());
2994 // The socket pool should close the connection asynchronously and establish a
2996 EXPECT_EQ(OK
, callback3
.WaitForResult());
2997 EXPECT_FALSE(pool
->IsStalled());
2998 EXPECT_FALSE(session1
);
2999 EXPECT_FALSE(session2
);
3002 // Tests that when a SPDY session becomes idle, it closes itself if there is
3003 // a lower layer pool stalled on the per-pool socket limit.
3004 TEST_P(SpdySessionTest
, CloseSessionOnIdleWhenPoolStalled
) {
3005 ClientSocketPoolManager::set_max_sockets_per_group(
3006 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3007 ClientSocketPoolManager::set_max_sockets_per_pool(
3008 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3010 MockRead reads
[] = {
3011 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3013 scoped_ptr
<SpdyFrame
> req1(
3014 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3015 scoped_ptr
<SpdyFrame
> cancel1(
3016 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3017 MockWrite writes
[] = {
3018 CreateMockWrite(*req1
, 1),
3019 CreateMockWrite(*cancel1
, 1),
3021 StaticSocketDataProvider
data(reads
, arraysize(reads
),
3022 writes
, arraysize(writes
));
3023 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3025 MockRead http_reads
[] = {
3026 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3028 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
), nullptr,
3030 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
3033 CreateNetworkSession();
3035 TransportClientSocketPool
* pool
=
3036 http_session_
->GetTransportSocketPool(
3037 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3039 // Create a SPDY session.
3040 CreateInsecureSpdySession();
3041 EXPECT_FALSE(pool
->IsStalled());
3043 // Create a stream using the session, and send a request.
3045 TestCompletionCallback callback1
;
3046 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3047 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
, session_
,
3048 test_url_
, DEFAULT_PRIORITY
, BoundNetLog());
3049 ASSERT_TRUE(spdy_stream1
.get());
3050 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3051 spdy_stream1
->SetDelegate(&delegate1
);
3053 scoped_ptr
<SpdyHeaderBlock
> headers1(
3054 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
3055 EXPECT_EQ(ERR_IO_PENDING
,
3056 spdy_stream1
->SendRequestHeaders(
3057 headers1
.Pass(), NO_MORE_DATA_TO_SEND
));
3058 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3060 base::RunLoop().RunUntilIdle();
3062 // Trying to create a new connection should cause the pool to be stalled, and
3063 // post a task asynchronously to try and close the session.
3064 TestCompletionCallback callback2
;
3065 HostPortPair
host_port2("2.com", 80);
3066 scoped_refptr
<TransportSocketParams
> params2(
3067 new TransportSocketParams(
3068 host_port2
, false, false, OnHostResolutionCallback(),
3069 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3070 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3071 EXPECT_EQ(ERR_IO_PENDING
,
3072 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3073 callback2
.callback(), pool
, BoundNetLog()));
3074 EXPECT_TRUE(pool
->IsStalled());
3076 // Running the message loop should cause the socket pool to ask the SPDY
3077 // session to close an idle socket, but since the socket is in use, nothing
3079 base::RunLoop().RunUntilIdle();
3080 EXPECT_TRUE(pool
->IsStalled());
3081 EXPECT_FALSE(callback2
.have_result());
3083 // Cancelling the request should result in the session's socket being
3084 // closed, since the pool is stalled.
3085 ASSERT_TRUE(spdy_stream1
.get());
3086 spdy_stream1
->Cancel();
3087 base::RunLoop().RunUntilIdle();
3088 ASSERT_FALSE(pool
->IsStalled());
3089 EXPECT_EQ(OK
, callback2
.WaitForResult());
3092 // Verify that SpdySessionKey and therefore SpdySession is different when
3093 // privacy mode is enabled or disabled.
3094 TEST_P(SpdySessionTest
, SpdySessionKeyPrivacyMode
) {
3095 CreateNetworkSession();
3097 HostPortPair
host_port_pair("www.example.org", 443);
3098 SpdySessionKey
key_privacy_enabled(host_port_pair
, ProxyServer::Direct(),
3099 PRIVACY_MODE_ENABLED
);
3100 SpdySessionKey
key_privacy_disabled(host_port_pair
, ProxyServer::Direct(),
3101 PRIVACY_MODE_DISABLED
);
3103 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3104 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3106 // Add SpdySession with PrivacyMode Enabled to the pool.
3107 base::WeakPtr
<SpdySession
> session_privacy_enabled
=
3108 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_enabled
);
3110 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3111 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3113 // Add SpdySession with PrivacyMode Disabled to the pool.
3114 base::WeakPtr
<SpdySession
> session_privacy_disabled
=
3115 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_disabled
);
3117 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3118 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3120 session_privacy_enabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3121 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3122 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3124 session_privacy_disabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3125 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3126 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3129 // Delegate that creates another stream when its stream is closed.
3130 class StreamCreatingDelegate
: public test::StreamDelegateDoNothing
{
3132 StreamCreatingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3133 const base::WeakPtr
<SpdySession
>& session
)
3134 : StreamDelegateDoNothing(stream
),
3135 session_(session
) {}
3137 ~StreamCreatingDelegate() override
{}
3139 void OnClose(int status
) override
{
3140 GURL
url(kDefaultURL
);
3142 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3143 session_
, url
, MEDIUM
, BoundNetLog()));
3147 const base::WeakPtr
<SpdySession
> session_
;
3150 // Create another stream in response to a stream being reset. Nothing
3151 // should blow up. This is a regression test for
3152 // http://crbug.com/263690 .
3153 TEST_P(SpdySessionTest
, CreateStreamOnStreamReset
) {
3154 session_deps_
.host_resolver
->set_synchronous_mode(true);
3156 scoped_ptr
<SpdyFrame
> req(
3157 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM
, true));
3158 MockWrite writes
[] = {
3159 CreateMockWrite(*req
, 0),
3162 scoped_ptr
<SpdyFrame
> rst(
3163 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
3164 MockRead reads
[] = {
3165 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3166 CreateMockRead(*rst
, 2),
3167 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3168 MockRead(ASYNC
, 0, 4) // EOF
3170 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3171 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3173 CreateNetworkSession();
3174 CreateInsecureSpdySession();
3176 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
3177 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
3178 ASSERT_TRUE(spdy_stream
.get() != nullptr);
3179 EXPECT_EQ(0u, spdy_stream
->stream_id());
3181 StreamCreatingDelegate
delegate(spdy_stream
, session_
);
3182 spdy_stream
->SetDelegate(&delegate
);
3184 scoped_ptr
<SpdyHeaderBlock
> headers(
3185 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
3186 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
3187 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
3189 EXPECT_EQ(0u, spdy_stream
->stream_id());
3191 base::RunLoop().RunUntilIdle();
3193 EXPECT_EQ(1u, spdy_stream
->stream_id());
3195 // Cause the stream to be reset, which should cause another stream
3197 data
.CompleteRead();
3198 base::RunLoop().RunUntilIdle();
3200 EXPECT_FALSE(spdy_stream
);
3201 EXPECT_TRUE(delegate
.StreamIsClosed());
3202 EXPECT_EQ(0u, session_
->num_active_streams());
3203 EXPECT_EQ(1u, session_
->num_created_streams());
3205 data
.CompleteRead();
3206 base::RunLoop().RunUntilIdle();
3207 EXPECT_FALSE(session_
);
3210 TEST_P(SpdySessionTest
, UpdateStreamsSendWindowSize
) {
3211 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3213 SettingsMap new_settings
;
3214 int32 window_size
= 1;
3215 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
3216 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, window_size
);
3218 // Set up the socket so we read a SETTINGS frame that sets
3219 // INITIAL_WINDOW_SIZE.
3220 scoped_ptr
<SpdyFrame
> settings_frame(
3221 spdy_util_
.ConstructSpdySettings(new_settings
));
3222 MockRead reads
[] = {
3223 CreateMockRead(*settings_frame
, 0),
3224 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3225 MockRead(ASYNC
, 0, 2) // EOF
3228 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
3229 MockWrite writes
[] = {
3230 CreateMockWrite(*settings_ack
, 3),
3233 session_deps_
.host_resolver
->set_synchronous_mode(true);
3235 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3236 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3238 CreateNetworkSession();
3239 CreateInsecureSpdySession();
3240 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
3241 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
3242 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
3243 TestCompletionCallback callback1
;
3244 EXPECT_NE(spdy_stream1
->send_window_size(), window_size
);
3246 // Process the SETTINGS frame.
3247 base::RunLoop().RunUntilIdle();
3248 EXPECT_EQ(session_
->stream_initial_send_window_size(), window_size
);
3249 EXPECT_EQ(spdy_stream1
->send_window_size(), window_size
);
3251 // Release the first one, this will allow the second to be created.
3252 spdy_stream1
->Cancel();
3253 EXPECT_FALSE(spdy_stream1
);
3255 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
3256 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
3257 ASSERT_TRUE(spdy_stream2
.get() != nullptr);
3258 EXPECT_EQ(spdy_stream2
->send_window_size(), window_size
);
3259 spdy_stream2
->Cancel();
3260 EXPECT_FALSE(spdy_stream2
);
3262 EXPECT_TRUE(session_
);
3263 data
.CompleteRead();
3264 base::RunLoop().RunUntilIdle();
3265 EXPECT_FALSE(session_
);
3268 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3269 // adjust the session receive window size. In addition,
3270 // SpdySession::IncreaseRecvWindowSize should trigger
3271 // sending a WINDOW_UPDATE frame for a large enough delta.
3272 TEST_P(SpdySessionTest
, AdjustRecvWindowSize
) {
3273 session_deps_
.host_resolver
->set_synchronous_mode(true);
3275 const int32 initial_window_size
=
3276 SpdySession::GetDefaultInitialWindowSize(GetParam());
3277 const int32 delta_window_size
= 100;
3279 MockRead reads
[] = {
3280 MockRead(ASYNC
, ERR_IO_PENDING
, 1), MockRead(ASYNC
, 0, 2) // EOF
3282 scoped_ptr
<SpdyFrame
> window_update(spdy_util_
.ConstructSpdyWindowUpdate(
3283 kSessionFlowControlStreamId
, initial_window_size
+ delta_window_size
));
3284 MockWrite writes
[] = {
3285 CreateMockWrite(*window_update
, 0),
3287 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3288 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3290 CreateNetworkSession();
3291 CreateInsecureSpdySession();
3292 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3293 session_
->flow_control_state());
3295 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3296 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3298 session_
->IncreaseRecvWindowSize(delta_window_size
);
3299 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3300 session_
->session_recv_window_size_
);
3301 EXPECT_EQ(delta_window_size
, session_
->session_unacked_recv_window_bytes_
);
3303 // Should trigger sending a WINDOW_UPDATE frame.
3304 session_
->IncreaseRecvWindowSize(initial_window_size
);
3305 EXPECT_EQ(initial_window_size
+ delta_window_size
+ initial_window_size
,
3306 session_
->session_recv_window_size_
);
3307 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3309 base::RunLoop().RunUntilIdle();
3311 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3312 session_
->in_io_loop_
= true;
3313 session_
->DecreaseRecvWindowSize(initial_window_size
+ delta_window_size
+
3314 initial_window_size
);
3315 session_
->in_io_loop_
= false;
3316 EXPECT_EQ(0, session_
->session_recv_window_size_
);
3317 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3319 EXPECT_TRUE(session_
);
3320 data
.CompleteRead();
3321 base::RunLoop().RunUntilIdle();
3322 EXPECT_FALSE(session_
);
3325 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3326 // adjust the session send window size when the "enable_spdy_31" flag
3328 TEST_P(SpdySessionTest
, AdjustSendWindowSize
) {
3329 session_deps_
.host_resolver
->set_synchronous_mode(true);
3331 MockRead reads
[] = {
3332 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3334 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
3335 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3337 CreateNetworkSession();
3338 session_
= CreateFakeSpdySession(spdy_session_pool_
, key_
);
3339 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3340 session_
->flow_control_state());
3342 const int32 initial_window_size
=
3343 SpdySession::GetDefaultInitialWindowSize(GetParam());
3344 const int32 delta_window_size
= 100;
3346 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3348 session_
->IncreaseSendWindowSize(delta_window_size
);
3349 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3350 session_
->session_send_window_size_
);
3352 session_
->DecreaseSendWindowSize(delta_window_size
);
3353 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3356 // Incoming data for an inactive stream should not cause the session
3357 // receive window size to decrease, but it should cause the unacked
3358 // bytes to increase.
3359 TEST_P(SpdySessionTest
, SessionFlowControlInactiveStream
) {
3360 session_deps_
.host_resolver
->set_synchronous_mode(true);
3362 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(1, false));
3363 MockRead reads
[] = {
3364 CreateMockRead(*resp
, 0),
3365 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3366 MockRead(ASYNC
, 0, 2) // EOF
3368 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
3369 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3371 CreateNetworkSession();
3372 CreateInsecureSpdySession();
3373 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3374 session_
->flow_control_state());
3376 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3377 session_
->session_recv_window_size_
);
3378 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3380 base::RunLoop().RunUntilIdle();
3382 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3383 session_
->session_recv_window_size_
);
3384 EXPECT_EQ(kUploadDataSize
, session_
->session_unacked_recv_window_bytes_
);
3386 EXPECT_TRUE(session_
);
3387 data
.CompleteRead();
3388 base::RunLoop().RunUntilIdle();
3389 EXPECT_FALSE(session_
);
3392 // The frame header is not included in flow control, but frame payload
3393 // (including optional pad length and padding) is.
3394 TEST_P(SpdySessionTest
, SessionFlowControlPadding
) {
3395 // Padding only exists in HTTP/2.
3396 if (GetParam() < kProtoHTTP2
)
3399 session_deps_
.host_resolver
->set_synchronous_mode(true);
3401 const int padding_length
= 42;
3402 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(
3403 1, kUploadData
, kUploadDataSize
, false, padding_length
));
3404 MockRead reads
[] = {
3405 CreateMockRead(*resp
, 0),
3406 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3407 MockRead(ASYNC
, 0, 2) // EOF
3409 SequencedSocketData
data(reads
, arraysize(reads
), nullptr, 0);
3410 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3412 CreateNetworkSession();
3413 CreateInsecureSpdySession();
3414 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3415 session_
->flow_control_state());
3417 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3418 session_
->session_recv_window_size_
);
3419 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3421 base::RunLoop().RunUntilIdle();
3423 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3424 session_
->session_recv_window_size_
);
3425 EXPECT_EQ(kUploadDataSize
+ padding_length
,
3426 session_
->session_unacked_recv_window_bytes_
);
3428 data
.CompleteRead();
3429 base::RunLoop().RunUntilIdle();
3430 EXPECT_FALSE(session_
);
3433 // Peer sends more data than stream level receiving flow control window.
3434 TEST_P(SpdySessionTest
, StreamFlowControlTooMuchData
) {
3435 const int32 stream_max_recv_window_size
= 1024;
3436 const int32 data_frame_size
= 2 * stream_max_recv_window_size
;
3438 scoped_ptr
<SpdyFrame
> req(
3439 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3440 scoped_ptr
<SpdyFrame
> rst(
3441 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
3442 MockWrite writes
[] = {
3443 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 4),
3446 scoped_ptr
<SpdyFrame
> resp(
3447 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3448 const std::string
payload(data_frame_size
, 'a');
3449 scoped_ptr
<SpdyFrame
> data_frame(spdy_util_
.ConstructSpdyBodyFrame(
3450 1, payload
.data(), data_frame_size
, false));
3451 MockRead reads
[] = {
3452 CreateMockRead(*resp
, 1),
3453 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
3454 CreateMockRead(*data_frame
, 3),
3455 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
3456 MockRead(ASYNC
, 0, 6),
3459 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3460 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3461 CreateNetworkSession();
3463 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
3464 pool_peer
.SetStreamInitialRecvWindowSize(stream_max_recv_window_size
);
3465 CreateInsecureSpdySession();
3466 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM
, session_
->flow_control_state());
3468 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
3469 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
3470 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3472 test::StreamDelegateDoNothing
delegate(spdy_stream
);
3473 spdy_stream
->SetDelegate(&delegate
);
3475 scoped_ptr
<SpdyHeaderBlock
> headers(
3476 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
3477 EXPECT_EQ(ERR_IO_PENDING
, spdy_stream
->SendRequestHeaders(
3478 headers
.Pass(), NO_MORE_DATA_TO_SEND
));
3480 // Request and response.
3481 base::RunLoop().RunUntilIdle();
3482 EXPECT_EQ(1u, spdy_stream
->stream_id());
3484 // Too large data frame causes flow control error, should close stream.
3485 data
.CompleteRead();
3486 base::RunLoop().RunUntilIdle();
3487 EXPECT_FALSE(spdy_stream
);
3489 EXPECT_TRUE(session_
);
3490 data
.CompleteRead();
3491 base::RunLoop().RunUntilIdle();
3492 EXPECT_FALSE(session_
);
3495 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3496 // deltas in the receiving window size when checking incoming frames for flow
3497 // control errors at session level.
3498 TEST_P(SpdySessionTest
, SessionFlowControlTooMuchDataTwoDataFrames
) {
3499 const int32 session_max_recv_window_size
= 500;
3500 const int32 first_data_frame_size
= 200;
3501 const int32 second_data_frame_size
= 400;
3503 // First data frame should not trigger a WINDOW_UPDATE.
3504 ASSERT_GT(session_max_recv_window_size
/ 2, first_data_frame_size
);
3505 // Second data frame would be fine had there been a WINDOW_UPDATE.
3506 ASSERT_GT(session_max_recv_window_size
, second_data_frame_size
);
3507 // But in fact, the two data frames together overflow the receiving window at
3509 ASSERT_LT(session_max_recv_window_size
,
3510 first_data_frame_size
+ second_data_frame_size
);
3512 session_deps_
.host_resolver
->set_synchronous_mode(true);
3514 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
3515 0, GOAWAY_FLOW_CONTROL_ERROR
,
3516 "delta_window_size is 400 in DecreaseRecvWindowSize, which is larger "
3517 "than the receive window size of 500"));
3518 MockWrite writes
[] = {
3519 CreateMockWrite(*goaway
, 4),
3522 const std::string
first_data_frame(first_data_frame_size
, 'a');
3523 scoped_ptr
<SpdyFrame
> first(spdy_util_
.ConstructSpdyBodyFrame(
3524 1, first_data_frame
.data(), first_data_frame_size
, false));
3525 const std::string
second_data_frame(second_data_frame_size
, 'b');
3526 scoped_ptr
<SpdyFrame
> second(spdy_util_
.ConstructSpdyBodyFrame(
3527 1, second_data_frame
.data(), second_data_frame_size
, false));
3528 MockRead reads
[] = {
3529 CreateMockRead(*first
, 0),
3530 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3531 CreateMockRead(*second
, 2),
3532 MockRead(ASYNC
, 0, 3),
3534 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3535 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3537 CreateNetworkSession();
3538 CreateInsecureSpdySession();
3539 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3540 session_
->flow_control_state());
3541 // Setting session level receiving window size to smaller than initial is not
3542 // possible via SpdySessionPoolPeer.
3543 session_
->session_recv_window_size_
= session_max_recv_window_size
;
3545 // First data frame is immediately consumed and does not trigger
3547 base::RunLoop().RunUntilIdle();
3548 EXPECT_EQ(first_data_frame_size
,
3549 session_
->session_unacked_recv_window_bytes_
);
3550 EXPECT_EQ(session_max_recv_window_size
, session_
->session_recv_window_size_
);
3551 EXPECT_EQ(SpdySession::STATE_AVAILABLE
, session_
->availability_state_
);
3553 // Second data frame overflows receiving window, causes session to close.
3554 data
.CompleteRead();
3555 base::RunLoop().RunUntilIdle();
3556 EXPECT_EQ(SpdySession::STATE_DRAINING
, session_
->availability_state_
);
3559 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3560 // deltas in the receiving window size when checking incoming data frames for
3561 // flow control errors at stream level.
3562 TEST_P(SpdySessionTest
, StreamFlowControlTooMuchDataTwoDataFrames
) {
3563 const int32 stream_max_recv_window_size
= 500;
3564 const int32 first_data_frame_size
= 200;
3565 const int32 second_data_frame_size
= 400;
3567 // First data frame should not trigger a WINDOW_UPDATE.
3568 ASSERT_GT(stream_max_recv_window_size
/ 2, first_data_frame_size
);
3569 // Second data frame would be fine had there been a WINDOW_UPDATE.
3570 ASSERT_GT(stream_max_recv_window_size
, second_data_frame_size
);
3571 // But in fact, they should overflow the receiving window at stream level.
3572 ASSERT_LT(stream_max_recv_window_size
,
3573 first_data_frame_size
+ second_data_frame_size
);
3575 scoped_ptr
<SpdyFrame
> req(
3576 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
3577 scoped_ptr
<SpdyFrame
> rst(
3578 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR
));
3579 MockWrite writes
[] = {
3580 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 6),
3583 scoped_ptr
<SpdyFrame
> resp(
3584 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3585 const std::string
first_data_frame(first_data_frame_size
, 'a');
3586 scoped_ptr
<SpdyFrame
> first(spdy_util_
.ConstructSpdyBodyFrame(
3587 1, first_data_frame
.data(), first_data_frame_size
, false));
3588 const std::string
second_data_frame(second_data_frame_size
, 'b');
3589 scoped_ptr
<SpdyFrame
> second(spdy_util_
.ConstructSpdyBodyFrame(
3590 1, second_data_frame
.data(), second_data_frame_size
, false));
3591 MockRead reads
[] = {
3592 CreateMockRead(*resp
, 1),
3593 MockRead(ASYNC
, ERR_IO_PENDING
, 2),
3594 CreateMockRead(*first
, 3),
3595 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
3596 CreateMockRead(*second
, 5),
3597 MockRead(ASYNC
, ERR_IO_PENDING
, 7),
3598 MockRead(ASYNC
, 0, 8),
3601 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3602 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3604 CreateNetworkSession();
3605 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
3606 pool_peer
.SetStreamInitialRecvWindowSize(stream_max_recv_window_size
);
3608 CreateInsecureSpdySession();
3609 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM
, session_
->flow_control_state());
3611 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
3612 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
3613 test::StreamDelegateDoNothing
delegate(spdy_stream
);
3614 spdy_stream
->SetDelegate(&delegate
);
3616 scoped_ptr
<SpdyHeaderBlock
> headers(
3617 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
3618 EXPECT_EQ(ERR_IO_PENDING
, spdy_stream
->SendRequestHeaders(
3619 headers
.Pass(), NO_MORE_DATA_TO_SEND
));
3621 // Request and response.
3622 base::RunLoop().RunUntilIdle();
3623 EXPECT_TRUE(spdy_stream
->IsLocallyClosed());
3624 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3626 // First data frame.
3627 data
.CompleteRead();
3628 base::RunLoop().RunUntilIdle();
3629 EXPECT_TRUE(spdy_stream
->IsLocallyClosed());
3630 EXPECT_EQ(stream_max_recv_window_size
- first_data_frame_size
,
3631 spdy_stream
->recv_window_size());
3633 // Consume first data frame. This does not trigger a WINDOW_UPDATE.
3634 std::string received_data
= delegate
.TakeReceivedData();
3635 EXPECT_EQ(static_cast<size_t>(first_data_frame_size
), received_data
.size());
3636 EXPECT_EQ(stream_max_recv_window_size
, spdy_stream
->recv_window_size());
3638 // Second data frame overflows receiving window, causes the stream to close.
3639 data
.CompleteRead();
3640 base::RunLoop().RunUntilIdle();
3641 EXPECT_FALSE(spdy_stream
.get());
3644 EXPECT_TRUE(session_
);
3645 data
.CompleteRead();
3646 base::RunLoop().RunUntilIdle();
3647 EXPECT_FALSE(session_
);
3650 // A delegate that drops any received data.
3651 class DropReceivedDataDelegate
: public test::StreamDelegateSendImmediate
{
3653 DropReceivedDataDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3654 base::StringPiece data
)
3655 : StreamDelegateSendImmediate(stream
, data
) {}
3657 ~DropReceivedDataDelegate() override
{}
3659 // Drop any received data.
3660 void OnDataReceived(scoped_ptr
<SpdyBuffer
> buffer
) override
{}
3663 // Send data back and forth but use a delegate that drops its received
3664 // data. The receive window should still increase to its original
3665 // value, i.e. we shouldn't "leak" receive window bytes.
3666 TEST_P(SpdySessionTest
, SessionFlowControlNoReceiveLeaks
) {
3667 const int32 msg_data_size
= 100;
3668 const std::string
msg_data(msg_data_size
, 'a');
3670 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3671 kDefaultURL
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
3672 scoped_ptr
<SpdyFrame
> msg(
3673 spdy_util_
.ConstructSpdyBodyFrame(
3674 1, msg_data
.data(), msg_data_size
, false));
3675 MockWrite writes
[] = {
3676 CreateMockWrite(*req
, 0),
3677 CreateMockWrite(*msg
, 2),
3680 scoped_ptr
<SpdyFrame
> resp(
3681 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3682 scoped_ptr
<SpdyFrame
> echo(
3683 spdy_util_
.ConstructSpdyBodyFrame(
3684 1, msg_data
.data(), msg_data_size
, false));
3685 scoped_ptr
<SpdyFrame
> window_update(
3686 spdy_util_
.ConstructSpdyWindowUpdate(
3687 kSessionFlowControlStreamId
, msg_data_size
));
3688 MockRead reads
[] = {
3689 CreateMockRead(*resp
, 1),
3690 CreateMockRead(*echo
, 3),
3691 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
3692 MockRead(ASYNC
, 0, 5) // EOF
3695 // Create SpdySession and SpdyStream and send the request.
3696 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3697 session_deps_
.host_resolver
->set_synchronous_mode(true);
3698 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3700 CreateNetworkSession();
3701 CreateInsecureSpdySession();
3703 base::WeakPtr
<SpdyStream
> stream
= CreateStreamSynchronously(
3704 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
3705 ASSERT_TRUE(stream
.get() != nullptr);
3706 EXPECT_EQ(0u, stream
->stream_id());
3708 DropReceivedDataDelegate
delegate(stream
, msg_data
);
3709 stream
->SetDelegate(&delegate
);
3711 scoped_ptr
<SpdyHeaderBlock
> headers(
3712 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, msg_data_size
));
3713 EXPECT_EQ(ERR_IO_PENDING
,
3714 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3715 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3717 const int32 initial_window_size
=
3718 SpdySession::GetDefaultInitialWindowSize(GetParam());
3719 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3720 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3722 base::RunLoop().RunUntilIdle();
3724 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3725 EXPECT_EQ(msg_data_size
, session_
->session_unacked_recv_window_bytes_
);
3728 EXPECT_FALSE(stream
);
3730 EXPECT_EQ(OK
, delegate
.WaitForClose());
3732 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3733 EXPECT_EQ(msg_data_size
, session_
->session_unacked_recv_window_bytes_
);
3735 data
.CompleteRead();
3736 base::RunLoop().RunUntilIdle();
3737 EXPECT_FALSE(session_
);
3740 // Send data back and forth but close the stream before its data frame
3741 // can be written to the socket. The send window should then increase
3742 // to its original value, i.e. we shouldn't "leak" send window bytes.
3743 TEST_P(SpdySessionTest
, SessionFlowControlNoSendLeaks
) {
3744 const int32 msg_data_size
= 100;
3745 const std::string
msg_data(msg_data_size
, 'a');
3747 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3748 kDefaultURL
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
3749 MockWrite writes
[] = {
3750 CreateMockWrite(*req
, 0),
3753 scoped_ptr
<SpdyFrame
> resp(
3754 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3755 MockRead reads
[] = {
3756 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
3757 CreateMockRead(*resp
, 2),
3758 MockRead(ASYNC
, 0, 3) // EOF
3761 // Create SpdySession and SpdyStream and send the request.
3762 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3763 session_deps_
.host_resolver
->set_synchronous_mode(true);
3764 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3766 CreateNetworkSession();
3767 CreateInsecureSpdySession();
3769 base::WeakPtr
<SpdyStream
> stream
= CreateStreamSynchronously(
3770 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
3771 ASSERT_TRUE(stream
.get() != nullptr);
3772 EXPECT_EQ(0u, stream
->stream_id());
3774 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3775 stream
->SetDelegate(&delegate
);
3777 scoped_ptr
<SpdyHeaderBlock
> headers(
3778 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, msg_data_size
));
3779 EXPECT_EQ(ERR_IO_PENDING
,
3780 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3781 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3783 const int32 initial_window_size
=
3784 SpdySession::GetDefaultInitialWindowSize(GetParam());
3785 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3788 base::RunLoop().RunUntilIdle();
3790 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3792 // Read response, but do not run the message loop, so that the body is not
3793 // written to the socket.
3794 data
.CompleteRead();
3796 EXPECT_EQ(initial_window_size
- msg_data_size
,
3797 session_
->session_send_window_size_
);
3799 // Closing the stream should increase the session's send window.
3801 EXPECT_FALSE(stream
);
3803 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3805 EXPECT_EQ(OK
, delegate
.WaitForClose());
3807 base::RunLoop().RunUntilIdle();
3808 EXPECT_FALSE(session_
);
3810 EXPECT_TRUE(data
.AllWriteDataConsumed());
3811 EXPECT_TRUE(data
.AllReadDataConsumed());
3814 // Send data back and forth; the send and receive windows should
3815 // change appropriately.
3816 TEST_P(SpdySessionTest
, SessionFlowControlEndToEnd
) {
3817 const int32 msg_data_size
= 100;
3818 const std::string
msg_data(msg_data_size
, 'a');
3820 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3821 kDefaultURL
, 1, msg_data_size
, MEDIUM
, nullptr, 0));
3822 scoped_ptr
<SpdyFrame
> msg(
3823 spdy_util_
.ConstructSpdyBodyFrame(
3824 1, msg_data
.data(), msg_data_size
, false));
3825 MockWrite writes
[] = {
3826 CreateMockWrite(*req
, 0),
3827 CreateMockWrite(*msg
, 2),
3830 scoped_ptr
<SpdyFrame
> resp(
3831 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3832 scoped_ptr
<SpdyFrame
> echo(
3833 spdy_util_
.ConstructSpdyBodyFrame(
3834 1, msg_data
.data(), msg_data_size
, false));
3835 scoped_ptr
<SpdyFrame
> window_update(
3836 spdy_util_
.ConstructSpdyWindowUpdate(
3837 kSessionFlowControlStreamId
, msg_data_size
));
3838 MockRead reads
[] = {
3839 CreateMockRead(*resp
, 1),
3840 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3841 CreateMockRead(*echo
, 4),
3842 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
3843 CreateMockRead(*window_update
, 6),
3844 MockRead(ASYNC
, ERR_IO_PENDING
, 7),
3845 MockRead(ASYNC
, 0, 8) // EOF
3848 // Create SpdySession and SpdyStream and send the request.
3849 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3850 session_deps_
.host_resolver
->set_synchronous_mode(true);
3851 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3853 CreateNetworkSession();
3854 CreateInsecureSpdySession();
3856 base::WeakPtr
<SpdyStream
> stream
= CreateStreamSynchronously(
3857 SPDY_BIDIRECTIONAL_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
3858 ASSERT_TRUE(stream
.get() != nullptr);
3859 EXPECT_EQ(0u, stream
->stream_id());
3861 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3862 stream
->SetDelegate(&delegate
);
3864 scoped_ptr
<SpdyHeaderBlock
> headers(
3865 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, msg_data_size
));
3866 EXPECT_EQ(ERR_IO_PENDING
,
3867 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3868 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3870 const int32 initial_window_size
=
3871 SpdySession::GetDefaultInitialWindowSize(GetParam());
3872 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3873 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3874 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3876 // Send request and message.
3877 base::RunLoop().RunUntilIdle();
3879 EXPECT_EQ(initial_window_size
- msg_data_size
,
3880 session_
->session_send_window_size_
);
3881 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3882 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3885 data
.CompleteRead();
3886 base::RunLoop().RunUntilIdle();
3888 EXPECT_EQ(initial_window_size
- msg_data_size
,
3889 session_
->session_send_window_size_
);
3890 EXPECT_EQ(initial_window_size
- msg_data_size
,
3891 session_
->session_recv_window_size_
);
3892 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3894 // Read window update.
3895 data
.CompleteRead();
3896 base::RunLoop().RunUntilIdle();
3898 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3899 EXPECT_EQ(initial_window_size
- msg_data_size
,
3900 session_
->session_recv_window_size_
);
3901 EXPECT_EQ(0, session_
->session_unacked_recv_window_bytes_
);
3903 EXPECT_EQ(msg_data
, delegate
.TakeReceivedData());
3905 // Draining the delegate's read queue should increase the session's
3907 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3908 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3909 EXPECT_EQ(msg_data_size
, session_
->session_unacked_recv_window_bytes_
);
3912 EXPECT_FALSE(stream
);
3914 EXPECT_EQ(OK
, delegate
.WaitForClose());
3916 EXPECT_EQ(initial_window_size
, session_
->session_send_window_size_
);
3917 EXPECT_EQ(initial_window_size
, session_
->session_recv_window_size_
);
3918 EXPECT_EQ(msg_data_size
, session_
->session_unacked_recv_window_bytes_
);
3920 data
.CompleteRead();
3921 base::RunLoop().RunUntilIdle();
3922 EXPECT_FALSE(session_
);
3925 // Given a stall function and an unstall function, runs a test to make
3926 // sure that a stream resumes after unstall.
3927 void SpdySessionTest::RunResumeAfterUnstallTest(
3928 const base::Callback
<void(SpdyStream
*)>& stall_function
,
3929 const base::Callback
<void(SpdyStream
*, int32
)>& unstall_function
) {
3931 session_deps_
.host_resolver
->set_synchronous_mode(true);
3933 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyPost(
3934 kDefaultURL
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
3935 scoped_ptr
<SpdyFrame
> body(
3936 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
3937 MockWrite writes
[] = {
3938 CreateMockWrite(*req
, 0),
3939 CreateMockWrite(*body
, 1),
3942 scoped_ptr
<SpdyFrame
> resp(
3943 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
3944 scoped_ptr
<SpdyFrame
> echo(
3945 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
3946 MockRead reads
[] = {
3947 CreateMockRead(*resp
, 2), MockRead(ASYNC
, 0, 3) // EOF
3950 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
3951 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3953 CreateNetworkSession();
3954 CreateInsecureSpdySession();
3955 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3956 session_
->flow_control_state());
3958 base::WeakPtr
<SpdyStream
> stream
= CreateStreamSynchronously(
3959 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
3960 ASSERT_TRUE(stream
.get() != nullptr);
3962 test::StreamDelegateWithBody
delegate(stream
, kBodyDataStringPiece
);
3963 stream
->SetDelegate(&delegate
);
3965 EXPECT_FALSE(stream
->HasUrlFromHeaders());
3966 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
3968 scoped_ptr
<SpdyHeaderBlock
> headers(
3969 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
3970 EXPECT_EQ(ERR_IO_PENDING
,
3971 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3972 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3973 EXPECT_EQ(kDefaultURL
, stream
->GetUrlFromHeaders().spec());
3975 stall_function
.Run(stream
.get());
3977 base::RunLoop().RunUntilIdle();
3979 EXPECT_TRUE(stream
->send_stalled_by_flow_control());
3981 unstall_function
.Run(stream
.get(), kBodyDataSize
);
3983 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
3985 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
3987 EXPECT_TRUE(delegate
.send_headers_completed());
3988 EXPECT_EQ("200", delegate
.GetResponseHeaderValue(":status"));
3989 EXPECT_EQ(std::string(), delegate
.TakeReceivedData());
3990 EXPECT_FALSE(session_
);
3991 EXPECT_TRUE(data
.AllWriteDataConsumed());
3994 // Run the resume-after-unstall test with all possible stall and
3995 // unstall sequences.
3997 TEST_P(SpdySessionTest
, ResumeAfterUnstallSession
) {
3998 RunResumeAfterUnstallTest(
3999 base::Bind(&SpdySessionTest::StallSessionOnly
,
4000 base::Unretained(this)),
4001 base::Bind(&SpdySessionTest::UnstallSessionOnly
,
4002 base::Unretained(this)));
4006 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4007 TEST_P(SpdySessionTest
, ResumeAfterUnstallStream
) {
4008 RunResumeAfterUnstallTest(
4009 base::Bind(&SpdySessionTest::StallStreamOnly
,
4010 base::Unretained(this)),
4011 base::Bind(&SpdySessionTest::UnstallStreamOnly
,
4012 base::Unretained(this)));
4015 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallSessionStream
) {
4016 RunResumeAfterUnstallTest(
4017 base::Bind(&SpdySessionTest::StallSessionStream
,
4018 base::Unretained(this)),
4019 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4020 base::Unretained(this)));
4023 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallSessionStream
) {
4024 RunResumeAfterUnstallTest(
4025 base::Bind(&SpdySessionTest::StallStreamSession
,
4026 base::Unretained(this)),
4027 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4028 base::Unretained(this)));
4031 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallStreamSession
) {
4032 RunResumeAfterUnstallTest(
4033 base::Bind(&SpdySessionTest::StallStreamSession
,
4034 base::Unretained(this)),
4035 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4036 base::Unretained(this)));
4039 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallStreamSession
) {
4040 RunResumeAfterUnstallTest(
4041 base::Bind(&SpdySessionTest::StallSessionStream
,
4042 base::Unretained(this)),
4043 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4044 base::Unretained(this)));
4047 // Cause a stall by reducing the flow control send window to 0. The
4048 // streams should resume in priority order when that window is then
4050 TEST_P(SpdySessionTest
, ResumeByPriorityAfterSendWindowSizeIncrease
) {
4051 session_deps_
.host_resolver
->set_synchronous_mode(true);
4053 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4054 kDefaultURL
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4055 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4056 kDefaultURL
, 3, kBodyDataSize
, MEDIUM
, nullptr, 0));
4057 scoped_ptr
<SpdyFrame
> body1(
4058 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
4059 scoped_ptr
<SpdyFrame
> body2(
4060 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4061 MockWrite writes
[] = {
4062 CreateMockWrite(*req1
, 0),
4063 CreateMockWrite(*req2
, 1),
4064 CreateMockWrite(*body2
, 2),
4065 CreateMockWrite(*body1
, 3),
4068 scoped_ptr
<SpdyFrame
> resp1(
4069 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4070 scoped_ptr
<SpdyFrame
> resp2(
4071 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
4072 MockRead reads
[] = {
4073 CreateMockRead(*resp1
, 4),
4074 CreateMockRead(*resp2
, 5),
4075 MockRead(ASYNC
, 0, 6) // EOF
4078 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4079 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4081 CreateNetworkSession();
4082 CreateInsecureSpdySession();
4083 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4084 session_
->flow_control_state());
4086 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
4087 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4088 ASSERT_TRUE(stream1
.get() != nullptr);
4090 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4091 stream1
->SetDelegate(&delegate1
);
4093 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4095 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
4096 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, MEDIUM
, BoundNetLog());
4097 ASSERT_TRUE(stream2
.get() != nullptr);
4099 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4100 stream2
->SetDelegate(&delegate2
);
4102 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4104 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4105 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4109 scoped_ptr
<SpdyHeaderBlock
> headers1(
4110 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4111 EXPECT_EQ(ERR_IO_PENDING
,
4112 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4113 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4114 EXPECT_EQ(kDefaultURL
, stream1
->GetUrlFromHeaders().spec());
4116 base::RunLoop().RunUntilIdle();
4117 EXPECT_EQ(1u, stream1
->stream_id());
4118 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4120 scoped_ptr
<SpdyHeaderBlock
> headers2(
4121 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4122 EXPECT_EQ(ERR_IO_PENDING
,
4123 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4124 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4125 EXPECT_EQ(kDefaultURL
, stream2
->GetUrlFromHeaders().spec());
4127 base::RunLoop().RunUntilIdle();
4128 EXPECT_EQ(3u, stream2
->stream_id());
4129 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4131 // This should unstall only stream2.
4132 UnstallSessionSend(kBodyDataSize
);
4134 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4135 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4137 base::RunLoop().RunUntilIdle();
4139 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4140 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4142 // This should then unstall stream1.
4143 UnstallSessionSend(kBodyDataSize
);
4145 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4146 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4148 base::RunLoop().RunUntilIdle();
4150 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4151 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4153 EXPECT_TRUE(delegate1
.send_headers_completed());
4154 EXPECT_EQ("200", delegate1
.GetResponseHeaderValue(":status"));
4155 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4157 EXPECT_TRUE(delegate2
.send_headers_completed());
4158 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4159 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4161 EXPECT_FALSE(session_
);
4162 EXPECT_TRUE(data
.AllWriteDataConsumed());
4163 EXPECT_TRUE(data
.AllReadDataConsumed());
4166 // Delegate that closes a given stream after sending its body.
4167 class StreamClosingDelegate
: public test::StreamDelegateWithBody
{
4169 StreamClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
4170 base::StringPiece data
)
4171 : StreamDelegateWithBody(stream
, data
) {}
4173 ~StreamClosingDelegate() override
{}
4175 void set_stream_to_close(const base::WeakPtr
<SpdyStream
>& stream_to_close
) {
4176 stream_to_close_
= stream_to_close
;
4179 void OnDataSent() override
{
4180 test::StreamDelegateWithBody::OnDataSent();
4181 if (stream_to_close_
.get()) {
4182 stream_to_close_
->Close();
4183 EXPECT_FALSE(stream_to_close_
);
4188 base::WeakPtr
<SpdyStream
> stream_to_close_
;
4191 // Cause a stall by reducing the flow control send window to
4192 // 0. Unstalling the session should properly handle deleted streams.
4193 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedStreams
) {
4194 session_deps_
.host_resolver
->set_synchronous_mode(true);
4196 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4197 kDefaultURL
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4198 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4199 kDefaultURL
, 3, kBodyDataSize
, LOWEST
, nullptr, 0));
4200 scoped_ptr
<SpdyFrame
> req3(spdy_util_
.ConstructSpdyPost(
4201 kDefaultURL
, 5, kBodyDataSize
, LOWEST
, nullptr, 0));
4202 scoped_ptr
<SpdyFrame
> body2(
4203 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4204 MockWrite writes
[] = {
4205 CreateMockWrite(*req1
, 0),
4206 CreateMockWrite(*req2
, 1),
4207 CreateMockWrite(*req3
, 2),
4208 CreateMockWrite(*body2
, 3),
4211 scoped_ptr
<SpdyFrame
> resp2(
4212 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 3));
4213 MockRead reads
[] = {
4214 CreateMockRead(*resp2
, 4),
4215 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4216 MockRead(ASYNC
, 0, 6) // EOF
4219 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4220 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4222 CreateNetworkSession();
4223 CreateInsecureSpdySession();
4224 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4225 session_
->flow_control_state());
4227 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
4228 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4229 ASSERT_TRUE(stream1
.get() != nullptr);
4231 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4232 stream1
->SetDelegate(&delegate1
);
4234 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4236 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
4237 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4238 ASSERT_TRUE(stream2
.get() != nullptr);
4240 StreamClosingDelegate
delegate2(stream2
, kBodyDataStringPiece
);
4241 stream2
->SetDelegate(&delegate2
);
4243 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4245 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
4246 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4247 ASSERT_TRUE(stream3
.get() != nullptr);
4249 test::StreamDelegateWithBody
delegate3(stream3
, kBodyDataStringPiece
);
4250 stream3
->SetDelegate(&delegate3
);
4252 EXPECT_FALSE(stream3
->HasUrlFromHeaders());
4254 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4255 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4256 EXPECT_FALSE(stream3
->send_stalled_by_flow_control());
4260 scoped_ptr
<SpdyHeaderBlock
> headers1(
4261 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4262 EXPECT_EQ(ERR_IO_PENDING
,
4263 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4264 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4265 EXPECT_EQ(kDefaultURL
, stream1
->GetUrlFromHeaders().spec());
4267 base::RunLoop().RunUntilIdle();
4268 EXPECT_EQ(1u, stream1
->stream_id());
4269 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4271 scoped_ptr
<SpdyHeaderBlock
> headers2(
4272 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4273 EXPECT_EQ(ERR_IO_PENDING
,
4274 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4275 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4276 EXPECT_EQ(kDefaultURL
, stream2
->GetUrlFromHeaders().spec());
4278 base::RunLoop().RunUntilIdle();
4279 EXPECT_EQ(3u, stream2
->stream_id());
4280 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4282 scoped_ptr
<SpdyHeaderBlock
> headers3(
4283 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4284 EXPECT_EQ(ERR_IO_PENDING
,
4285 stream3
->SendRequestHeaders(headers3
.Pass(), MORE_DATA_TO_SEND
));
4286 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
4287 EXPECT_EQ(kDefaultURL
, stream3
->GetUrlFromHeaders().spec());
4289 base::RunLoop().RunUntilIdle();
4290 EXPECT_EQ(5u, stream3
->stream_id());
4291 EXPECT_TRUE(stream3
->send_stalled_by_flow_control());
4293 SpdyStreamId stream_id1
= stream1
->stream_id();
4294 SpdyStreamId stream_id2
= stream2
->stream_id();
4295 SpdyStreamId stream_id3
= stream3
->stream_id();
4297 // Close stream1 preemptively.
4298 session_
->CloseActiveStream(stream_id1
, ERR_CONNECTION_CLOSED
);
4299 EXPECT_FALSE(stream1
);
4301 EXPECT_FALSE(session_
->IsStreamActive(stream_id1
));
4302 EXPECT_TRUE(session_
->IsStreamActive(stream_id2
));
4303 EXPECT_TRUE(session_
->IsStreamActive(stream_id3
));
4305 // Unstall stream2, which should then close stream3.
4306 delegate2
.set_stream_to_close(stream3
);
4307 UnstallSessionSend(kBodyDataSize
);
4309 base::RunLoop().RunUntilIdle();
4310 EXPECT_FALSE(stream3
);
4312 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4313 EXPECT_FALSE(session_
->IsStreamActive(stream_id1
));
4314 EXPECT_TRUE(session_
->IsStreamActive(stream_id2
));
4315 EXPECT_FALSE(session_
->IsStreamActive(stream_id3
));
4317 data
.CompleteRead();
4318 base::RunLoop().RunUntilIdle();
4319 EXPECT_FALSE(stream2
);
4320 EXPECT_FALSE(session_
);
4322 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4323 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4324 EXPECT_EQ(OK
, delegate3
.WaitForClose());
4326 EXPECT_TRUE(delegate1
.send_headers_completed());
4327 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4329 EXPECT_TRUE(delegate2
.send_headers_completed());
4330 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4331 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4333 EXPECT_TRUE(delegate3
.send_headers_completed());
4334 EXPECT_EQ(std::string(), delegate3
.TakeReceivedData());
4336 EXPECT_TRUE(data
.AllWriteDataConsumed());
4339 // Cause a stall by reducing the flow control send window to
4340 // 0. Unstalling the session should properly handle the session itself
4342 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedSession
) {
4343 session_deps_
.host_resolver
->set_synchronous_mode(true);
4345 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyPost(
4346 kDefaultURL
, 1, kBodyDataSize
, LOWEST
, nullptr, 0));
4347 scoped_ptr
<SpdyFrame
> req2(spdy_util_
.ConstructSpdyPost(
4348 kDefaultURL
, 3, kBodyDataSize
, LOWEST
, nullptr, 0));
4349 scoped_ptr
<SpdyFrame
> body1(
4350 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4351 MockWrite writes
[] = {
4352 CreateMockWrite(*req1
, 0),
4353 CreateMockWrite(*req2
, 1),
4356 MockRead reads
[] = {
4357 MockRead(ASYNC
, ERR_IO_PENDING
, 2), MockRead(ASYNC
, 0, 3) // EOF
4360 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4361 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4363 CreateNetworkSession();
4364 CreateInsecureSpdySession();
4365 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4366 session_
->flow_control_state());
4368 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
4369 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4370 ASSERT_TRUE(stream1
.get() != nullptr);
4372 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4373 stream1
->SetDelegate(&delegate1
);
4375 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4377 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
4378 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4379 ASSERT_TRUE(stream2
.get() != nullptr);
4381 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4382 stream2
->SetDelegate(&delegate2
);
4384 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4386 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4387 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4391 scoped_ptr
<SpdyHeaderBlock
> headers1(
4392 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4393 EXPECT_EQ(ERR_IO_PENDING
,
4394 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4395 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4396 EXPECT_EQ(kDefaultURL
, stream1
->GetUrlFromHeaders().spec());
4398 base::RunLoop().RunUntilIdle();
4399 EXPECT_EQ(1u, stream1
->stream_id());
4400 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4402 scoped_ptr
<SpdyHeaderBlock
> headers2(
4403 spdy_util_
.ConstructPostHeaderBlock(kDefaultURL
, kBodyDataSize
));
4404 EXPECT_EQ(ERR_IO_PENDING
,
4405 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4406 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4407 EXPECT_EQ(kDefaultURL
, stream2
->GetUrlFromHeaders().spec());
4409 base::RunLoop().RunUntilIdle();
4410 EXPECT_EQ(3u, stream2
->stream_id());
4411 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4413 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
4416 UnstallSessionSend(kBodyDataSize
);
4418 // Close the session (since we can't do it from within the delegate
4419 // method, since it's in the stream's loop).
4420 session_
->CloseSessionOnError(ERR_CONNECTION_CLOSED
, "Closing session");
4421 data
.CompleteRead();
4422 base::RunLoop().RunUntilIdle();
4423 EXPECT_FALSE(session_
);
4425 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
4427 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4428 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4430 EXPECT_TRUE(delegate1
.send_headers_completed());
4431 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4433 EXPECT_TRUE(delegate2
.send_headers_completed());
4434 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4436 EXPECT_TRUE(data
.AllWriteDataConsumed());
4439 TEST_P(SpdySessionTest
, GoAwayOnSessionFlowControlError
) {
4440 scoped_ptr
<SpdyFrame
> req(
4441 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4442 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
4443 0, GOAWAY_FLOW_CONTROL_ERROR
,
4444 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4445 "the receive window size of 1"));
4446 MockWrite writes
[] = {
4447 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 4),
4450 scoped_ptr
<SpdyFrame
> resp(
4451 spdy_util_
.ConstructSpdyGetSynReply(nullptr, 0, 1));
4452 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4453 MockRead reads
[] = {
4454 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4455 CreateMockRead(*resp
, 2),
4456 CreateMockRead(*body
, 3),
4459 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4460 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4462 CreateNetworkSession();
4463 CreateInsecureSpdySession();
4465 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
4466 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4467 ASSERT_TRUE(spdy_stream
.get() != nullptr);
4468 test::StreamDelegateDoNothing
delegate(spdy_stream
);
4469 spdy_stream
->SetDelegate(&delegate
);
4471 scoped_ptr
<SpdyHeaderBlock
> headers(
4472 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
4473 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4476 base::RunLoop().RunUntilIdle();
4478 // Put session on the edge of overflowing it's recv window.
4479 session_
->session_recv_window_size_
= 1;
4481 // Read response headers & body. Body overflows the session window, and a
4482 // goaway is written.
4483 data
.CompleteRead();
4484 base::RunLoop().RunUntilIdle();
4486 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR
, delegate
.WaitForClose());
4487 EXPECT_FALSE(session_
);
4490 TEST_P(SpdySessionTest
, SplitHeaders
) {
4491 GURL
kStreamUrl("http://www.example.org/foo.dat");
4492 SpdyHeaderBlock headers
;
4493 spdy_util_
.AddUrlToHeaderBlock(kStreamUrl
.spec(), &headers
);
4494 headers
["alpha"] = "beta";
4496 SpdyHeaderBlock request_headers
;
4497 SpdyHeaderBlock response_headers
;
4499 SplitPushedHeadersToRequestAndResponse(
4500 headers
, spdy_util_
.spdy_version(), &request_headers
, &response_headers
);
4502 SpdyHeaderBlock::const_iterator it
= response_headers
.find("alpha");
4503 std::string alpha_val
=
4504 (it
== response_headers
.end()) ? std::string() : it
->second
;
4505 EXPECT_EQ("beta", alpha_val
);
4508 GetUrlFromHeaderBlock(request_headers
, spdy_util_
.spdy_version(), true);
4509 EXPECT_EQ(kStreamUrl
, request_url
);
4512 // Regression. Sorta. Push streams and client streams were sharing a single
4513 // limit for a long time.
4514 TEST_P(SpdySessionTest
, PushedStreamShouldNotCountToClientConcurrencyLimit
) {
4515 SettingsMap new_settings
;
4516 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4517 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, 2);
4518 scoped_ptr
<SpdyFrame
> settings_frame(
4519 spdy_util_
.ConstructSpdySettings(new_settings
));
4520 scoped_ptr
<SpdyFrame
> pushed(spdy_util_
.ConstructSpdyPush(
4521 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4522 MockRead reads
[] = {
4523 CreateMockRead(*settings_frame
, 0),
4524 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4525 CreateMockRead(*pushed
, 4),
4526 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4527 MockRead(ASYNC
, 0, 6),
4530 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
4531 scoped_ptr
<SpdyFrame
> req(
4532 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4533 MockWrite writes
[] = {
4534 CreateMockWrite(*settings_ack
, 1), CreateMockWrite(*req
, 2),
4537 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4538 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4540 CreateNetworkSession();
4541 CreateInsecureSpdySession();
4543 // Read the settings frame.
4544 base::RunLoop().RunUntilIdle();
4546 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4547 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4548 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4549 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4550 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4551 spdy_stream1
->SetDelegate(&delegate1
);
4553 EXPECT_EQ(0u, session_
->num_active_streams());
4554 EXPECT_EQ(1u, session_
->num_created_streams());
4555 EXPECT_EQ(0u, session_
->num_pushed_streams());
4556 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4558 scoped_ptr
<SpdyHeaderBlock
> headers(
4559 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
4560 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4561 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4563 // Run until 1st stream is activated.
4564 EXPECT_EQ(0u, delegate1
.stream_id());
4565 base::RunLoop().RunUntilIdle();
4566 EXPECT_EQ(1u, delegate1
.stream_id());
4567 EXPECT_EQ(1u, session_
->num_active_streams());
4568 EXPECT_EQ(0u, session_
->num_created_streams());
4569 EXPECT_EQ(0u, session_
->num_pushed_streams());
4570 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4572 // Run until pushed stream is created.
4573 data
.CompleteRead();
4574 base::RunLoop().RunUntilIdle();
4575 EXPECT_EQ(2u, session_
->num_active_streams());
4576 EXPECT_EQ(0u, session_
->num_created_streams());
4577 EXPECT_EQ(1u, session_
->num_pushed_streams());
4578 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4580 // Second stream should not be stalled, although we have 2 active streams, but
4581 // one of them is push stream and should not be taken into account when we
4582 // create streams on the client.
4583 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
4584 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4585 EXPECT_TRUE(spdy_stream2
);
4586 EXPECT_EQ(2u, session_
->num_active_streams());
4587 EXPECT_EQ(1u, session_
->num_created_streams());
4588 EXPECT_EQ(1u, session_
->num_pushed_streams());
4589 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4592 data
.CompleteRead();
4593 base::RunLoop().RunUntilIdle();
4594 EXPECT_FALSE(session_
);
4597 TEST_P(SpdySessionTest
, RejectPushedStreamExceedingConcurrencyLimit
) {
4598 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4599 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4600 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
4601 nullptr, 0, 4, 1, "http://www.example.org/b.dat"));
4602 MockRead reads
[] = {
4603 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4604 CreateMockRead(*push_a
, 2),
4605 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4606 CreateMockRead(*push_b
, 4),
4607 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
4608 MockRead(ASYNC
, 0, 7),
4611 scoped_ptr
<SpdyFrame
> req(
4612 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4613 scoped_ptr
<SpdyFrame
> rst(
4614 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4615 MockWrite writes
[] = {
4616 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5),
4619 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4620 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4622 CreateNetworkSession();
4623 CreateInsecureSpdySession();
4624 session_
->set_max_concurrent_pushed_streams(1);
4626 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4627 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4628 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4629 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4630 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4631 spdy_stream1
->SetDelegate(&delegate1
);
4633 EXPECT_EQ(0u, session_
->num_active_streams());
4634 EXPECT_EQ(1u, session_
->num_created_streams());
4635 EXPECT_EQ(0u, session_
->num_pushed_streams());
4636 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4638 scoped_ptr
<SpdyHeaderBlock
> headers(
4639 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
4640 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4641 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4643 // Run until 1st stream is activated.
4644 EXPECT_EQ(0u, delegate1
.stream_id());
4645 base::RunLoop().RunUntilIdle();
4646 EXPECT_EQ(1u, delegate1
.stream_id());
4647 EXPECT_EQ(1u, session_
->num_active_streams());
4648 EXPECT_EQ(0u, session_
->num_created_streams());
4649 EXPECT_EQ(0u, session_
->num_pushed_streams());
4650 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4652 // Run until pushed stream is created.
4653 data
.CompleteRead();
4654 base::RunLoop().RunUntilIdle();
4655 EXPECT_EQ(2u, session_
->num_active_streams());
4656 EXPECT_EQ(0u, session_
->num_created_streams());
4657 EXPECT_EQ(1u, session_
->num_pushed_streams());
4658 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4660 // Reset incoming pushed stream.
4661 data
.CompleteRead();
4662 base::RunLoop().RunUntilIdle();
4663 EXPECT_EQ(2u, session_
->num_active_streams());
4664 EXPECT_EQ(0u, session_
->num_created_streams());
4665 EXPECT_EQ(1u, session_
->num_pushed_streams());
4666 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4669 data
.CompleteRead();
4670 base::RunLoop().RunUntilIdle();
4671 EXPECT_FALSE(session_
);
4674 TEST_P(SpdySessionTest
, IgnoreReservedRemoteStreamsCount
) {
4675 // Streams in reserved remote state exist only in HTTP/2.
4676 if (spdy_util_
.spdy_version() < HTTP2
)
4679 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4680 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4681 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4682 spdy_util_
.AddUrlToHeaderBlock("http://www.example.org/b.dat",
4683 push_headers
.get());
4684 scoped_ptr
<SpdyFrame
> push_b(
4685 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 4, 1));
4686 scoped_ptr
<SpdyFrame
> headers_b(
4687 spdy_util_
.ConstructSpdyPushHeaders(4, nullptr, 0));
4688 MockRead reads
[] = {
4689 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4690 CreateMockRead(*push_a
, 2),
4691 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4692 CreateMockRead(*push_b
, 4),
4693 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
4694 CreateMockRead(*headers_b
, 6),
4695 MockRead(ASYNC
, ERR_IO_PENDING
, 8),
4696 MockRead(ASYNC
, 0, 9),
4699 scoped_ptr
<SpdyFrame
> req(
4700 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4701 scoped_ptr
<SpdyFrame
> rst(
4702 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4703 MockWrite writes
[] = {
4704 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 7),
4707 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4708 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4710 CreateNetworkSession();
4711 CreateInsecureSpdySession();
4712 session_
->set_max_concurrent_pushed_streams(1);
4714 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4715 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4716 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4717 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4718 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4719 spdy_stream1
->SetDelegate(&delegate1
);
4721 EXPECT_EQ(0u, session_
->num_active_streams());
4722 EXPECT_EQ(1u, session_
->num_created_streams());
4723 EXPECT_EQ(0u, session_
->num_pushed_streams());
4724 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4726 scoped_ptr
<SpdyHeaderBlock
> headers(
4727 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
4728 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4729 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4731 // Run until 1st stream is activated.
4732 EXPECT_EQ(0u, delegate1
.stream_id());
4733 base::RunLoop().RunUntilIdle();
4734 EXPECT_EQ(1u, delegate1
.stream_id());
4735 EXPECT_EQ(1u, session_
->num_active_streams());
4736 EXPECT_EQ(0u, session_
->num_created_streams());
4737 EXPECT_EQ(0u, session_
->num_pushed_streams());
4738 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4740 // Run until pushed stream is created.
4741 data
.CompleteRead();
4742 base::RunLoop().RunUntilIdle();
4743 EXPECT_EQ(2u, session_
->num_active_streams());
4744 EXPECT_EQ(0u, session_
->num_created_streams());
4745 EXPECT_EQ(1u, session_
->num_pushed_streams());
4746 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4748 // Accept promised stream. It should not count towards pushed stream limit.
4749 data
.CompleteRead();
4750 base::RunLoop().RunUntilIdle();
4751 EXPECT_EQ(3u, session_
->num_active_streams());
4752 EXPECT_EQ(0u, session_
->num_created_streams());
4753 EXPECT_EQ(2u, session_
->num_pushed_streams());
4754 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4756 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4757 // while we accept only one.
4758 data
.CompleteRead();
4759 base::RunLoop().RunUntilIdle();
4760 EXPECT_EQ(2u, session_
->num_active_streams());
4761 EXPECT_EQ(0u, session_
->num_created_streams());
4762 EXPECT_EQ(1u, session_
->num_pushed_streams());
4763 EXPECT_EQ(1u, session_
->num_active_pushed_streams());
4766 data
.CompleteRead();
4767 base::RunLoop().RunUntilIdle();
4768 EXPECT_FALSE(session_
);
4771 TEST_P(SpdySessionTest
, CancelReservedStreamOnHeadersReceived
) {
4772 // Streams in reserved remote state exist only in HTTP/2.
4773 if (spdy_util_
.spdy_version() < HTTP2
)
4776 const char kPushedUrl
[] = "http://www.example.org/a.dat";
4777 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4778 spdy_util_
.AddUrlToHeaderBlock(kPushedUrl
, push_headers
.get());
4779 scoped_ptr
<SpdyFrame
> push_promise(
4780 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 2, 1));
4781 scoped_ptr
<SpdyFrame
> headers_frame(
4782 spdy_util_
.ConstructSpdyPushHeaders(2, nullptr, 0));
4783 MockRead reads
[] = {
4784 MockRead(ASYNC
, ERR_IO_PENDING
, 1),
4785 CreateMockRead(*push_promise
, 2),
4786 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
4787 CreateMockRead(*headers_frame
, 4),
4788 MockRead(ASYNC
, ERR_IO_PENDING
, 6),
4789 MockRead(ASYNC
, 0, 7),
4792 scoped_ptr
<SpdyFrame
> req(
4793 spdy_util_
.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST
, true));
4794 scoped_ptr
<SpdyFrame
> rst(
4795 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
4796 MockWrite writes
[] = {
4797 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 5),
4800 SequencedSocketData
data(reads
, arraysize(reads
), writes
, arraysize(writes
));
4801 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4803 CreateNetworkSession();
4804 CreateInsecureSpdySession();
4806 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4807 SPDY_REQUEST_RESPONSE_STREAM
, session_
, test_url_
, LOWEST
, BoundNetLog());
4808 ASSERT_TRUE(spdy_stream1
.get() != nullptr);
4809 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4810 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4811 spdy_stream1
->SetDelegate(&delegate1
);
4813 EXPECT_EQ(0u, session_
->num_active_streams());
4814 EXPECT_EQ(1u, session_
->num_created_streams());
4815 EXPECT_EQ(0u, session_
->num_pushed_streams());
4816 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4818 scoped_ptr
<SpdyHeaderBlock
> headers(
4819 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
4820 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4821 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4823 // Run until 1st stream is activated.
4824 EXPECT_EQ(0u, delegate1
.stream_id());
4825 base::RunLoop().RunUntilIdle();
4826 EXPECT_EQ(1u, delegate1
.stream_id());
4827 EXPECT_EQ(1u, session_
->num_active_streams());
4828 EXPECT_EQ(0u, session_
->num_created_streams());
4829 EXPECT_EQ(0u, session_
->num_pushed_streams());
4830 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4832 // Run until pushed stream is created.
4833 data
.CompleteRead();
4834 base::RunLoop().RunUntilIdle();
4835 EXPECT_EQ(2u, session_
->num_active_streams());
4836 EXPECT_EQ(0u, session_
->num_created_streams());
4837 EXPECT_EQ(1u, session_
->num_pushed_streams());
4838 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4840 base::WeakPtr
<SpdyStream
> pushed_stream
;
4842 session_
->GetPushStream(GURL(kPushedUrl
), &pushed_stream
, BoundNetLog());
4844 ASSERT_TRUE(pushed_stream
.get() != nullptr);
4845 test::StreamDelegateCloseOnHeaders
delegate2(pushed_stream
);
4846 pushed_stream
->SetDelegate(&delegate2
);
4848 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4849 // that all our counters are in consistent state.
4850 data
.CompleteRead();
4851 base::RunLoop().RunUntilIdle();
4852 EXPECT_EQ(1u, session_
->num_active_streams());
4853 EXPECT_EQ(0u, session_
->num_created_streams());
4854 EXPECT_EQ(0u, session_
->num_pushed_streams());
4855 EXPECT_EQ(0u, session_
->num_active_pushed_streams());
4858 data
.CompleteRead();
4859 base::RunLoop().RunUntilIdle();
4860 EXPECT_TRUE(data
.AllWriteDataConsumed());
4861 EXPECT_TRUE(data
.AllReadDataConsumed());
4864 TEST_P(SpdySessionTest
, RejectInvalidUnknownFrames
) {
4865 session_deps_
.host_resolver
->set_synchronous_mode(true);
4867 MockRead reads
[] = {
4868 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
4871 StaticSocketDataProvider
data(reads
, arraysize(reads
), nullptr, 0);
4872 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4874 CreateNetworkSession();
4875 CreateInsecureSpdySession();
4877 session_
->stream_hi_water_mark_
= 5;
4878 // Low client (odd) ids are fine.
4879 EXPECT_TRUE(session_
->OnUnknownFrame(3, 0));
4880 // Client id exceeding watermark.
4881 EXPECT_FALSE(session_
->OnUnknownFrame(9, 0));
4883 session_
->last_accepted_push_stream_id_
= 6;
4884 // Low server (even) ids are fine.
4885 EXPECT_TRUE(session_
->OnUnknownFrame(2, 0));
4886 // Server id exceeding last accepted id.
4887 EXPECT_FALSE(session_
->OnUnknownFrame(8, 0));
4890 TEST(MapFramerErrorToProtocolError
, MapsValues
) {
4892 SPDY_ERROR_INVALID_CONTROL_FRAME
,
4893 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4895 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS
,
4896 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
4898 SPDY_ERROR_GOAWAY_FRAME_CORRUPT
,
4899 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT
));
4900 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME
,
4901 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME
));
4904 TEST(MapFramerErrorToNetError
, MapsValue
) {
4905 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR
,
4906 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4907 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
4908 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE
));
4909 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
4910 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE
));
4912 ERR_SPDY_FRAME_SIZE_ERROR
,
4913 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
));
4916 TEST(MapRstStreamStatusToProtocolError
, MapsValues
) {
4917 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR
,
4918 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR
));
4919 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR
,
4920 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR
));
4921 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM
,
4922 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM
));
4923 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY
,
4924 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY
));
4925 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED
,
4926 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED
));
4929 TEST(MapNetErrorToGoAwayStatus
, MapsValue
) {
4930 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY
,
4931 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
));
4932 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR
,
4933 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR
));
4934 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
,
4935 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR
));
4936 CHECK_EQ(GOAWAY_COMPRESSION_ERROR
,
4937 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR
));
4938 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR
,
4939 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR
));
4940 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED
));
4943 TEST(CanPoolTest
, CanPool
) {
4944 // Load a cert that is valid for:
4949 TransportSecurityState tss
;
4951 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
4952 "spdy_pooling.pem");
4954 EXPECT_TRUE(SpdySession::CanPool(
4955 &tss
, ssl_info
, "www.example.org", "www.example.org"));
4956 EXPECT_TRUE(SpdySession::CanPool(
4957 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
4958 EXPECT_TRUE(SpdySession::CanPool(
4959 &tss
, ssl_info
, "www.example.org", "mail.example.com"));
4960 EXPECT_FALSE(SpdySession::CanPool(
4961 &tss
, ssl_info
, "www.example.org", "mail.google.com"));
4964 TEST(CanPoolTest
, CanNotPoolWithCertErrors
) {
4965 // Load a cert that is valid for:
4970 TransportSecurityState tss
;
4972 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
4973 "spdy_pooling.pem");
4974 ssl_info
.cert_status
= CERT_STATUS_REVOKED
;
4976 EXPECT_FALSE(SpdySession::CanPool(
4977 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
4980 TEST(CanPoolTest
, CanNotPoolWithClientCerts
) {
4981 // Load a cert that is valid for:
4986 TransportSecurityState tss
;
4988 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
4989 "spdy_pooling.pem");
4990 ssl_info
.client_cert_sent
= true;
4992 EXPECT_FALSE(SpdySession::CanPool(
4993 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
4996 TEST(CanPoolTest
, CanNotPoolAcrossETLDsWithChannelID
) {
4997 // Load a cert that is valid for:
5002 TransportSecurityState tss
;
5004 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5005 "spdy_pooling.pem");
5006 ssl_info
.channel_id_sent
= true;
5008 EXPECT_TRUE(SpdySession::CanPool(
5009 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5010 EXPECT_FALSE(SpdySession::CanPool(
5011 &tss
, ssl_info
, "www.example.org", "www.example.com"));
5014 TEST(CanPoolTest
, CanNotPoolWithBadPins
) {
5015 uint8 primary_pin
= 1;
5016 uint8 backup_pin
= 2;
5018 TransportSecurityState tss
;
5019 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5022 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5023 "spdy_pooling.pem");
5024 ssl_info
.is_issued_by_known_root
= true;
5025 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(bad_pin
));
5027 EXPECT_FALSE(SpdySession::CanPool(
5028 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5031 TEST(CanPoolTest
, CanPoolWithAcceptablePins
) {
5032 uint8 primary_pin
= 1;
5033 uint8 backup_pin
= 2;
5034 TransportSecurityState tss
;
5035 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5038 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5039 "spdy_pooling.pem");
5040 ssl_info
.is_issued_by_known_root
= true;
5041 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(primary_pin
));
5043 EXPECT_TRUE(SpdySession::CanPool(
5044 &tss
, ssl_info
, "www.example.org", "mail.example.org"));