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/net_log_unittest.h"
16 #include "net/base/request_priority.h"
17 #include "net/base/test_data_directory.h"
18 #include "net/base/test_data_stream.h"
19 #include "net/socket/client_socket_pool_manager.h"
20 #include "net/socket/next_proto.h"
21 #include "net/socket/socket_test_util.h"
22 #include "net/spdy/spdy_http_utils.h"
23 #include "net/spdy/spdy_session_pool.h"
24 #include "net/spdy/spdy_session_test_util.h"
25 #include "net/spdy/spdy_stream.h"
26 #include "net/spdy/spdy_stream_test_util.h"
27 #include "net/spdy/spdy_test_util_common.h"
28 #include "net/spdy/spdy_test_utils.h"
29 #include "net/test/cert_test_util.h"
30 #include "testing/platform_test.h"
36 static const char kTestUrl
[] = "http://www.example.org/";
37 static const char kTestHost
[] = "www.example.org";
38 static const int kTestPort
= 80;
40 const char kBodyData
[] = "Body data";
41 const size_t kBodyDataSize
= arraysize(kBodyData
);
42 const base::StringPiece
kBodyDataStringPiece(kBodyData
, kBodyDataSize
);
44 static base::TimeDelta g_time_delta
;
45 base::TimeTicks
TheNearFuture() {
46 return base::TimeTicks::Now() + g_time_delta
;
51 class SpdySessionTest
: public PlatformTest
,
52 public ::testing::WithParamInterface
<NextProto
> {
54 // Functions used with RunResumeAfterUnstallTest().
56 void StallSessionOnly(SpdySession
* session
, SpdyStream
* stream
) {
57 StallSessionSend(session
);
60 void StallStreamOnly(SpdySession
* session
, SpdyStream
* stream
) {
61 StallStreamSend(stream
);
64 void StallSessionStream(SpdySession
* session
, SpdyStream
* stream
) {
65 StallSessionSend(session
);
66 StallStreamSend(stream
);
69 void StallStreamSession(SpdySession
* session
, SpdyStream
* stream
) {
70 StallStreamSend(stream
);
71 StallSessionSend(session
);
74 void UnstallSessionOnly(SpdySession
* session
,
76 int32 delta_window_size
) {
77 UnstallSessionSend(session
, delta_window_size
);
80 void UnstallStreamOnly(SpdySession
* session
,
82 int32 delta_window_size
) {
83 UnstallStreamSend(stream
, delta_window_size
);
86 void UnstallSessionStream(SpdySession
* session
,
88 int32 delta_window_size
) {
89 UnstallSessionSend(session
, delta_window_size
);
90 UnstallStreamSend(stream
, delta_window_size
);
93 void UnstallStreamSession(SpdySession
* session
,
95 int32 delta_window_size
) {
96 UnstallStreamSend(stream
, delta_window_size
);
97 UnstallSessionSend(session
, delta_window_size
);
102 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
103 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
104 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
105 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
106 spdy_util_(GetParam()),
107 session_deps_(GetParam()),
108 spdy_session_pool_(NULL
),
110 test_host_port_pair_(kTestHost
, kTestPort
),
111 key_(test_host_port_pair_
, ProxyServer::Direct(),
112 PRIVACY_MODE_DISABLED
) {
115 virtual ~SpdySessionTest() {
116 // Important to restore the per-pool limit first, since the pool limit must
117 // always be greater than group limit, and the tests reduce both limits.
118 ClientSocketPoolManager::set_max_sockets_per_pool(
119 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
120 ClientSocketPoolManager::set_max_sockets_per_group(
121 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
124 void SetUp() override
{ g_time_delta
= base::TimeDelta(); }
126 void CreateDeterministicNetworkSession() {
128 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
);
129 spdy_session_pool_
= http_session_
->spdy_session_pool();
132 void CreateNetworkSession() {
134 SpdySessionDependencies::SpdyCreateSession(&session_deps_
);
135 spdy_session_pool_
= http_session_
->spdy_session_pool();
138 void StallSessionSend(SpdySession
* session
) {
139 // Reduce the send window size to 0 to stall.
140 while (session
->session_send_window_size_
> 0) {
141 session
->DecreaseSendWindowSize(
142 std::min(kMaxSpdyFrameChunkSize
, session
->session_send_window_size_
));
146 void UnstallSessionSend(SpdySession
* session
, int32 delta_window_size
) {
147 session
->IncreaseSendWindowSize(delta_window_size
);
150 void StallStreamSend(SpdyStream
* stream
) {
151 // Reduce the send window size to 0 to stall.
152 while (stream
->send_window_size() > 0) {
153 stream
->DecreaseSendWindowSize(
154 std::min(kMaxSpdyFrameChunkSize
, stream
->send_window_size()));
158 void UnstallStreamSend(SpdyStream
* stream
, int32 delta_window_size
) {
159 stream
->IncreaseSendWindowSize(delta_window_size
);
162 void RunResumeAfterUnstallTest(
163 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
164 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
167 // Original socket limits. Some tests set these. Safest to always restore
168 // them once each test has been run.
169 int old_max_group_sockets_
;
170 int old_max_pool_sockets_
;
172 SpdyTestUtil spdy_util_
;
173 SpdySessionDependencies session_deps_
;
174 scoped_refptr
<HttpNetworkSession
> http_session_
;
175 SpdySessionPool
* spdy_session_pool_
;
177 HostPortPair test_host_port_pair_
;
181 INSTANTIATE_TEST_CASE_P(
184 testing::Values(kProtoSPDY31
, kProtoSPDY4_14
, kProtoSPDY4_15
));
186 // Try to create a SPDY session that will fail during
187 // initialization. Nothing should blow up.
188 TEST_P(SpdySessionTest
, InitialReadError
) {
189 CreateDeterministicNetworkSession();
191 base::WeakPtr
<SpdySession
> session
= TryCreateFakeSpdySessionExpectingFailure(
192 spdy_session_pool_
, key_
, ERR_CONNECTION_CLOSED
);
193 EXPECT_TRUE(session
);
195 base::RunLoop().RunUntilIdle();
196 EXPECT_FALSE(session
);
201 // A helper class that vends a callback that, when fired, destroys a
202 // given SpdyStreamRequest.
203 class StreamRequestDestroyingCallback
: public TestCompletionCallbackBase
{
205 StreamRequestDestroyingCallback() {}
207 ~StreamRequestDestroyingCallback() override
{}
209 void SetRequestToDestroy(scoped_ptr
<SpdyStreamRequest
> request
) {
210 request_
= request
.Pass();
213 CompletionCallback
MakeCallback() {
214 return base::Bind(&StreamRequestDestroyingCallback::OnComplete
,
215 base::Unretained(this));
219 void OnComplete(int result
) {
224 scoped_ptr
<SpdyStreamRequest
> request_
;
229 // Request kInitialMaxConcurrentStreams streams. Request two more
230 // streams, but have the callback for one destroy the second stream
231 // request. Close the session. Nothing should blow up. This is a
232 // regression test for http://crbug.com/250841 .
233 TEST_P(SpdySessionTest
, PendingStreamCancellingAnother
) {
234 session_deps_
.host_resolver
->set_synchronous_mode(true);
236 MockRead reads
[] = {MockRead(ASYNC
, 0, 0), };
238 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
239 MockConnect
connect_data(SYNCHRONOUS
, OK
);
240 data
.set_connect_data(connect_data
);
241 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
243 CreateDeterministicNetworkSession();
245 base::WeakPtr
<SpdySession
> session
=
246 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
248 // Create the maximum number of concurrent streams.
249 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
250 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
251 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
, BoundNetLog());
252 ASSERT_TRUE(spdy_stream
!= NULL
);
255 SpdyStreamRequest request1
;
256 scoped_ptr
<SpdyStreamRequest
> request2(new SpdyStreamRequest
);
258 StreamRequestDestroyingCallback callback1
;
259 ASSERT_EQ(ERR_IO_PENDING
,
260 request1
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
,
265 callback1
.MakeCallback()));
267 // |callback2| is never called.
268 TestCompletionCallback callback2
;
269 ASSERT_EQ(ERR_IO_PENDING
,
270 request2
->StartRequest(SPDY_BIDIRECTIONAL_STREAM
,
275 callback2
.callback()));
277 callback1
.SetRequestToDestroy(request2
.Pass());
279 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
281 EXPECT_EQ(ERR_ABORTED
, callback1
.WaitForResult());
284 // A session receiving a GOAWAY frame with no active streams should close.
285 TEST_P(SpdySessionTest
, GoAwayWithNoActiveStreams
) {
286 session_deps_
.host_resolver
->set_synchronous_mode(true);
288 MockConnect
connect_data(SYNCHRONOUS
, OK
);
289 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
291 CreateMockRead(*goaway
, 0),
293 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
294 data
.set_connect_data(connect_data
);
295 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
297 CreateDeterministicNetworkSession();
299 base::WeakPtr
<SpdySession
> session
=
300 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
302 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
304 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
306 // Read and process the GOAWAY frame.
308 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
309 base::RunLoop().RunUntilIdle();
310 EXPECT_TRUE(session
== NULL
);
313 // A session receiving a GOAWAY frame immediately with no active
314 // streams should then close.
315 TEST_P(SpdySessionTest
, GoAwayImmediatelyWithNoActiveStreams
) {
316 session_deps_
.host_resolver
->set_synchronous_mode(true);
318 MockConnect
connect_data(SYNCHRONOUS
, OK
);
319 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
321 CreateMockRead(*goaway
, 0, SYNCHRONOUS
),
323 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
324 data
.set_connect_data(connect_data
);
325 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
327 CreateDeterministicNetworkSession();
331 base::WeakPtr
<SpdySession
> session
=
332 TryCreateInsecureSpdySessionExpectingFailure(
333 http_session_
, key_
, ERR_CONNECTION_CLOSED
, BoundNetLog());
334 base::RunLoop().RunUntilIdle();
336 EXPECT_FALSE(session
);
337 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
340 // A session receiving a GOAWAY frame with active streams should close
341 // when the last active stream is closed.
342 TEST_P(SpdySessionTest
, GoAwayWithActiveStreams
) {
343 session_deps_
.host_resolver
->set_synchronous_mode(true);
345 MockConnect
connect_data(SYNCHRONOUS
, OK
);
346 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
348 CreateMockRead(*goaway
, 2),
349 MockRead(ASYNC
, 0, 3) // EOF
351 scoped_ptr
<SpdyFrame
> req1(
352 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
353 scoped_ptr
<SpdyFrame
> req2(
354 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
355 MockWrite writes
[] = {
356 CreateMockWrite(*req1
, 0),
357 CreateMockWrite(*req2
, 1),
359 DeterministicSocketData
data(reads
, arraysize(reads
),
360 writes
, arraysize(writes
));
361 data
.set_connect_data(connect_data
);
362 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
364 CreateDeterministicNetworkSession();
366 base::WeakPtr
<SpdySession
> session
=
367 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
369 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
371 GURL
url(kDefaultURL
);
372 base::WeakPtr
<SpdyStream
> spdy_stream1
=
373 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
374 session
, url
, MEDIUM
, BoundNetLog());
375 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
376 spdy_stream1
->SetDelegate(&delegate1
);
378 base::WeakPtr
<SpdyStream
> spdy_stream2
=
379 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
380 session
, url
, MEDIUM
, BoundNetLog());
381 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
382 spdy_stream2
->SetDelegate(&delegate2
);
384 scoped_ptr
<SpdyHeaderBlock
> headers(
385 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
386 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
388 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
389 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
390 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
391 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
395 EXPECT_EQ(1u, spdy_stream1
->stream_id());
396 EXPECT_EQ(3u, spdy_stream2
->stream_id());
398 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
400 // Read and process the GOAWAY frame.
403 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
405 EXPECT_FALSE(session
->IsStreamActive(3));
406 EXPECT_EQ(NULL
, spdy_stream2
.get());
407 EXPECT_TRUE(session
->IsStreamActive(1));
409 EXPECT_TRUE(session
->IsGoingAway());
411 // Should close the session.
412 spdy_stream1
->Close();
413 EXPECT_EQ(NULL
, spdy_stream1
.get());
415 base::MessageLoop::current()->RunUntilIdle();
416 EXPECT_TRUE(session
== NULL
);
419 // Have a session receive two GOAWAY frames, with the last one causing
420 // the last active stream to be closed. The session should then be
421 // closed after the second GOAWAY frame.
422 TEST_P(SpdySessionTest
, GoAwayTwice
) {
423 session_deps_
.host_resolver
->set_synchronous_mode(true);
425 MockConnect
connect_data(SYNCHRONOUS
, OK
);
426 scoped_ptr
<SpdyFrame
> goaway1(spdy_util_
.ConstructSpdyGoAway(1));
427 scoped_ptr
<SpdyFrame
> goaway2(spdy_util_
.ConstructSpdyGoAway(0));
429 CreateMockRead(*goaway1
, 2),
430 CreateMockRead(*goaway2
, 3),
431 MockRead(ASYNC
, 0, 4) // EOF
433 scoped_ptr
<SpdyFrame
> req1(
434 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
435 scoped_ptr
<SpdyFrame
> req2(
436 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
437 MockWrite writes
[] = {
438 CreateMockWrite(*req1
, 0),
439 CreateMockWrite(*req2
, 1),
441 DeterministicSocketData
data(reads
, arraysize(reads
),
442 writes
, arraysize(writes
));
443 data
.set_connect_data(connect_data
);
444 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
446 CreateDeterministicNetworkSession();
448 base::WeakPtr
<SpdySession
> session
=
449 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
451 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
453 GURL
url(kDefaultURL
);
454 base::WeakPtr
<SpdyStream
> spdy_stream1
=
455 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
456 session
, url
, MEDIUM
, BoundNetLog());
457 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
458 spdy_stream1
->SetDelegate(&delegate1
);
460 base::WeakPtr
<SpdyStream
> spdy_stream2
=
461 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
462 session
, url
, MEDIUM
, BoundNetLog());
463 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
464 spdy_stream2
->SetDelegate(&delegate2
);
466 scoped_ptr
<SpdyHeaderBlock
> headers(
467 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
468 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
470 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
471 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
472 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
473 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
477 EXPECT_EQ(1u, spdy_stream1
->stream_id());
478 EXPECT_EQ(3u, spdy_stream2
->stream_id());
480 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
482 // Read and process the first GOAWAY frame.
485 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
487 EXPECT_FALSE(session
->IsStreamActive(3));
488 EXPECT_EQ(NULL
, spdy_stream2
.get());
489 EXPECT_TRUE(session
->IsStreamActive(1));
490 EXPECT_TRUE(session
->IsGoingAway());
492 // Read and process the second GOAWAY frame, which should close the
495 base::MessageLoop::current()->RunUntilIdle();
496 EXPECT_TRUE(session
== NULL
);
499 // Have a session with active streams receive a GOAWAY frame and then
500 // close it. It should handle the close properly (i.e., not try to
501 // make itself unavailable in its pool twice).
502 TEST_P(SpdySessionTest
, GoAwayWithActiveStreamsThenClose
) {
503 session_deps_
.host_resolver
->set_synchronous_mode(true);
505 MockConnect
connect_data(SYNCHRONOUS
, OK
);
506 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
508 CreateMockRead(*goaway
, 2),
509 MockRead(ASYNC
, 0, 3) // EOF
511 scoped_ptr
<SpdyFrame
> req1(
512 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
513 scoped_ptr
<SpdyFrame
> req2(
514 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
515 MockWrite writes
[] = {
516 CreateMockWrite(*req1
, 0),
517 CreateMockWrite(*req2
, 1),
519 DeterministicSocketData
data(reads
, arraysize(reads
),
520 writes
, arraysize(writes
));
521 data
.set_connect_data(connect_data
);
522 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
524 CreateDeterministicNetworkSession();
526 base::WeakPtr
<SpdySession
> session
=
527 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
529 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
531 GURL
url(kDefaultURL
);
532 base::WeakPtr
<SpdyStream
> spdy_stream1
=
533 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
534 session
, url
, MEDIUM
, BoundNetLog());
535 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
536 spdy_stream1
->SetDelegate(&delegate1
);
538 base::WeakPtr
<SpdyStream
> spdy_stream2
=
539 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
540 session
, url
, MEDIUM
, BoundNetLog());
541 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
542 spdy_stream2
->SetDelegate(&delegate2
);
544 scoped_ptr
<SpdyHeaderBlock
> headers(
545 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
546 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
548 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
549 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
550 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
551 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
555 EXPECT_EQ(1u, spdy_stream1
->stream_id());
556 EXPECT_EQ(3u, spdy_stream2
->stream_id());
558 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
560 // Read and process the GOAWAY frame.
563 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
565 EXPECT_FALSE(session
->IsStreamActive(3));
566 EXPECT_EQ(NULL
, spdy_stream2
.get());
567 EXPECT_TRUE(session
->IsStreamActive(1));
568 EXPECT_TRUE(session
->IsGoingAway());
570 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
571 EXPECT_EQ(NULL
, spdy_stream1
.get());
573 base::MessageLoop::current()->RunUntilIdle();
574 EXPECT_TRUE(session
== NULL
);
577 // Process a joint read buffer which causes the session to begin draining, and
578 // then processes a GOAWAY. The session should gracefully drain. Regression test
579 // for crbug.com/379469
580 TEST_P(SpdySessionTest
, GoAwayWhileDraining
) {
581 session_deps_
.host_resolver
->set_synchronous_mode(true);
583 scoped_ptr
<SpdyFrame
> req(
584 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
585 MockWrite writes
[] = {
586 CreateMockWrite(*req
, 0),
589 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
590 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
591 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
592 size_t joint_size
= goaway
->size() * 2 + body
->size();
594 // Compose interleaved |goaway| and |body| frames into a single read.
595 scoped_ptr
<char[]> buffer(new char[joint_size
]);
598 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
599 out
+= goaway
->size();
600 memcpy(&buffer
[out
], body
->data(), body
->size());
602 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
603 out
+= goaway
->size();
604 ASSERT_EQ(out
, joint_size
);
606 SpdyFrame
joint_frames(buffer
.get(), joint_size
, false);
609 CreateMockRead(*resp
, 1), CreateMockRead(joint_frames
, 2),
610 MockRead(ASYNC
, 0, 3) // EOF
613 MockConnect
connect_data(SYNCHRONOUS
, OK
);
614 DeterministicSocketData
data(
615 reads
, arraysize(reads
), writes
, arraysize(writes
));
616 data
.set_connect_data(connect_data
);
617 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
619 CreateDeterministicNetworkSession();
620 base::WeakPtr
<SpdySession
> session
=
621 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
623 GURL
url(kDefaultURL
);
624 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
625 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
626 test::StreamDelegateDoNothing
delegate(spdy_stream
);
627 spdy_stream
->SetDelegate(&delegate
);
629 scoped_ptr
<SpdyHeaderBlock
> headers(
630 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
631 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
632 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
635 base::MessageLoop::current()->RunUntilIdle();
637 // Stream and session closed gracefully.
638 EXPECT_TRUE(delegate
.StreamIsClosed());
639 EXPECT_EQ(OK
, delegate
.WaitForClose());
640 EXPECT_EQ(kUploadData
, delegate
.TakeReceivedData());
641 EXPECT_TRUE(session
== NULL
);
644 // Try to create a stream after receiving a GOAWAY frame. It should
646 TEST_P(SpdySessionTest
, CreateStreamAfterGoAway
) {
647 session_deps_
.host_resolver
->set_synchronous_mode(true);
649 MockConnect
connect_data(SYNCHRONOUS
, OK
);
650 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
652 CreateMockRead(*goaway
, 1),
653 MockRead(ASYNC
, 0, 2) // EOF
655 scoped_ptr
<SpdyFrame
> req(
656 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
657 MockWrite writes
[] = {
658 CreateMockWrite(*req
, 0),
660 DeterministicSocketData
data(reads
, arraysize(reads
),
661 writes
, arraysize(writes
));
662 data
.set_connect_data(connect_data
);
663 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
665 CreateDeterministicNetworkSession();
667 base::WeakPtr
<SpdySession
> session
=
668 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
670 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
672 GURL
url(kDefaultURL
);
673 base::WeakPtr
<SpdyStream
> spdy_stream
=
674 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
675 session
, url
, MEDIUM
, BoundNetLog());
676 test::StreamDelegateDoNothing
delegate(spdy_stream
);
677 spdy_stream
->SetDelegate(&delegate
);
679 scoped_ptr
<SpdyHeaderBlock
> headers(
680 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
681 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
682 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
686 EXPECT_EQ(1u, spdy_stream
->stream_id());
688 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
690 // Read and process the GOAWAY frame.
693 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
694 EXPECT_TRUE(session
->IsStreamActive(1));
696 SpdyStreamRequest stream_request
;
697 int rv
= stream_request
.StartRequest(
698 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog(),
699 CompletionCallback());
700 EXPECT_EQ(ERR_FAILED
, rv
);
702 // Read and process EOF.
705 EXPECT_TRUE(session
== NULL
);
708 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
709 // the stream being refused.
710 TEST_P(SpdySessionTest
, SynStreamAfterGoAway
) {
711 session_deps_
.host_resolver
->set_synchronous_mode(true);
713 MockConnect
connect_data(SYNCHRONOUS
, OK
);
714 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
715 scoped_ptr
<SpdyFrame
>
716 push(spdy_util_
.ConstructSpdyPush(NULL
, 0, 2, 1, kDefaultURL
));
718 CreateMockRead(*goaway
, 1),
719 CreateMockRead(*push
, 2),
720 MockRead(ASYNC
, 0, 4) // EOF
722 scoped_ptr
<SpdyFrame
> req(
723 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
724 scoped_ptr
<SpdyFrame
> rst(
725 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
726 MockWrite writes
[] = {
727 CreateMockWrite(*req
, 0),
728 CreateMockWrite(*rst
, 3)
730 DeterministicSocketData
data(reads
, arraysize(reads
),
731 writes
, arraysize(writes
));
732 data
.set_connect_data(connect_data
);
733 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
735 CreateDeterministicNetworkSession();
737 base::WeakPtr
<SpdySession
> session
=
738 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
740 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
742 GURL
url(kDefaultURL
);
743 base::WeakPtr
<SpdyStream
> spdy_stream
=
744 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
745 session
, url
, MEDIUM
, BoundNetLog());
746 test::StreamDelegateDoNothing
delegate(spdy_stream
);
747 spdy_stream
->SetDelegate(&delegate
);
749 scoped_ptr
<SpdyHeaderBlock
> headers(
750 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
751 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
752 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
756 EXPECT_EQ(1u, spdy_stream
->stream_id());
758 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
760 // Read and process the GOAWAY frame.
763 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
764 EXPECT_TRUE(session
->IsStreamActive(1));
766 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
769 base::MessageLoop::current()->RunUntilIdle();
770 EXPECT_TRUE(session
== NULL
);
773 // A session observing a network change with active streams should close
774 // when the last active stream is closed.
775 TEST_P(SpdySessionTest
, NetworkChangeWithActiveStreams
) {
776 session_deps_
.host_resolver
->set_synchronous_mode(true);
778 MockConnect
connect_data(SYNCHRONOUS
, OK
);
780 MockRead(ASYNC
, 0, 1) // EOF
782 scoped_ptr
<SpdyFrame
> req1(
783 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
784 MockWrite writes
[] = {
785 CreateMockWrite(*req1
, 0),
787 DeterministicSocketData
data(reads
, arraysize(reads
),
788 writes
, arraysize(writes
));
789 data
.set_connect_data(connect_data
);
790 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
792 CreateDeterministicNetworkSession();
794 base::WeakPtr
<SpdySession
> session
=
795 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
797 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
799 base::WeakPtr
<SpdyStream
> spdy_stream
=
800 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
, session
,
801 GURL(kDefaultURL
), MEDIUM
, BoundNetLog());
802 test::StreamDelegateDoNothing
delegate(spdy_stream
);
803 spdy_stream
->SetDelegate(&delegate
);
805 scoped_ptr
<SpdyHeaderBlock
> headers(
806 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
808 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
809 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
813 EXPECT_EQ(1u, spdy_stream
->stream_id());
815 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
817 spdy_session_pool_
->OnIPAddressChanged();
819 // The SpdySessionPool behavior differs based on how the OSs reacts to
820 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
821 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
822 // For OSs where the TCP connections will close upon relevant network
823 // changes, SpdySessionPool doesn't need to force them to close, so in these
824 // cases verify the session has become unavailable but remains open and the
825 // pre-existing stream is still active.
826 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
828 EXPECT_TRUE(session
->IsGoingAway());
830 EXPECT_TRUE(session
->IsStreamActive(1));
832 // Should close the session.
833 spdy_stream
->Close();
835 EXPECT_EQ(NULL
, spdy_stream
.get());
837 base::MessageLoop::current()->RunUntilIdle();
838 EXPECT_TRUE(session
== NULL
);
841 TEST_P(SpdySessionTest
, ClientPing
) {
842 session_deps_
.enable_ping
= true;
843 session_deps_
.host_resolver
->set_synchronous_mode(true);
845 MockConnect
connect_data(SYNCHRONOUS
, OK
);
846 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(1, true));
848 CreateMockRead(*read_ping
, 1),
849 MockRead(ASYNC
, 0, 0, 2) // EOF
851 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
852 MockWrite writes
[] = {
853 CreateMockWrite(*write_ping
, 0),
855 DeterministicSocketData
data(
856 reads
, arraysize(reads
), writes
, arraysize(writes
));
857 data
.set_connect_data(connect_data
);
858 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
860 CreateDeterministicNetworkSession();
862 base::WeakPtr
<SpdySession
> session
=
863 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
865 base::WeakPtr
<SpdyStream
> spdy_stream1
=
866 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
867 session
, test_url_
, MEDIUM
, BoundNetLog());
868 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
869 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
870 spdy_stream1
->SetDelegate(&delegate
);
872 base::TimeTicks before_ping_time
= base::TimeTicks::Now();
874 session
->set_connection_at_risk_of_loss_time(
875 base::TimeDelta::FromSeconds(-1));
876 session
->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
878 session
->SendPrefacePingIfNoneInFlight();
882 session
->CheckPingStatus(before_ping_time
);
884 EXPECT_EQ(0, session
->pings_in_flight());
885 EXPECT_GE(session
->next_ping_id(), 1U);
886 EXPECT_FALSE(session
->check_ping_status_pending());
887 EXPECT_GE(session
->last_activity_time(), before_ping_time
);
891 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
893 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
894 EXPECT_TRUE(session
== NULL
);
897 TEST_P(SpdySessionTest
, ServerPing
) {
898 session_deps_
.host_resolver
->set_synchronous_mode(true);
900 MockConnect
connect_data(SYNCHRONOUS
, OK
);
901 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(2, false));
903 CreateMockRead(*read_ping
),
904 MockRead(SYNCHRONOUS
, 0, 0) // EOF
906 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(2, true));
907 MockWrite writes
[] = {
908 CreateMockWrite(*write_ping
),
910 StaticSocketDataProvider
data(
911 reads
, arraysize(reads
), writes
, arraysize(writes
));
912 data
.set_connect_data(connect_data
);
913 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
915 CreateNetworkSession();
917 base::WeakPtr
<SpdySession
> session
=
918 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
920 base::WeakPtr
<SpdyStream
> spdy_stream1
=
921 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
922 session
, test_url_
, MEDIUM
, BoundNetLog());
923 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
924 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
925 spdy_stream1
->SetDelegate(&delegate
);
927 // Flush the read completion task.
928 base::MessageLoop::current()->RunUntilIdle();
930 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
932 EXPECT_TRUE(session
== NULL
);
933 EXPECT_EQ(NULL
, spdy_stream1
.get());
936 // Cause a ping to be sent out while producing a write. The write loop
937 // should handle this properly, i.e. another DoWriteLoop task should
938 // not be posted. This is a regression test for
939 // http://crbug.com/261043 .
940 TEST_P(SpdySessionTest
, PingAndWriteLoop
) {
941 session_deps_
.enable_ping
= true;
942 session_deps_
.time_func
= TheNearFuture
;
944 MockConnect
connect_data(SYNCHRONOUS
, OK
);
945 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
946 scoped_ptr
<SpdyFrame
> req(
947 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
948 MockWrite writes
[] = {
949 CreateMockWrite(*req
, 0),
950 CreateMockWrite(*write_ping
, 1),
954 MockRead(ASYNC
, 0, 2) // EOF
957 session_deps_
.host_resolver
->set_synchronous_mode(true);
959 DeterministicSocketData
data(reads
, arraysize(reads
),
960 writes
, arraysize(writes
));
961 data
.set_connect_data(connect_data
);
962 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
964 CreateDeterministicNetworkSession();
966 base::WeakPtr
<SpdySession
> session
=
967 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
969 GURL
url(kDefaultURL
);
970 base::WeakPtr
<SpdyStream
> spdy_stream
=
971 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
972 session
, url
, LOWEST
, BoundNetLog());
973 test::StreamDelegateDoNothing
delegate(spdy_stream
);
974 spdy_stream
->SetDelegate(&delegate
);
976 scoped_ptr
<SpdyHeaderBlock
> headers(
977 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
978 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
980 // Shift time so that a ping will be sent out.
981 g_time_delta
= base::TimeDelta::FromSeconds(11);
985 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting");
988 TEST_P(SpdySessionTest
, StreamIdSpaceExhausted
) {
989 const SpdyStreamId kLastStreamId
= 0x7fffffff;
990 session_deps_
.host_resolver
->set_synchronous_mode(true);
992 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
993 // fixed to allow for two stream ID assignments, and three concurrent
994 // streams. Four streams are started, and two are activated. Verify the
995 // session goes away, and that the created (but not activated) and
996 // stalled streams are aborted. Also verify the activated streams complete,
997 // at which point the session closes.
999 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyGet(
1000 NULL
, 0, false, kLastStreamId
- 2, MEDIUM
, true));
1001 scoped_ptr
<SpdyFrame
> req2(
1002 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, kLastStreamId
, MEDIUM
, true));
1004 MockWrite writes
[] = {
1005 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
1008 scoped_ptr
<SpdyFrame
> resp1(
1009 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, kLastStreamId
- 2));
1010 scoped_ptr
<SpdyFrame
> resp2(
1011 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, kLastStreamId
));
1013 scoped_ptr
<SpdyFrame
> body1(
1014 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
- 2, true));
1015 scoped_ptr
<SpdyFrame
> body2(
1016 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
, true));
1018 MockRead reads
[] = {
1019 CreateMockRead(*resp1
, 2), CreateMockRead(*resp2
, 3),
1020 CreateMockRead(*body1
, 4), CreateMockRead(*body2
, 5),
1021 MockRead(ASYNC
, 0, 6) // EOF
1024 DeterministicSocketData
data(
1025 reads
, arraysize(reads
), writes
, arraysize(writes
));
1027 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1028 data
.set_connect_data(connect_data
);
1029 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1031 CreateDeterministicNetworkSession();
1032 base::WeakPtr
<SpdySession
> session
=
1033 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1035 // Fix stream_hi_water_mark_ to allow for two stream activations.
1036 session
->stream_hi_water_mark_
= kLastStreamId
- 2;
1037 // Fix max_concurrent_streams to allow for three stream creations.
1038 session
->max_concurrent_streams_
= 3;
1040 // Create three streams synchronously, and begin a fourth (which is stalled).
1041 GURL
url(kDefaultURL
);
1042 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
1043 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1044 test::StreamDelegateDoNothing
delegate1(stream1
);
1045 stream1
->SetDelegate(&delegate1
);
1047 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
1048 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1049 test::StreamDelegateDoNothing
delegate2(stream2
);
1050 stream2
->SetDelegate(&delegate2
);
1052 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
1053 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1054 test::StreamDelegateDoNothing
delegate3(stream3
);
1055 stream3
->SetDelegate(&delegate3
);
1057 SpdyStreamRequest request4
;
1058 TestCompletionCallback callback4
;
1059 EXPECT_EQ(ERR_IO_PENDING
,
1060 request4
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
,
1065 callback4
.callback()));
1067 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1068 EXPECT_EQ(0u, session
->num_active_streams());
1069 EXPECT_EQ(3u, session
->num_created_streams());
1070 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1072 // Activate stream 1. One ID remains available.
1073 stream1
->SendRequestHeaders(
1074 scoped_ptr
<SpdyHeaderBlock
>(
1075 spdy_util_
.ConstructGetHeaderBlock(url
.spec())),
1076 NO_MORE_DATA_TO_SEND
);
1079 EXPECT_EQ(kLastStreamId
- 2u, stream1
->stream_id());
1080 EXPECT_EQ(1u, session
->num_active_streams());
1081 EXPECT_EQ(2u, session
->num_created_streams());
1082 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1084 // Activate stream 2. ID space is exhausted.
1085 stream2
->SendRequestHeaders(
1086 scoped_ptr
<SpdyHeaderBlock
>(
1087 spdy_util_
.ConstructGetHeaderBlock(url
.spec())),
1088 NO_MORE_DATA_TO_SEND
);
1091 // Active streams remain active.
1092 EXPECT_EQ(kLastStreamId
, stream2
->stream_id());
1093 EXPECT_EQ(2u, session
->num_active_streams());
1095 // Session is going away. Created and stalled streams were aborted.
1096 EXPECT_EQ(SpdySession::STATE_GOING_AWAY
, session
->availability_state_
);
1097 EXPECT_EQ(ERR_ABORTED
, delegate3
.WaitForClose());
1098 EXPECT_EQ(ERR_ABORTED
, callback4
.WaitForResult());
1099 EXPECT_EQ(0u, session
->num_created_streams());
1100 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1102 // Read responses on remaining active streams.
1104 EXPECT_EQ(OK
, delegate1
.WaitForClose());
1105 EXPECT_EQ(kUploadData
, delegate1
.TakeReceivedData());
1106 EXPECT_EQ(OK
, delegate2
.WaitForClose());
1107 EXPECT_EQ(kUploadData
, delegate2
.TakeReceivedData());
1109 // Session was destroyed.
1110 base::MessageLoop::current()->RunUntilIdle();
1111 EXPECT_FALSE(session
.get());
1114 // Verifies that an unstalled pending stream creation racing with a new stream
1115 // creation doesn't violate the maximum stream concurrency. Regression test for
1116 // crbug.com/373858.
1117 TEST_P(SpdySessionTest
, UnstallRacesWithStreamCreation
) {
1118 session_deps_
.host_resolver
->set_synchronous_mode(true);
1120 MockRead reads
[] = {
1121 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1124 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1126 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1127 data
.set_connect_data(connect_data
);
1128 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1130 CreateNetworkSession();
1131 base::WeakPtr
<SpdySession
> session
=
1132 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1134 // Fix max_concurrent_streams to allow for one open stream.
1135 session
->max_concurrent_streams_
= 1;
1137 // Create two streams: one synchronously, and one which stalls.
1138 GURL
url(kDefaultURL
);
1139 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
1140 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1142 SpdyStreamRequest request2
;
1143 TestCompletionCallback callback2
;
1144 EXPECT_EQ(ERR_IO_PENDING
,
1145 request2
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
,
1150 callback2
.callback()));
1152 EXPECT_EQ(1u, session
->num_created_streams());
1153 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1155 // Cancel the first stream. A callback to unstall the second stream was
1156 // posted. Don't run it yet.
1159 EXPECT_EQ(0u, session
->num_created_streams());
1160 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1162 // Create a third stream prior to the second stream's callback.
1163 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
1164 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1166 EXPECT_EQ(1u, session
->num_created_streams());
1167 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1169 // NOW run the message loop. The unstalled stream will re-stall itself.
1170 base::MessageLoop::current()->RunUntilIdle();
1171 EXPECT_EQ(1u, session
->num_created_streams());
1172 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1174 // Cancel the third stream and run the message loop. Verify that the second
1175 // stream creation now completes.
1177 base::MessageLoop::current()->RunUntilIdle();
1179 EXPECT_EQ(1u, session
->num_created_streams());
1180 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1181 EXPECT_EQ(OK
, callback2
.WaitForResult());
1184 TEST_P(SpdySessionTest
, DeleteExpiredPushStreams
) {
1185 session_deps_
.host_resolver
->set_synchronous_mode(true);
1186 session_deps_
.time_func
= TheNearFuture
;
1188 scoped_ptr
<SpdyFrame
> req(
1189 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
1190 scoped_ptr
<SpdyFrame
> rst(
1191 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
1193 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
1194 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
1195 scoped_ptr
<SpdyFrame
> push_a_body(
1196 spdy_util_
.ConstructSpdyBodyFrame(2, false));
1197 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
1198 NULL
, 0, 4, 1, "http://www.google.com/b.dat"));
1199 MockWrite writes
[] = {CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 4)};
1200 MockRead reads
[] = {
1201 CreateMockRead(*push_a
, 1), CreateMockRead(*push_a_body
, 2),
1202 CreateMockRead(*push_b
, 3), MockRead(ASYNC
, 0, 5), // EOF
1204 DeterministicSocketData
data(
1205 reads
, arraysize(reads
), writes
, arraysize(writes
));
1207 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1208 data
.set_connect_data(connect_data
);
1209 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1211 CreateDeterministicNetworkSession();
1212 base::WeakPtr
<SpdySession
> session
=
1213 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1215 // Process the principal request, and the first push stream request & body.
1216 GURL
url(kDefaultURL
);
1217 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1218 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1219 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1220 spdy_stream
->SetDelegate(&delegate
);
1222 scoped_ptr
<SpdyHeaderBlock
> headers(
1223 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1224 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1228 // Verify that there is one unclaimed push stream.
1229 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
1230 SpdySession::PushedStreamMap::iterator iter
=
1231 session
->unclaimed_pushed_streams_
.find(
1232 GURL("http://www.google.com/a.dat"));
1233 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
1235 if (session
->flow_control_state_
==
1236 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1237 // Unclaimed push body consumed bytes from the session window.
1238 EXPECT_EQ(kSpdySessionInitialWindowSize
- kUploadDataSize
,
1239 session
->session_recv_window_size_
);
1240 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
1243 // Shift time to expire the push stream. Read the second SYN_STREAM,
1244 // and verify a RST_STREAM was written.
1245 g_time_delta
= base::TimeDelta::FromSeconds(301);
1248 // Verify that the second pushed stream evicted the first pushed stream.
1249 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
1250 iter
= session
->unclaimed_pushed_streams_
.find(
1251 GURL("http://www.google.com/b.dat"));
1252 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
1254 if (session
->flow_control_state_
==
1255 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1256 // Verify that the session window reclaimed the evicted stream body.
1257 EXPECT_EQ(kSpdySessionInitialWindowSize
,
1258 session
->session_recv_window_size_
);
1259 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
1262 // Read and process EOF.
1264 base::MessageLoop::current()->RunUntilIdle();
1265 EXPECT_TRUE(session
== NULL
);
1268 TEST_P(SpdySessionTest
, FailedPing
) {
1269 session_deps_
.host_resolver
->set_synchronous_mode(true);
1271 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1272 MockRead reads
[] = {
1273 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1275 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
1276 scoped_ptr
<SpdyFrame
> goaway(
1277 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Failed ping."));
1278 MockWrite writes
[] = {CreateMockWrite(*write_ping
), CreateMockWrite(*goaway
)};
1279 StaticSocketDataProvider
data(
1280 reads
, arraysize(reads
), writes
, arraysize(writes
));
1281 data
.set_connect_data(connect_data
);
1282 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1284 CreateNetworkSession();
1286 base::WeakPtr
<SpdySession
> session
=
1287 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1289 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1290 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1291 session
, test_url_
, MEDIUM
, BoundNetLog());
1292 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1293 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
1294 spdy_stream1
->SetDelegate(&delegate
);
1296 session
->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1297 session
->set_hung_interval(base::TimeDelta::FromSeconds(0));
1299 // Send a PING frame.
1300 session
->WritePingFrame(1, false);
1301 EXPECT_LT(0, session
->pings_in_flight());
1302 EXPECT_GE(session
->next_ping_id(), 1U);
1303 EXPECT_TRUE(session
->check_ping_status_pending());
1305 // Assert session is not closed.
1306 EXPECT_TRUE(session
->IsAvailable());
1307 EXPECT_LT(0u, session
->num_active_streams() + session
->num_created_streams());
1308 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1310 // We set last time we have received any data in 1 sec less than now.
1311 // CheckPingStatus will trigger timeout because hung interval is zero.
1312 base::TimeTicks now
= base::TimeTicks::Now();
1313 session
->last_activity_time_
= now
- base::TimeDelta::FromSeconds(1);
1314 session
->CheckPingStatus(now
);
1315 base::MessageLoop::current()->RunUntilIdle();
1317 EXPECT_TRUE(session
== NULL
);
1318 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1319 EXPECT_EQ(NULL
, spdy_stream1
.get());
1322 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1323 // settings frame increasing the max concurrent streams by 1. Make
1324 // sure nothing blows up. This is a regression test for
1325 // http://crbug.com/57331 .
1326 TEST_P(SpdySessionTest
, OnSettings
) {
1327 session_deps_
.host_resolver
->set_synchronous_mode(true);
1329 const SpdySettingsIds kSpdySettingsIds
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1331 SettingsMap new_settings
;
1332 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1333 new_settings
[kSpdySettingsIds
] =
1334 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1335 scoped_ptr
<SpdyFrame
> settings_frame(
1336 spdy_util_
.ConstructSpdySettings(new_settings
));
1337 MockRead reads
[] = {
1338 CreateMockRead(*settings_frame
, 0),
1339 MockRead(ASYNC
, 0, 1),
1342 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1343 MockWrite writes
[] = {
1344 CreateMockWrite(*settings_ack
, 2),
1347 DeterministicSocketData
data(reads
, arraysize(reads
),
1348 writes
, arraysize(writes
));
1349 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1350 data
.set_connect_data(connect_data
);
1351 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1353 CreateDeterministicNetworkSession();
1355 base::WeakPtr
<SpdySession
> session
=
1356 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1358 // Create the maximum number of concurrent streams.
1359 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1360 base::WeakPtr
<SpdyStream
> spdy_stream
=
1361 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1362 session
, test_url_
, MEDIUM
, BoundNetLog());
1363 ASSERT_TRUE(spdy_stream
!= NULL
);
1366 StreamReleaserCallback stream_releaser
;
1367 SpdyStreamRequest request
;
1368 ASSERT_EQ(ERR_IO_PENDING
,
1369 request
.StartRequest(
1370 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1372 stream_releaser
.MakeCallback(&request
)));
1376 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1379 if (spdy_util_
.spdy_version() >= SPDY4
) {
1380 // Allow the SETTINGS+ACK to write, so the session finishes draining.
1383 base::MessageLoop::current()->RunUntilIdle();
1384 EXPECT_TRUE(session
== NULL
);
1387 // Start with a persisted value for max concurrent streams. Receive a
1388 // settings frame increasing the max concurrent streams by 1 and which
1389 // also clears the persisted data. Verify that persisted data is
1391 TEST_P(SpdySessionTest
, ClearSettings
) {
1392 if (spdy_util_
.spdy_version() >= SPDY4
) {
1393 // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1394 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4.
1397 session_deps_
.host_resolver
->set_synchronous_mode(true);
1399 SettingsMap new_settings
;
1400 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1401 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1402 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1403 scoped_ptr
<SpdyFrame
> settings_frame(
1404 spdy_util_
.ConstructSpdySettings(new_settings
));
1405 uint8 flags
= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
1406 test::SetFrameFlags(settings_frame
.get(), flags
, spdy_util_
.spdy_version());
1407 MockRead reads
[] = {
1408 CreateMockRead(*settings_frame
, 0),
1409 MockRead(ASYNC
, 0, 1),
1412 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
1413 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1414 data
.set_connect_data(connect_data
);
1415 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1417 CreateDeterministicNetworkSession();
1419 // Initialize the SpdySetting with the default.
1420 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1421 test_host_port_pair_
,
1422 SETTINGS_MAX_CONCURRENT_STREAMS
,
1423 SETTINGS_FLAG_PLEASE_PERSIST
,
1424 kInitialMaxConcurrentStreams
);
1427 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1428 test_host_port_pair_
).empty());
1430 base::WeakPtr
<SpdySession
> session
=
1431 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1433 // Create the maximum number of concurrent streams.
1434 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1435 base::WeakPtr
<SpdyStream
> spdy_stream
=
1436 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1437 session
, test_url_
, MEDIUM
, BoundNetLog());
1438 ASSERT_TRUE(spdy_stream
!= NULL
);
1441 StreamReleaserCallback stream_releaser
;
1443 SpdyStreamRequest request
;
1444 ASSERT_EQ(ERR_IO_PENDING
,
1445 request
.StartRequest(
1446 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1448 stream_releaser
.MakeCallback(&request
)));
1452 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1454 // Make sure that persisted data is cleared.
1456 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1457 test_host_port_pair_
).empty());
1459 // Make sure session's max_concurrent_streams is correct.
1460 EXPECT_EQ(kInitialMaxConcurrentStreams
+ 1,
1461 session
->max_concurrent_streams());
1464 EXPECT_TRUE(session
== NULL
);
1467 // Start with max concurrent streams set to 1. Request two streams.
1468 // When the first completes, have the callback close its stream, which
1469 // should trigger the second stream creation. Then cancel that one
1470 // immediately. Don't crash. This is a regression test for
1471 // http://crbug.com/63532 .
1472 TEST_P(SpdySessionTest
, CancelPendingCreateStream
) {
1473 session_deps_
.host_resolver
->set_synchronous_mode(true);
1475 MockRead reads
[] = {
1476 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1479 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1480 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1482 data
.set_connect_data(connect_data
);
1483 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1485 CreateNetworkSession();
1487 // Initialize the SpdySetting with 1 max concurrent streams.
1488 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1489 test_host_port_pair_
,
1490 SETTINGS_MAX_CONCURRENT_STREAMS
,
1491 SETTINGS_FLAG_PLEASE_PERSIST
,
1494 base::WeakPtr
<SpdySession
> session
=
1495 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1497 // Leave room for only one more stream to be created.
1498 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
1499 base::WeakPtr
<SpdyStream
> spdy_stream
=
1500 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1501 session
, test_url_
, MEDIUM
, BoundNetLog());
1502 ASSERT_TRUE(spdy_stream
!= NULL
);
1505 // Create 2 more streams. First will succeed. Second will be pending.
1506 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1507 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1508 session
, test_url_
, MEDIUM
, BoundNetLog());
1509 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1511 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1512 // a valgrind error if the callback is invoked when it's not supposed to be.
1513 scoped_ptr
<TestCompletionCallback
> callback(new TestCompletionCallback
);
1515 SpdyStreamRequest request
;
1516 ASSERT_EQ(ERR_IO_PENDING
,
1517 request
.StartRequest(
1518 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1520 callback
->callback()));
1522 // Release the first one, this will allow the second to be created.
1523 spdy_stream1
->Cancel();
1524 EXPECT_EQ(NULL
, spdy_stream1
.get());
1526 request
.CancelRequest();
1529 // Should not crash when running the pending callback.
1530 base::MessageLoop::current()->RunUntilIdle();
1533 TEST_P(SpdySessionTest
, SendInitialDataOnNewSession
) {
1534 session_deps_
.host_resolver
->set_synchronous_mode(true);
1536 MockRead reads
[] = {
1537 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1540 SettingsMap settings
;
1541 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1542 const SpdySettingsIds kSpdySettingsIds2
= SETTINGS_INITIAL_WINDOW_SIZE
;
1543 const uint32 kInitialRecvWindowSize
= 10 * 1024 * 1024;
1544 settings
[kSpdySettingsIds1
] =
1545 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
1546 if (spdy_util_
.spdy_version() >= SPDY3
) {
1547 settings
[kSpdySettingsIds2
] =
1548 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kInitialRecvWindowSize
);
1550 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1551 scoped_ptr
<SpdyFrame
> settings_frame(
1552 spdy_util_
.ConstructSpdySettings(settings
));
1553 scoped_ptr
<SpdyFrame
> initial_window_update(
1554 spdy_util_
.ConstructSpdyWindowUpdate(
1555 kSessionFlowControlStreamId
,
1556 kDefaultInitialRecvWindowSize
- kSpdySessionInitialWindowSize
));
1557 std::vector
<MockWrite
> writes
;
1558 if ((GetParam() >= kProtoSPDY4MinimumVersion
) &&
1559 (GetParam() <= kProtoSPDY4MaximumVersion
)) {
1562 kHttp2ConnectionHeaderPrefix
,
1563 kHttp2ConnectionHeaderPrefixSize
));
1565 writes
.push_back(CreateMockWrite(*settings_frame
));
1566 if (GetParam() >= kProtoSPDY31
) {
1567 writes
.push_back(CreateMockWrite(*initial_window_update
));
1570 SettingsMap server_settings
;
1571 const uint32 initial_max_concurrent_streams
= 1;
1572 server_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1573 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED
,
1574 initial_max_concurrent_streams
);
1575 scoped_ptr
<SpdyFrame
> server_settings_frame(
1576 spdy_util_
.ConstructSpdySettings(server_settings
));
1577 if (GetParam() <= kProtoSPDY31
) {
1578 writes
.push_back(CreateMockWrite(*server_settings_frame
));
1581 session_deps_
.stream_initial_recv_window_size
= kInitialRecvWindowSize
;
1583 StaticSocketDataProvider
data(reads
, arraysize(reads
),
1584 vector_as_array(&writes
), writes
.size());
1585 data
.set_connect_data(connect_data
);
1586 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1588 CreateNetworkSession();
1590 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1591 test_host_port_pair_
,
1592 SETTINGS_MAX_CONCURRENT_STREAMS
,
1593 SETTINGS_FLAG_PLEASE_PERSIST
,
1594 initial_max_concurrent_streams
);
1596 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
1597 pool_peer
.SetEnableSendingInitialData(true);
1599 base::WeakPtr
<SpdySession
> session
=
1600 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1602 base::MessageLoop::current()->RunUntilIdle();
1603 EXPECT_TRUE(data
.at_write_eof());
1606 TEST_P(SpdySessionTest
, ClearSettingsStorageOnIPAddressChanged
) {
1607 CreateNetworkSession();
1609 base::WeakPtr
<HttpServerProperties
> test_http_server_properties
=
1610 spdy_session_pool_
->http_server_properties();
1611 SettingsFlagsAndValue
flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST
, 2);
1612 test_http_server_properties
->SetSpdySetting(
1613 test_host_port_pair_
,
1614 SETTINGS_MAX_CONCURRENT_STREAMS
,
1615 SETTINGS_FLAG_PLEASE_PERSIST
,
1617 EXPECT_NE(0u, test_http_server_properties
->GetSpdySettings(
1618 test_host_port_pair_
).size());
1619 spdy_session_pool_
->OnIPAddressChanged();
1620 EXPECT_EQ(0u, test_http_server_properties
->GetSpdySettings(
1621 test_host_port_pair_
).size());
1624 TEST_P(SpdySessionTest
, Initialize
) {
1625 CapturingBoundNetLog log
;
1626 session_deps_
.net_log
= log
.bound().net_log();
1627 session_deps_
.host_resolver
->set_synchronous_mode(true);
1629 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1630 MockRead reads
[] = {
1631 MockRead(ASYNC
, 0, 0) // EOF
1634 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1635 data
.set_connect_data(connect_data
);
1636 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1638 CreateNetworkSession();
1640 base::WeakPtr
<SpdySession
> session
=
1641 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1642 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1644 // Flush the read completion task.
1645 base::MessageLoop::current()->RunUntilIdle();
1647 net::CapturingNetLog::CapturedEntryList entries
;
1648 log
.GetEntries(&entries
);
1649 EXPECT_LT(0u, entries
.size());
1651 // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly.
1652 int pos
= net::ExpectLogContainsSomewhere(
1654 net::NetLog::TYPE_SPDY_SESSION_INITIALIZED
,
1655 net::NetLog::PHASE_NONE
);
1658 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1659 NetLog::Source socket_source
;
1660 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry
.params
.get(),
1662 EXPECT_TRUE(socket_source
.IsValid());
1663 EXPECT_NE(log
.bound().source().id
, socket_source
.id
);
1666 TEST_P(SpdySessionTest
, NetLogOnSessionGoaway
) {
1667 session_deps_
.host_resolver
->set_synchronous_mode(true);
1669 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1670 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
1671 MockRead reads
[] = {
1672 CreateMockRead(*goaway
),
1673 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1676 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1677 data
.set_connect_data(connect_data
);
1678 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1680 CreateNetworkSession();
1682 CapturingBoundNetLog log
;
1683 base::WeakPtr
<SpdySession
> session
=
1684 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1685 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1687 // Flush the read completion task.
1688 base::MessageLoop::current()->RunUntilIdle();
1690 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1691 EXPECT_TRUE(session
== NULL
);
1693 // Check that the NetLog was filled reasonably.
1694 net::CapturingNetLog::CapturedEntryList entries
;
1695 log
.GetEntries(&entries
);
1696 EXPECT_LT(0u, entries
.size());
1698 // Check that we logged SPDY_SESSION_CLOSE correctly.
1699 int pos
= net::ExpectLogContainsSomewhere(
1701 net::NetLog::TYPE_SPDY_SESSION_CLOSE
,
1702 net::NetLog::PHASE_NONE
);
1704 if (pos
< static_cast<int>(entries
.size())) {
1705 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1707 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1708 EXPECT_EQ(OK
, error_code
);
1714 TEST_P(SpdySessionTest
, NetLogOnSessionEOF
) {
1715 session_deps_
.host_resolver
->set_synchronous_mode(true);
1717 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1718 MockRead reads
[] = {
1719 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1722 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1723 data
.set_connect_data(connect_data
);
1724 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1726 CreateNetworkSession();
1728 CapturingBoundNetLog log
;
1729 base::WeakPtr
<SpdySession
> session
=
1730 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1731 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1733 // Flush the read completion task.
1734 base::MessageLoop::current()->RunUntilIdle();
1736 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1737 EXPECT_TRUE(session
== NULL
);
1739 // Check that the NetLog was filled reasonably.
1740 net::CapturingNetLog::CapturedEntryList entries
;
1741 log
.GetEntries(&entries
);
1742 EXPECT_LT(0u, entries
.size());
1744 // Check that we logged SPDY_SESSION_CLOSE correctly.
1746 net::ExpectLogContainsSomewhere(entries
,
1748 net::NetLog::TYPE_SPDY_SESSION_CLOSE
,
1749 net::NetLog::PHASE_NONE
);
1751 if (pos
< static_cast<int>(entries
.size())) {
1752 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1754 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1755 EXPECT_EQ(ERR_CONNECTION_CLOSED
, error_code
);
1761 TEST_P(SpdySessionTest
, SynCompressionHistograms
) {
1762 session_deps_
.enable_compression
= true;
1764 scoped_ptr
<SpdyFrame
> req(
1765 spdy_util_
.ConstructSpdyGet(NULL
, 0, true, 1, MEDIUM
, true));
1766 MockWrite writes
[] = {
1767 CreateMockWrite(*req
, 0),
1769 MockRead reads
[] = {
1770 MockRead(ASYNC
, 0, 1) // EOF
1772 DeterministicSocketData
data(reads
, arraysize(reads
),
1773 writes
, arraysize(writes
));
1774 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1775 data
.set_connect_data(connect_data
);
1776 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1778 CreateDeterministicNetworkSession();
1779 base::WeakPtr
<SpdySession
> session
=
1780 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1782 GURL
url(kDefaultURL
);
1783 base::WeakPtr
<SpdyStream
> spdy_stream
=
1784 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1785 session
, url
, MEDIUM
, BoundNetLog());
1786 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1787 spdy_stream
->SetDelegate(&delegate
);
1789 scoped_ptr
<SpdyHeaderBlock
> headers(
1790 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1791 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1792 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
1794 // Write request headers & capture resulting histogram update.
1795 base::HistogramTester histogram_tester
;
1798 // Regression test of compression performance under the request fixture.
1799 switch (spdy_util_
.spdy_version()) {
1801 histogram_tester
.ExpectBucketCount(
1802 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1805 histogram_tester
.ExpectBucketCount(
1806 "Net.SpdySynStreamCompressionPercentage", 82, 1);
1809 histogram_tester
.ExpectBucketCount(
1810 "Net.SpdySynStreamCompressionPercentage", 82, 1);
1816 // Read and process EOF.
1818 base::MessageLoop::current()->RunUntilIdle();
1819 EXPECT_TRUE(session
== NULL
);
1822 // Queue up a low-priority SYN_STREAM followed by a high-priority
1823 // one. The high priority one should still send first and receive
1825 TEST_P(SpdySessionTest
, OutOfOrderSynStreams
) {
1826 // Construct the request.
1827 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1828 scoped_ptr
<SpdyFrame
> req_highest(
1829 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, HIGHEST
, true));
1830 scoped_ptr
<SpdyFrame
> req_lowest(
1831 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1832 MockWrite writes
[] = {
1833 CreateMockWrite(*req_highest
, 0),
1834 CreateMockWrite(*req_lowest
, 1),
1837 scoped_ptr
<SpdyFrame
> resp_highest(
1838 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1839 scoped_ptr
<SpdyFrame
> body_highest(
1840 spdy_util_
.ConstructSpdyBodyFrame(1, true));
1841 scoped_ptr
<SpdyFrame
> resp_lowest(
1842 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1843 scoped_ptr
<SpdyFrame
> body_lowest(
1844 spdy_util_
.ConstructSpdyBodyFrame(3, true));
1845 MockRead reads
[] = {
1846 CreateMockRead(*resp_highest
, 2),
1847 CreateMockRead(*body_highest
, 3),
1848 CreateMockRead(*resp_lowest
, 4),
1849 CreateMockRead(*body_lowest
, 5),
1850 MockRead(ASYNC
, 0, 6) // EOF
1853 session_deps_
.host_resolver
->set_synchronous_mode(true);
1855 DeterministicSocketData
data(reads
, arraysize(reads
),
1856 writes
, arraysize(writes
));
1857 data
.set_connect_data(connect_data
);
1858 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1860 CreateDeterministicNetworkSession();
1862 base::WeakPtr
<SpdySession
> session
=
1863 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1865 GURL
url(kDefaultURL
);
1867 base::WeakPtr
<SpdyStream
> spdy_stream_lowest
=
1868 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1869 session
, url
, LOWEST
, BoundNetLog());
1870 ASSERT_TRUE(spdy_stream_lowest
);
1871 EXPECT_EQ(0u, spdy_stream_lowest
->stream_id());
1872 test::StreamDelegateDoNothing
delegate_lowest(spdy_stream_lowest
);
1873 spdy_stream_lowest
->SetDelegate(&delegate_lowest
);
1875 base::WeakPtr
<SpdyStream
> spdy_stream_highest
=
1876 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1877 session
, url
, HIGHEST
, BoundNetLog());
1878 ASSERT_TRUE(spdy_stream_highest
);
1879 EXPECT_EQ(0u, spdy_stream_highest
->stream_id());
1880 test::StreamDelegateDoNothing
delegate_highest(spdy_stream_highest
);
1881 spdy_stream_highest
->SetDelegate(&delegate_highest
);
1883 // Queue the lower priority one first.
1885 scoped_ptr
<SpdyHeaderBlock
> headers_lowest(
1886 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1887 spdy_stream_lowest
->SendRequestHeaders(
1888 headers_lowest
.Pass(), NO_MORE_DATA_TO_SEND
);
1889 EXPECT_TRUE(spdy_stream_lowest
->HasUrlFromHeaders());
1891 scoped_ptr
<SpdyHeaderBlock
> headers_highest(
1892 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1893 spdy_stream_highest
->SendRequestHeaders(
1894 headers_highest
.Pass(), NO_MORE_DATA_TO_SEND
);
1895 EXPECT_TRUE(spdy_stream_highest
->HasUrlFromHeaders());
1899 EXPECT_FALSE(spdy_stream_lowest
);
1900 EXPECT_FALSE(spdy_stream_highest
);
1901 EXPECT_EQ(3u, delegate_lowest
.stream_id());
1902 EXPECT_EQ(1u, delegate_highest
.stream_id());
1905 TEST_P(SpdySessionTest
, CancelStream
) {
1906 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1907 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1908 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1909 scoped_ptr
<SpdyFrame
> req2(
1910 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1911 MockWrite writes
[] = {
1912 CreateMockWrite(*req2
, 0),
1915 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1916 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1917 MockRead reads
[] = {
1918 CreateMockRead(*resp2
, 1),
1919 CreateMockRead(*body2
, 2),
1920 MockRead(ASYNC
, 0, 3) // EOF
1923 session_deps_
.host_resolver
->set_synchronous_mode(true);
1925 DeterministicSocketData
data(reads
, arraysize(reads
),
1926 writes
, arraysize(writes
));
1927 data
.set_connect_data(connect_data
);
1928 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1930 CreateDeterministicNetworkSession();
1932 base::WeakPtr
<SpdySession
> session
=
1933 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1935 GURL
url1(kDefaultURL
);
1936 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1937 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1938 session
, url1
, HIGHEST
, BoundNetLog());
1939 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1940 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1941 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
1942 spdy_stream1
->SetDelegate(&delegate1
);
1944 GURL
url2(kDefaultURL
);
1945 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1946 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1947 session
, url2
, LOWEST
, BoundNetLog());
1948 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1949 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1950 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
1951 spdy_stream2
->SetDelegate(&delegate2
);
1953 scoped_ptr
<SpdyHeaderBlock
> headers(
1954 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1955 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1956 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1958 scoped_ptr
<SpdyHeaderBlock
> headers2(
1959 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1960 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1961 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1963 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1965 spdy_stream1
->Cancel();
1966 EXPECT_EQ(NULL
, spdy_stream1
.get());
1968 EXPECT_EQ(0u, delegate1
.stream_id());
1972 EXPECT_EQ(0u, delegate1
.stream_id());
1973 EXPECT_EQ(1u, delegate2
.stream_id());
1975 spdy_stream2
->Cancel();
1976 EXPECT_EQ(NULL
, spdy_stream2
.get());
1979 // Create two streams that are set to re-close themselves on close,
1980 // and then close the session. Nothing should blow up. Also a
1981 // regression test for http://crbug.com/139518 .
1982 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedSelfClosingStreams
) {
1983 session_deps_
.host_resolver
->set_synchronous_mode(true);
1985 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1987 // No actual data will be sent.
1988 MockWrite writes
[] = {
1989 MockWrite(ASYNC
, 0, 1) // EOF
1992 MockRead reads
[] = {
1993 MockRead(ASYNC
, 0, 0) // EOF
1995 DeterministicSocketData
data(reads
, arraysize(reads
),
1996 writes
, arraysize(writes
));
1997 data
.set_connect_data(connect_data
);
1998 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2000 CreateDeterministicNetworkSession();
2002 base::WeakPtr
<SpdySession
> session
=
2003 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2005 GURL
url1(kDefaultURL
);
2006 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2007 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2008 session
, url1
, HIGHEST
, BoundNetLog());
2009 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2010 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2012 GURL
url2(kDefaultURL
);
2013 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2014 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2015 session
, url2
, LOWEST
, BoundNetLog());
2016 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2017 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2019 test::ClosingDelegate
delegate1(spdy_stream1
);
2020 spdy_stream1
->SetDelegate(&delegate1
);
2022 test::ClosingDelegate
delegate2(spdy_stream2
);
2023 spdy_stream2
->SetDelegate(&delegate2
);
2025 scoped_ptr
<SpdyHeaderBlock
> headers(
2026 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2027 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2028 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2030 scoped_ptr
<SpdyHeaderBlock
> headers2(
2031 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2032 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2033 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2035 // Ensure that the streams have not yet been activated and assigned an id.
2036 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2037 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2039 // Ensure we don't crash while closing the session.
2040 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2042 EXPECT_EQ(NULL
, spdy_stream1
.get());
2043 EXPECT_EQ(NULL
, spdy_stream2
.get());
2045 EXPECT_TRUE(delegate1
.StreamIsClosed());
2046 EXPECT_TRUE(delegate2
.StreamIsClosed());
2048 base::MessageLoop::current()->RunUntilIdle();
2049 EXPECT_TRUE(session
== NULL
);
2052 // Create two streams that are set to close each other on close, and
2053 // then close the session. Nothing should blow up.
2054 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedMutuallyClosingStreams
) {
2055 session_deps_
.host_resolver
->set_synchronous_mode(true);
2057 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2059 // No actual data will be sent.
2060 MockWrite writes
[] = {
2061 MockWrite(ASYNC
, 0, 1) // EOF
2064 MockRead reads
[] = {
2065 MockRead(ASYNC
, 0, 0) // EOF
2067 DeterministicSocketData
data(reads
, arraysize(reads
),
2068 writes
, arraysize(writes
));
2069 data
.set_connect_data(connect_data
);
2070 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2072 CreateDeterministicNetworkSession();
2074 base::WeakPtr
<SpdySession
> session
=
2075 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2077 GURL
url1(kDefaultURL
);
2078 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2079 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2080 session
, url1
, HIGHEST
, BoundNetLog());
2081 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2082 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2084 GURL
url2(kDefaultURL
);
2085 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2086 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2087 session
, url2
, LOWEST
, BoundNetLog());
2088 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2089 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2091 // Make |spdy_stream1| close |spdy_stream2|.
2092 test::ClosingDelegate
delegate1(spdy_stream2
);
2093 spdy_stream1
->SetDelegate(&delegate1
);
2095 // Make |spdy_stream2| close |spdy_stream1|.
2096 test::ClosingDelegate
delegate2(spdy_stream1
);
2097 spdy_stream2
->SetDelegate(&delegate2
);
2099 scoped_ptr
<SpdyHeaderBlock
> headers(
2100 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2101 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2102 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2104 scoped_ptr
<SpdyHeaderBlock
> headers2(
2105 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2106 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2107 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2109 // Ensure that the streams have not yet been activated and assigned an id.
2110 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2111 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2113 // Ensure we don't crash while closing the session.
2114 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2116 EXPECT_EQ(NULL
, spdy_stream1
.get());
2117 EXPECT_EQ(NULL
, spdy_stream2
.get());
2119 EXPECT_TRUE(delegate1
.StreamIsClosed());
2120 EXPECT_TRUE(delegate2
.StreamIsClosed());
2122 base::MessageLoop::current()->RunUntilIdle();
2123 EXPECT_TRUE(session
== NULL
);
2126 // Create two streams that are set to re-close themselves on close,
2127 // activate them, and then close the session. Nothing should blow up.
2128 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedSelfClosingStreams
) {
2129 session_deps_
.host_resolver
->set_synchronous_mode(true);
2131 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2133 scoped_ptr
<SpdyFrame
> req1(
2134 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2135 scoped_ptr
<SpdyFrame
> req2(
2136 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
2137 MockWrite writes
[] = {
2138 CreateMockWrite(*req1
, 0),
2139 CreateMockWrite(*req2
, 1),
2142 MockRead reads
[] = {
2143 MockRead(ASYNC
, 0, 2) // EOF
2146 DeterministicSocketData
data(reads
, arraysize(reads
),
2147 writes
, arraysize(writes
));
2148 data
.set_connect_data(connect_data
);
2149 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2151 CreateDeterministicNetworkSession();
2153 base::WeakPtr
<SpdySession
> session
=
2154 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2156 GURL
url1(kDefaultURL
);
2157 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2158 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2159 session
, url1
, MEDIUM
, BoundNetLog());
2160 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2161 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2163 GURL
url2(kDefaultURL
);
2164 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2165 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2166 session
, url2
, MEDIUM
, BoundNetLog());
2167 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2168 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2170 test::ClosingDelegate
delegate1(spdy_stream1
);
2171 spdy_stream1
->SetDelegate(&delegate1
);
2173 test::ClosingDelegate
delegate2(spdy_stream2
);
2174 spdy_stream2
->SetDelegate(&delegate2
);
2176 scoped_ptr
<SpdyHeaderBlock
> headers(
2177 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2178 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2179 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2181 scoped_ptr
<SpdyHeaderBlock
> headers2(
2182 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2183 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2184 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2186 // Ensure that the streams have not yet been activated and assigned an id.
2187 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2188 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2192 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2193 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2195 // Ensure we don't crash while closing the session.
2196 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2198 EXPECT_EQ(NULL
, spdy_stream1
.get());
2199 EXPECT_EQ(NULL
, spdy_stream2
.get());
2201 EXPECT_TRUE(delegate1
.StreamIsClosed());
2202 EXPECT_TRUE(delegate2
.StreamIsClosed());
2204 base::MessageLoop::current()->RunUntilIdle();
2205 EXPECT_TRUE(session
== NULL
);
2208 // Create two streams that are set to close each other on close,
2209 // activate them, and then close the session. Nothing should blow up.
2210 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedMutuallyClosingStreams
) {
2211 session_deps_
.host_resolver
->set_synchronous_mode(true);
2213 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2215 scoped_ptr
<SpdyFrame
> req1(
2216 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2217 scoped_ptr
<SpdyFrame
> req2(
2218 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
2219 MockWrite writes
[] = {
2220 CreateMockWrite(*req1
, 0),
2221 CreateMockWrite(*req2
, 1),
2224 MockRead reads
[] = {
2225 MockRead(ASYNC
, 0, 2) // EOF
2228 DeterministicSocketData
data(reads
, arraysize(reads
),
2229 writes
, arraysize(writes
));
2230 data
.set_connect_data(connect_data
);
2231 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2233 CreateDeterministicNetworkSession();
2235 base::WeakPtr
<SpdySession
> session
=
2236 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2238 GURL
url1(kDefaultURL
);
2239 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2240 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2241 session
, url1
, MEDIUM
, BoundNetLog());
2242 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2243 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2245 GURL
url2(kDefaultURL
);
2246 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2247 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2248 session
, url2
, MEDIUM
, BoundNetLog());
2249 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2250 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2252 // Make |spdy_stream1| close |spdy_stream2|.
2253 test::ClosingDelegate
delegate1(spdy_stream2
);
2254 spdy_stream1
->SetDelegate(&delegate1
);
2256 // Make |spdy_stream2| close |spdy_stream1|.
2257 test::ClosingDelegate
delegate2(spdy_stream1
);
2258 spdy_stream2
->SetDelegate(&delegate2
);
2260 scoped_ptr
<SpdyHeaderBlock
> headers(
2261 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2262 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2263 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2265 scoped_ptr
<SpdyHeaderBlock
> headers2(
2266 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2267 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2268 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2270 // Ensure that the streams have not yet been activated and assigned an id.
2271 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2272 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2276 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2277 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2279 // Ensure we don't crash while closing the session.
2280 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2282 EXPECT_EQ(NULL
, spdy_stream1
.get());
2283 EXPECT_EQ(NULL
, spdy_stream2
.get());
2285 EXPECT_TRUE(delegate1
.StreamIsClosed());
2286 EXPECT_TRUE(delegate2
.StreamIsClosed());
2288 base::MessageLoop::current()->RunUntilIdle();
2289 EXPECT_TRUE(session
== NULL
);
2292 // Delegate that closes a given session when the stream is closed.
2293 class SessionClosingDelegate
: public test::StreamDelegateDoNothing
{
2295 SessionClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
2296 const base::WeakPtr
<SpdySession
>& session_to_close
)
2297 : StreamDelegateDoNothing(stream
),
2298 session_to_close_(session_to_close
) {}
2300 ~SessionClosingDelegate() override
{}
2302 void OnClose(int status
) override
{
2303 session_to_close_
->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR
, "Error");
2307 base::WeakPtr
<SpdySession
> session_to_close_
;
2310 // Close an activated stream that closes its session. Nothing should
2311 // blow up. This is a regression test for http://crbug.com/263691 .
2312 TEST_P(SpdySessionTest
, CloseActivatedStreamThatClosesSession
) {
2313 session_deps_
.host_resolver
->set_synchronous_mode(true);
2315 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2317 scoped_ptr
<SpdyFrame
> req(
2318 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2319 scoped_ptr
<SpdyFrame
> rst(
2320 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2321 scoped_ptr
<SpdyFrame
> goaway(
2322 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Error"));
2323 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2324 // despite being queued second.
2325 MockWrite writes
[] = {
2326 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 1),
2327 CreateMockWrite(*rst
, 2),
2330 MockRead reads
[] = {
2331 MockRead(ASYNC
, 0, 3) // EOF
2333 DeterministicSocketData
data(reads
, arraysize(reads
),
2334 writes
, arraysize(writes
));
2335 data
.set_connect_data(connect_data
);
2336 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2338 CreateDeterministicNetworkSession();
2340 base::WeakPtr
<SpdySession
> session
=
2341 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2343 GURL
url(kDefaultURL
);
2344 base::WeakPtr
<SpdyStream
> spdy_stream
=
2345 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2346 session
, url
, MEDIUM
, BoundNetLog());
2347 ASSERT_TRUE(spdy_stream
.get() != NULL
);
2348 EXPECT_EQ(0u, spdy_stream
->stream_id());
2350 SessionClosingDelegate
delegate(spdy_stream
, session
);
2351 spdy_stream
->SetDelegate(&delegate
);
2353 scoped_ptr
<SpdyHeaderBlock
> headers(
2354 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
2355 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2356 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
2358 EXPECT_EQ(0u, spdy_stream
->stream_id());
2362 EXPECT_EQ(1u, spdy_stream
->stream_id());
2364 // Ensure we don't crash while closing the stream (which closes the
2366 spdy_stream
->Cancel();
2368 EXPECT_EQ(NULL
, spdy_stream
.get());
2369 EXPECT_TRUE(delegate
.StreamIsClosed());
2371 data
.RunFor(2); // Write the RST_STREAM & GOAWAY.
2372 base::MessageLoop::current()->RunUntilIdle();
2373 EXPECT_TRUE(session
== NULL
);
2376 TEST_P(SpdySessionTest
, VerifyDomainAuthentication
) {
2377 session_deps_
.host_resolver
->set_synchronous_mode(true);
2379 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2381 // No actual data will be sent.
2382 MockWrite writes
[] = {
2383 MockWrite(ASYNC
, 0, 1) // EOF
2386 MockRead reads
[] = {
2387 MockRead(ASYNC
, 0, 0) // EOF
2389 DeterministicSocketData
data(reads
, arraysize(reads
),
2390 writes
, arraysize(writes
));
2391 data
.set_connect_data(connect_data
);
2392 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2394 // Load a cert that is valid for:
2398 base::FilePath certs_dir
= GetTestCertsDirectory();
2399 scoped_refptr
<X509Certificate
> test_cert(
2400 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2401 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
.get());
2403 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2404 ssl
.cert
= test_cert
;
2405 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2407 CreateDeterministicNetworkSession();
2409 base::WeakPtr
<SpdySession
> session
=
2410 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2412 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2413 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2414 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.com"));
2415 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2418 TEST_P(SpdySessionTest
, ConnectionPooledWithTlsChannelId
) {
2419 session_deps_
.host_resolver
->set_synchronous_mode(true);
2421 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2423 // No actual data will be sent.
2424 MockWrite writes
[] = {
2425 MockWrite(ASYNC
, 0, 1) // EOF
2428 MockRead reads
[] = {
2429 MockRead(ASYNC
, 0, 0) // EOF
2431 DeterministicSocketData
data(reads
, arraysize(reads
),
2432 writes
, arraysize(writes
));
2433 data
.set_connect_data(connect_data
);
2434 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2436 // Load a cert that is valid for:
2440 base::FilePath certs_dir
= GetTestCertsDirectory();
2441 scoped_refptr
<X509Certificate
> test_cert(
2442 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2443 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
.get());
2445 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2446 ssl
.channel_id_sent
= true;
2447 ssl
.cert
= test_cert
;
2448 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2450 CreateDeterministicNetworkSession();
2452 base::WeakPtr
<SpdySession
> session
=
2453 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2455 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2456 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2457 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.example.com"));
2458 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2461 TEST_P(SpdySessionTest
, CloseTwoStalledCreateStream
) {
2462 // TODO(rtenneti): Define a helper class/methods and move the common code in
2464 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2466 SettingsMap new_settings
;
2467 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
2468 const uint32 max_concurrent_streams
= 1;
2469 new_settings
[kSpdySettingsIds1
] =
2470 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
2472 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
2473 scoped_ptr
<SpdyFrame
> req1(
2474 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2475 scoped_ptr
<SpdyFrame
> req2(
2476 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
2477 scoped_ptr
<SpdyFrame
> req3(
2478 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
2479 MockWrite writes
[] = {
2480 CreateMockWrite(*settings_ack
, 1),
2481 CreateMockWrite(*req1
, 2),
2482 CreateMockWrite(*req2
, 5),
2483 CreateMockWrite(*req3
, 8),
2486 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2488 scoped_ptr
<SpdyFrame
> settings_frame(
2489 spdy_util_
.ConstructSpdySettings(new_settings
));
2491 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2492 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2494 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
2495 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
2497 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
2498 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
2500 MockRead reads
[] = {
2501 CreateMockRead(*settings_frame
),
2502 CreateMockRead(*resp1
, 3),
2503 CreateMockRead(*body1
, 4),
2504 CreateMockRead(*resp2
, 6),
2505 CreateMockRead(*body2
, 7),
2506 CreateMockRead(*resp3
, 9),
2507 CreateMockRead(*body3
, 10),
2508 MockRead(ASYNC
, 0, 11) // EOF
2511 DeterministicSocketData
data(reads
, arraysize(reads
),
2512 writes
, arraysize(writes
));
2513 data
.set_connect_data(connect_data
);
2514 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2516 CreateDeterministicNetworkSession();
2518 base::WeakPtr
<SpdySession
> session
=
2519 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2521 // Read the settings frame.
2524 GURL
url1(kDefaultURL
);
2525 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2526 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2527 session
, url1
, LOWEST
, BoundNetLog());
2528 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2529 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2530 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2531 spdy_stream1
->SetDelegate(&delegate1
);
2533 TestCompletionCallback callback2
;
2534 GURL
url2(kDefaultURL
);
2535 SpdyStreamRequest request2
;
2536 ASSERT_EQ(ERR_IO_PENDING
,
2537 request2
.StartRequest(
2538 SPDY_REQUEST_RESPONSE_STREAM
,
2539 session
, url2
, LOWEST
, BoundNetLog(), callback2
.callback()));
2541 TestCompletionCallback callback3
;
2542 GURL
url3(kDefaultURL
);
2543 SpdyStreamRequest request3
;
2544 ASSERT_EQ(ERR_IO_PENDING
,
2545 request3
.StartRequest(
2546 SPDY_REQUEST_RESPONSE_STREAM
,
2547 session
, url3
, LOWEST
, BoundNetLog(), callback3
.callback()));
2549 EXPECT_EQ(0u, session
->num_active_streams());
2550 EXPECT_EQ(1u, session
->num_created_streams());
2551 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2553 scoped_ptr
<SpdyHeaderBlock
> headers(
2554 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2555 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2556 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2558 // Run until 1st stream is activated and then closed.
2559 EXPECT_EQ(0u, delegate1
.stream_id());
2561 EXPECT_EQ(NULL
, spdy_stream1
.get());
2562 EXPECT_EQ(1u, delegate1
.stream_id());
2564 EXPECT_EQ(0u, session
->num_active_streams());
2565 EXPECT_EQ(0u, session
->num_created_streams());
2566 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2568 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2569 // create the 2nd stream.
2570 base::MessageLoop::current()->RunUntilIdle();
2572 EXPECT_EQ(0u, session
->num_active_streams());
2573 EXPECT_EQ(1u, session
->num_created_streams());
2574 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2576 base::WeakPtr
<SpdyStream
> stream2
= request2
.ReleaseStream();
2577 test::StreamDelegateDoNothing
delegate2(stream2
);
2578 stream2
->SetDelegate(&delegate2
);
2579 scoped_ptr
<SpdyHeaderBlock
> headers2(
2580 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2581 stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2582 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
2584 // Run until 2nd stream is activated and then closed.
2585 EXPECT_EQ(0u, delegate2
.stream_id());
2587 EXPECT_EQ(NULL
, stream2
.get());
2588 EXPECT_EQ(3u, delegate2
.stream_id());
2590 EXPECT_EQ(0u, session
->num_active_streams());
2591 EXPECT_EQ(0u, session
->num_created_streams());
2592 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2594 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2595 // create the 3rd stream.
2596 base::MessageLoop::current()->RunUntilIdle();
2598 EXPECT_EQ(0u, session
->num_active_streams());
2599 EXPECT_EQ(1u, session
->num_created_streams());
2600 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2602 base::WeakPtr
<SpdyStream
> stream3
= request3
.ReleaseStream();
2603 test::StreamDelegateDoNothing
delegate3(stream3
);
2604 stream3
->SetDelegate(&delegate3
);
2605 scoped_ptr
<SpdyHeaderBlock
> headers3(
2606 spdy_util_
.ConstructGetHeaderBlock(url3
.spec()));
2607 stream3
->SendRequestHeaders(headers3
.Pass(), NO_MORE_DATA_TO_SEND
);
2608 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
2610 // Run until 2nd stream is activated and then closed.
2611 EXPECT_EQ(0u, delegate3
.stream_id());
2613 EXPECT_EQ(NULL
, stream3
.get());
2614 EXPECT_EQ(5u, delegate3
.stream_id());
2616 EXPECT_EQ(0u, session
->num_active_streams());
2617 EXPECT_EQ(0u, session
->num_created_streams());
2618 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2623 TEST_P(SpdySessionTest
, CancelTwoStalledCreateStream
) {
2624 session_deps_
.host_resolver
->set_synchronous_mode(true);
2626 MockRead reads
[] = {
2627 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2630 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
2631 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2633 data
.set_connect_data(connect_data
);
2634 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2636 CreateNetworkSession();
2638 base::WeakPtr
<SpdySession
> session
=
2639 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2641 // Leave room for only one more stream to be created.
2642 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
2643 base::WeakPtr
<SpdyStream
> spdy_stream
=
2644 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2645 session
, test_url_
, MEDIUM
, BoundNetLog());
2646 ASSERT_TRUE(spdy_stream
!= NULL
);
2649 GURL
url1(kDefaultURL
);
2650 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2651 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2652 session
, url1
, LOWEST
, BoundNetLog());
2653 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2654 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2656 TestCompletionCallback callback2
;
2657 GURL
url2(kDefaultURL
);
2658 SpdyStreamRequest request2
;
2659 ASSERT_EQ(ERR_IO_PENDING
,
2660 request2
.StartRequest(
2661 SPDY_BIDIRECTIONAL_STREAM
, session
, url2
, LOWEST
, BoundNetLog(),
2662 callback2
.callback()));
2664 TestCompletionCallback callback3
;
2665 GURL
url3(kDefaultURL
);
2666 SpdyStreamRequest request3
;
2667 ASSERT_EQ(ERR_IO_PENDING
,
2668 request3
.StartRequest(
2669 SPDY_BIDIRECTIONAL_STREAM
, session
, url3
, LOWEST
, BoundNetLog(),
2670 callback3
.callback()));
2672 EXPECT_EQ(0u, session
->num_active_streams());
2673 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2674 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2676 // Cancel the first stream; this will allow the second stream to be created.
2677 EXPECT_TRUE(spdy_stream1
.get() != NULL
);
2678 spdy_stream1
->Cancel();
2679 EXPECT_EQ(NULL
, spdy_stream1
.get());
2681 EXPECT_EQ(OK
, callback2
.WaitForResult());
2682 EXPECT_EQ(0u, session
->num_active_streams());
2683 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2684 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2686 // Cancel the second stream; this will allow the third stream to be created.
2687 base::WeakPtr
<SpdyStream
> spdy_stream2
= request2
.ReleaseStream();
2688 spdy_stream2
->Cancel();
2689 EXPECT_EQ(NULL
, spdy_stream2
.get());
2691 EXPECT_EQ(OK
, callback3
.WaitForResult());
2692 EXPECT_EQ(0u, session
->num_active_streams());
2693 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2694 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2696 // Cancel the third stream.
2697 base::WeakPtr
<SpdyStream
> spdy_stream3
= request3
.ReleaseStream();
2698 spdy_stream3
->Cancel();
2699 EXPECT_EQ(NULL
, spdy_stream3
.get());
2700 EXPECT_EQ(0u, session
->num_active_streams());
2701 EXPECT_EQ(kInitialMaxConcurrentStreams
- 1, session
->num_created_streams());
2702 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2705 // Test that SpdySession::DoReadLoop reads data from the socket
2706 // without yielding. This test makes 32k - 1 bytes of data available
2707 // on the socket for reading. It then verifies that it has read all
2708 // the available data without yielding.
2709 TEST_P(SpdySessionTest
, ReadDataWithoutYielding
) {
2710 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2711 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2713 scoped_ptr
<SpdyFrame
> req1(
2714 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2715 MockWrite writes
[] = {
2716 CreateMockWrite(*req1
, 0),
2719 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2720 // (-spdy_data_frame_size).
2721 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2722 const int kPayloadSize
=
2723 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2724 TestDataStream test_stream
;
2725 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
2726 char* payload_data
= payload
->data();
2727 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2729 scoped_ptr
<SpdyFrame
> partial_data_frame(
2730 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2731 scoped_ptr
<SpdyFrame
> finish_data_frame(
2732 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
- 1, DATA_FLAG_FIN
));
2734 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2736 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2738 MockRead reads
[] = {
2739 CreateMockRead(*resp1
, 1),
2740 CreateMockRead(*partial_data_frame
, 2),
2741 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2742 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2743 CreateMockRead(*finish_data_frame
, 5, SYNCHRONOUS
),
2744 MockRead(ASYNC
, 0, 6) // EOF
2747 // Create SpdySession and SpdyStream and send the request.
2748 DeterministicSocketData
data(reads
, arraysize(reads
),
2749 writes
, arraysize(writes
));
2750 data
.set_connect_data(connect_data
);
2751 session_deps_
.host_resolver
->set_synchronous_mode(true);
2752 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2754 CreateDeterministicNetworkSession();
2756 base::WeakPtr
<SpdySession
> session
=
2757 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2759 GURL
url1(kDefaultURL
);
2760 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2761 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2762 session
, url1
, MEDIUM
, BoundNetLog());
2763 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2764 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2765 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2766 spdy_stream1
->SetDelegate(&delegate1
);
2768 scoped_ptr
<SpdyHeaderBlock
> headers1(
2769 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2770 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2771 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2773 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2775 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2777 // Run until 1st read.
2778 EXPECT_EQ(0u, delegate1
.stream_id());
2780 EXPECT_EQ(1u, delegate1
.stream_id());
2781 EXPECT_EQ(0u, observer
.executed_count());
2783 // Read all the data and verify SpdySession::DoReadLoop has not
2786 EXPECT_EQ(NULL
, spdy_stream1
.get());
2788 // Verify task observer's executed_count is zero, which indicates DoRead read
2789 // all the available data.
2790 EXPECT_EQ(0u, observer
.executed_count());
2791 EXPECT_TRUE(data
.at_write_eof());
2792 EXPECT_TRUE(data
.at_read_eof());
2795 // Test that SpdySession::DoReadLoop yields while reading the
2796 // data. This test makes 32k + 1 bytes of data available on the socket
2797 // for reading. It then verifies that DoRead has yielded even though
2798 // there is data available for it to read (i.e, socket()->Read didn't
2799 // return ERR_IO_PENDING during socket reads).
2800 TEST_P(SpdySessionTest
, TestYieldingDuringReadData
) {
2801 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2802 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2804 scoped_ptr
<SpdyFrame
> req1(
2805 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2806 MockWrite writes
[] = {
2807 CreateMockWrite(*req1
, 0),
2810 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2811 // (-spdy_data_frame_size).
2812 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2813 const int kPayloadSize
=
2814 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2815 TestDataStream test_stream
;
2816 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
2817 char* payload_data
= payload
->data();
2818 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2820 scoped_ptr
<SpdyFrame
> partial_data_frame(
2821 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2822 scoped_ptr
<SpdyFrame
> finish_data_frame(
2823 framer
.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN
));
2825 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2827 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2828 MockRead reads
[] = {
2829 CreateMockRead(*resp1
, 1),
2830 CreateMockRead(*partial_data_frame
, 2),
2831 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2832 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2833 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2834 CreateMockRead(*finish_data_frame
, 6, SYNCHRONOUS
),
2835 MockRead(ASYNC
, 0, 7) // EOF
2838 // Create SpdySession and SpdyStream and send the request.
2839 DeterministicSocketData
data(reads
, arraysize(reads
),
2840 writes
, arraysize(writes
));
2841 data
.set_connect_data(connect_data
);
2842 session_deps_
.host_resolver
->set_synchronous_mode(true);
2843 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2845 CreateDeterministicNetworkSession();
2847 base::WeakPtr
<SpdySession
> session
=
2848 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2850 GURL
url1(kDefaultURL
);
2851 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2852 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2853 session
, url1
, MEDIUM
, BoundNetLog());
2854 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2855 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2856 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2857 spdy_stream1
->SetDelegate(&delegate1
);
2859 scoped_ptr
<SpdyHeaderBlock
> headers1(
2860 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2861 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2862 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2864 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2866 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2868 // Run until 1st read.
2869 EXPECT_EQ(0u, delegate1
.stream_id());
2871 EXPECT_EQ(1u, delegate1
.stream_id());
2872 EXPECT_EQ(0u, observer
.executed_count());
2874 // Read all the data and verify SpdySession::DoReadLoop has posted a
2877 EXPECT_EQ(NULL
, spdy_stream1
.get());
2879 // Verify task observer's executed_count is 1, which indicates DoRead has
2880 // posted only one task and thus yielded though there is data available for it
2882 EXPECT_EQ(1u, observer
.executed_count());
2883 EXPECT_TRUE(data
.at_write_eof());
2884 EXPECT_TRUE(data
.at_read_eof());
2887 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2888 // + async, by doing the following MockReads.
2890 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2891 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2893 // The above reads 26K synchronously. Since that is less that 32K, we
2894 // will attempt to read again. However, that DoRead() will return
2895 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2896 // yield. When we come back, DoRead() will read the results from the
2897 // async read, and rest of the data synchronously.
2898 TEST_P(SpdySessionTest
, TestYieldingDuringAsyncReadData
) {
2899 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2900 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2902 scoped_ptr
<SpdyFrame
> req1(
2903 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2904 MockWrite writes
[] = {
2905 CreateMockWrite(*req1
, 0),
2908 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2909 // (-spdy_data_frame_size).
2910 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2911 TestDataStream test_stream
;
2912 const int kEightKPayloadSize
=
2913 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2914 scoped_refptr
<net::IOBuffer
> eightk_payload(
2915 new net::IOBuffer(kEightKPayloadSize
));
2916 char* eightk_payload_data
= eightk_payload
->data();
2917 test_stream
.GetBytes(eightk_payload_data
, kEightKPayloadSize
);
2919 // Build buffer of 2k size.
2920 TestDataStream test_stream2
;
2921 const int kTwoKPayloadSize
= kEightKPayloadSize
- 6 * 1024;
2922 scoped_refptr
<net::IOBuffer
> twok_payload(
2923 new net::IOBuffer(kTwoKPayloadSize
));
2924 char* twok_payload_data
= twok_payload
->data();
2925 test_stream2
.GetBytes(twok_payload_data
, kTwoKPayloadSize
);
2927 scoped_ptr
<SpdyFrame
> eightk_data_frame(framer
.CreateDataFrame(
2928 1, eightk_payload_data
, kEightKPayloadSize
, DATA_FLAG_NONE
));
2929 scoped_ptr
<SpdyFrame
> twok_data_frame(framer
.CreateDataFrame(
2930 1, twok_payload_data
, kTwoKPayloadSize
, DATA_FLAG_NONE
));
2931 scoped_ptr
<SpdyFrame
> finish_data_frame(framer
.CreateDataFrame(
2932 1, "h", 1, DATA_FLAG_FIN
));
2934 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2936 MockRead reads
[] = {
2937 CreateMockRead(*resp1
, 1),
2938 CreateMockRead(*eightk_data_frame
, 2),
2939 CreateMockRead(*eightk_data_frame
, 3, SYNCHRONOUS
),
2940 CreateMockRead(*eightk_data_frame
, 4, SYNCHRONOUS
),
2941 CreateMockRead(*twok_data_frame
, 5, SYNCHRONOUS
),
2942 CreateMockRead(*eightk_data_frame
, 6, ASYNC
),
2943 CreateMockRead(*eightk_data_frame
, 7, SYNCHRONOUS
),
2944 CreateMockRead(*eightk_data_frame
, 8, SYNCHRONOUS
),
2945 CreateMockRead(*eightk_data_frame
, 9, SYNCHRONOUS
),
2946 CreateMockRead(*twok_data_frame
, 10, SYNCHRONOUS
),
2947 CreateMockRead(*finish_data_frame
, 11, SYNCHRONOUS
),
2948 MockRead(ASYNC
, 0, 12) // EOF
2951 // Create SpdySession and SpdyStream and send the request.
2952 DeterministicSocketData
data(reads
, arraysize(reads
),
2953 writes
, arraysize(writes
));
2954 data
.set_connect_data(connect_data
);
2955 session_deps_
.host_resolver
->set_synchronous_mode(true);
2956 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2958 CreateDeterministicNetworkSession();
2960 base::WeakPtr
<SpdySession
> session
=
2961 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2963 GURL
url1(kDefaultURL
);
2964 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2965 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2966 session
, url1
, MEDIUM
, BoundNetLog());
2967 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2968 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2969 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2970 spdy_stream1
->SetDelegate(&delegate1
);
2972 scoped_ptr
<SpdyHeaderBlock
> headers1(
2973 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2974 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2975 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2977 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2978 // posting of tasks.
2979 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2981 // Run until 1st read.
2982 EXPECT_EQ(0u, delegate1
.stream_id());
2984 EXPECT_EQ(1u, delegate1
.stream_id());
2985 EXPECT_EQ(0u, observer
.executed_count());
2987 // Read all the data and verify SpdySession::DoReadLoop has posted a
2990 EXPECT_EQ(NULL
, spdy_stream1
.get());
2992 // Verify task observer's executed_count is 1, which indicates DoRead has
2993 // posted only one task and thus yielded though there is data available for
2995 EXPECT_EQ(1u, observer
.executed_count());
2996 EXPECT_TRUE(data
.at_write_eof());
2997 EXPECT_TRUE(data
.at_read_eof());
3000 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
3001 // nothing blows up.
3002 TEST_P(SpdySessionTest
, GoAwayWhileInDoReadLoop
) {
3003 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3004 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3006 scoped_ptr
<SpdyFrame
> req1(
3007 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
3008 MockWrite writes
[] = {
3009 CreateMockWrite(*req1
, 0),
3012 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3013 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3014 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
3016 MockRead reads
[] = {
3017 CreateMockRead(*resp1
, 1),
3018 CreateMockRead(*body1
, 2),
3019 CreateMockRead(*goaway
, 3),
3022 // Create SpdySession and SpdyStream and send the request.
3023 DeterministicSocketData
data(reads
, arraysize(reads
),
3024 writes
, arraysize(writes
));
3025 data
.set_connect_data(connect_data
);
3026 session_deps_
.host_resolver
->set_synchronous_mode(true);
3027 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3029 CreateDeterministicNetworkSession();
3031 base::WeakPtr
<SpdySession
> session
=
3032 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3034 GURL
url1(kDefaultURL
);
3035 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3036 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3037 session
, url1
, MEDIUM
, BoundNetLog());
3038 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3039 spdy_stream1
->SetDelegate(&delegate1
);
3040 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
3041 EXPECT_EQ(0u, spdy_stream1
->stream_id());
3043 scoped_ptr
<SpdyHeaderBlock
> headers1(
3044 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
3045 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
3046 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3048 // Run until 1st read.
3049 EXPECT_EQ(0u, spdy_stream1
->stream_id());
3051 EXPECT_EQ(1u, spdy_stream1
->stream_id());
3053 // Run until GoAway.
3055 EXPECT_EQ(NULL
, spdy_stream1
.get());
3056 EXPECT_TRUE(data
.at_write_eof());
3057 EXPECT_TRUE(data
.at_read_eof());
3058 EXPECT_TRUE(session
== NULL
);
3061 // Within this framework, a SpdySession should be initialized with
3062 // flow control disabled for protocol version 2, with flow control
3063 // enabled only for streams for protocol version 3, and with flow
3064 // control enabled for streams and sessions for higher versions.
3065 TEST_P(SpdySessionTest
, ProtocolNegotiation
) {
3066 session_deps_
.host_resolver
->set_synchronous_mode(true);
3068 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3069 MockRead reads
[] = {
3070 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3072 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3073 data
.set_connect_data(connect_data
);
3074 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3076 CreateNetworkSession();
3077 base::WeakPtr
<SpdySession
> session
=
3078 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3080 EXPECT_EQ(spdy_util_
.spdy_version(),
3081 session
->buffered_spdy_framer_
->protocol_version());
3082 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3083 session
->flow_control_state());
3084 EXPECT_EQ(kSpdySessionInitialWindowSize
,
3085 session
->session_send_window_size_
);
3086 EXPECT_EQ(kSpdySessionInitialWindowSize
,
3087 session
->session_recv_window_size_
);
3088 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3091 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3092 // pointers to the idle session are currently held.
3093 TEST_P(SpdySessionTest
, CloseOneIdleConnection
) {
3094 ClientSocketPoolManager::set_max_sockets_per_group(
3095 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3096 ClientSocketPoolManager::set_max_sockets_per_pool(
3097 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3099 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3100 MockRead reads
[] = {
3101 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3103 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3104 data
.set_connect_data(connect_data
);
3105 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3106 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3108 CreateNetworkSession();
3110 TransportClientSocketPool
* pool
=
3111 http_session_
->GetTransportSocketPool(
3112 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3114 // Create an idle SPDY session.
3115 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3116 PRIVACY_MODE_DISABLED
);
3117 base::WeakPtr
<SpdySession
> session1
=
3118 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3119 EXPECT_FALSE(pool
->IsStalled());
3121 // Trying to create a new connection should cause the pool to be stalled, and
3122 // post a task asynchronously to try and close the session.
3123 TestCompletionCallback callback2
;
3124 HostPortPair
host_port2("2.com", 80);
3125 scoped_refptr
<TransportSocketParams
> params2(
3126 new TransportSocketParams(
3127 host_port2
, false, false, OnHostResolutionCallback(),
3128 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3129 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3130 EXPECT_EQ(ERR_IO_PENDING
,
3131 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3132 callback2
.callback(), pool
, BoundNetLog()));
3133 EXPECT_TRUE(pool
->IsStalled());
3135 // The socket pool should close the connection asynchronously and establish a
3137 EXPECT_EQ(OK
, callback2
.WaitForResult());
3138 EXPECT_FALSE(pool
->IsStalled());
3139 EXPECT_TRUE(session1
== NULL
);
3142 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3143 // pointers to the idle session are currently held, in the case the SPDY session
3145 TEST_P(SpdySessionTest
, CloseOneIdleConnectionWithAlias
) {
3146 ClientSocketPoolManager::set_max_sockets_per_group(
3147 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3148 ClientSocketPoolManager::set_max_sockets_per_pool(
3149 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3151 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3152 MockRead reads
[] = {
3153 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3155 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3156 data
.set_connect_data(connect_data
);
3157 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3158 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3160 session_deps_
.host_resolver
->set_synchronous_mode(true);
3161 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3162 "1.com", "192.168.0.2", std::string());
3163 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3164 "2.com", "192.168.0.2", std::string());
3165 // Not strictly needed.
3166 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3167 "3.com", "192.168.0.3", std::string());
3169 CreateNetworkSession();
3171 TransportClientSocketPool
* pool
=
3172 http_session_
->GetTransportSocketPool(
3173 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3175 // Create an idle SPDY session.
3176 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3177 PRIVACY_MODE_DISABLED
);
3178 base::WeakPtr
<SpdySession
> session1
=
3179 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3180 EXPECT_FALSE(pool
->IsStalled());
3182 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3183 SpdySessionKey
key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3184 PRIVACY_MODE_DISABLED
);
3185 HostResolver::RequestInfo
info(key2
.host_port_pair());
3186 AddressList addresses
;
3187 // Pre-populate the DNS cache, since a synchronous resolution is required in
3188 // order to create the alias.
3189 session_deps_
.host_resolver
->Resolve(info
,
3192 CompletionCallback(),
3195 // Get a session for |key2|, which should return the session created earlier.
3196 base::WeakPtr
<SpdySession
> session2
=
3197 spdy_session_pool_
->FindAvailableSession(key2
, BoundNetLog());
3198 ASSERT_EQ(session1
.get(), session2
.get());
3199 EXPECT_FALSE(pool
->IsStalled());
3201 // Trying to create a new connection should cause the pool to be stalled, and
3202 // post a task asynchronously to try and close the session.
3203 TestCompletionCallback callback3
;
3204 HostPortPair
host_port3("3.com", 80);
3205 scoped_refptr
<TransportSocketParams
> params3(
3206 new TransportSocketParams(
3207 host_port3
, false, false, OnHostResolutionCallback(),
3208 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3209 scoped_ptr
<ClientSocketHandle
> connection3(new ClientSocketHandle
);
3210 EXPECT_EQ(ERR_IO_PENDING
,
3211 connection3
->Init(host_port3
.ToString(), params3
, DEFAULT_PRIORITY
,
3212 callback3
.callback(), pool
, BoundNetLog()));
3213 EXPECT_TRUE(pool
->IsStalled());
3215 // The socket pool should close the connection asynchronously and establish a
3217 EXPECT_EQ(OK
, callback3
.WaitForResult());
3218 EXPECT_FALSE(pool
->IsStalled());
3219 EXPECT_TRUE(session1
== NULL
);
3220 EXPECT_TRUE(session2
== NULL
);
3223 // Tests that when a SPDY session becomes idle, it closes itself if there is
3224 // a lower layer pool stalled on the per-pool socket limit.
3225 TEST_P(SpdySessionTest
, CloseSessionOnIdleWhenPoolStalled
) {
3226 ClientSocketPoolManager::set_max_sockets_per_group(
3227 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3228 ClientSocketPoolManager::set_max_sockets_per_pool(
3229 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3231 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3232 MockRead reads
[] = {
3233 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3235 scoped_ptr
<SpdyFrame
> req1(
3236 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3237 scoped_ptr
<SpdyFrame
> cancel1(
3238 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3239 MockWrite writes
[] = {
3240 CreateMockWrite(*req1
, 1),
3241 CreateMockWrite(*cancel1
, 1),
3243 StaticSocketDataProvider
data(reads
, arraysize(reads
),
3244 writes
, arraysize(writes
));
3245 data
.set_connect_data(connect_data
);
3246 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3248 MockRead http_reads
[] = {
3249 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3251 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
3253 http_data
.set_connect_data(connect_data
);
3254 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
3257 CreateNetworkSession();
3259 TransportClientSocketPool
* pool
=
3260 http_session_
->GetTransportSocketPool(
3261 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3263 // Create a SPDY session.
3264 GURL
url1(kDefaultURL
);
3265 SpdySessionKey
key1(HostPortPair(url1
.host(), 80),
3266 ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3267 base::WeakPtr
<SpdySession
> session1
=
3268 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3269 EXPECT_FALSE(pool
->IsStalled());
3271 // Create a stream using the session, and send a request.
3273 TestCompletionCallback callback1
;
3274 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3275 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3276 session1
, url1
, DEFAULT_PRIORITY
,
3278 ASSERT_TRUE(spdy_stream1
.get());
3279 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3280 spdy_stream1
->SetDelegate(&delegate1
);
3282 scoped_ptr
<SpdyHeaderBlock
> headers1(
3283 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
3284 EXPECT_EQ(ERR_IO_PENDING
,
3285 spdy_stream1
->SendRequestHeaders(
3286 headers1
.Pass(), NO_MORE_DATA_TO_SEND
));
3287 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3289 base::MessageLoop::current()->RunUntilIdle();
3291 // Trying to create a new connection should cause the pool to be stalled, and
3292 // post a task asynchronously to try and close the session.
3293 TestCompletionCallback callback2
;
3294 HostPortPair
host_port2("2.com", 80);
3295 scoped_refptr
<TransportSocketParams
> params2(
3296 new TransportSocketParams(
3297 host_port2
, false, false, OnHostResolutionCallback(),
3298 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3299 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3300 EXPECT_EQ(ERR_IO_PENDING
,
3301 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3302 callback2
.callback(), pool
, BoundNetLog()));
3303 EXPECT_TRUE(pool
->IsStalled());
3305 // Running the message loop should cause the socket pool to ask the SPDY
3306 // session to close an idle socket, but since the socket is in use, nothing
3308 base::RunLoop().RunUntilIdle();
3309 EXPECT_TRUE(pool
->IsStalled());
3310 EXPECT_FALSE(callback2
.have_result());
3312 // Cancelling the request should result in the session's socket being
3313 // closed, since the pool is stalled.
3314 ASSERT_TRUE(spdy_stream1
.get());
3315 spdy_stream1
->Cancel();
3316 base::RunLoop().RunUntilIdle();
3317 ASSERT_FALSE(pool
->IsStalled());
3318 EXPECT_EQ(OK
, callback2
.WaitForResult());
3321 // Verify that SpdySessionKey and therefore SpdySession is different when
3322 // privacy mode is enabled or disabled.
3323 TEST_P(SpdySessionTest
, SpdySessionKeyPrivacyMode
) {
3324 CreateDeterministicNetworkSession();
3326 HostPortPair
host_port_pair("www.google.com", 443);
3327 SpdySessionKey
key_privacy_enabled(host_port_pair
, ProxyServer::Direct(),
3328 PRIVACY_MODE_ENABLED
);
3329 SpdySessionKey
key_privacy_disabled(host_port_pair
, ProxyServer::Direct(),
3330 PRIVACY_MODE_DISABLED
);
3332 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3333 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3335 // Add SpdySession with PrivacyMode Enabled to the pool.
3336 base::WeakPtr
<SpdySession
> session_privacy_enabled
=
3337 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_enabled
);
3339 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3340 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3342 // Add SpdySession with PrivacyMode Disabled to the pool.
3343 base::WeakPtr
<SpdySession
> session_privacy_disabled
=
3344 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_disabled
);
3346 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3347 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3349 session_privacy_enabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3350 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3351 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3353 session_privacy_disabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3354 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3355 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3358 // Delegate that creates another stream when its stream is closed.
3359 class StreamCreatingDelegate
: public test::StreamDelegateDoNothing
{
3361 StreamCreatingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3362 const base::WeakPtr
<SpdySession
>& session
)
3363 : StreamDelegateDoNothing(stream
),
3364 session_(session
) {}
3366 ~StreamCreatingDelegate() override
{}
3368 void OnClose(int status
) override
{
3369 GURL
url(kDefaultURL
);
3371 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3372 session_
, url
, MEDIUM
, BoundNetLog()));
3376 const base::WeakPtr
<SpdySession
> session_
;
3379 // Create another stream in response to a stream being reset. Nothing
3380 // should blow up. This is a regression test for
3381 // http://crbug.com/263690 .
3382 TEST_P(SpdySessionTest
, CreateStreamOnStreamReset
) {
3383 session_deps_
.host_resolver
->set_synchronous_mode(true);
3385 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3387 scoped_ptr
<SpdyFrame
> req(
3388 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
3389 MockWrite writes
[] = {
3390 CreateMockWrite(*req
, 0),
3393 scoped_ptr
<SpdyFrame
> rst(
3394 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
3395 MockRead reads
[] = {
3396 CreateMockRead(*rst
, 1),
3397 MockRead(ASYNC
, 0, 2) // EOF
3399 DeterministicSocketData
data(reads
, arraysize(reads
),
3400 writes
, arraysize(writes
));
3401 data
.set_connect_data(connect_data
);
3402 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3404 CreateDeterministicNetworkSession();
3406 base::WeakPtr
<SpdySession
> session
=
3407 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3409 GURL
url(kDefaultURL
);
3410 base::WeakPtr
<SpdyStream
> spdy_stream
=
3411 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3412 session
, url
, MEDIUM
, BoundNetLog());
3413 ASSERT_TRUE(spdy_stream
.get() != NULL
);
3414 EXPECT_EQ(0u, spdy_stream
->stream_id());
3416 StreamCreatingDelegate
delegate(spdy_stream
, session
);
3417 spdy_stream
->SetDelegate(&delegate
);
3419 scoped_ptr
<SpdyHeaderBlock
> headers(
3420 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
3421 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
3422 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
3424 EXPECT_EQ(0u, spdy_stream
->stream_id());
3428 EXPECT_EQ(1u, spdy_stream
->stream_id());
3430 // Cause the stream to be reset, which should cause another stream
3434 EXPECT_EQ(NULL
, spdy_stream
.get());
3435 EXPECT_TRUE(delegate
.StreamIsClosed());
3436 EXPECT_EQ(0u, session
->num_active_streams());
3437 EXPECT_EQ(1u, session
->num_created_streams());
3440 // The tests below are only for SPDY/3 and above.
3442 TEST_P(SpdySessionTest
, UpdateStreamsSendWindowSize
) {
3443 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3445 SettingsMap new_settings
;
3446 int32 window_size
= 1;
3447 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
3448 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, window_size
);
3450 // Set up the socket so we read a SETTINGS frame that sets
3451 // INITIAL_WINDOW_SIZE.
3452 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3453 scoped_ptr
<SpdyFrame
> settings_frame(
3454 spdy_util_
.ConstructSpdySettings(new_settings
));
3455 MockRead reads
[] = {
3456 CreateMockRead(*settings_frame
, 0),
3457 MockRead(ASYNC
, 0, 1) // EOF
3460 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
3461 MockWrite writes
[] = {
3462 CreateMockWrite(*settings_ack
, 2),
3465 session_deps_
.host_resolver
->set_synchronous_mode(true);
3467 DeterministicSocketData
data(reads
, arraysize(reads
),
3468 writes
, arraysize(writes
));
3469 data
.set_connect_data(connect_data
);
3470 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3472 CreateDeterministicNetworkSession();
3474 base::WeakPtr
<SpdySession
> session
=
3475 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3476 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3477 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3478 session
, test_url_
, MEDIUM
, BoundNetLog());
3479 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
3480 TestCompletionCallback callback1
;
3481 EXPECT_NE(spdy_stream1
->send_window_size(), window_size
);
3483 data
.RunFor(1); // Process the SETTINGS frame, but not the EOF
3484 base::MessageLoop::current()->RunUntilIdle();
3485 EXPECT_EQ(session
->stream_initial_send_window_size(), window_size
);
3486 EXPECT_EQ(spdy_stream1
->send_window_size(), window_size
);
3488 // Release the first one, this will allow the second to be created.
3489 spdy_stream1
->Cancel();
3490 EXPECT_EQ(NULL
, spdy_stream1
.get());
3492 base::WeakPtr
<SpdyStream
> spdy_stream2
=
3493 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3494 session
, test_url_
, MEDIUM
, BoundNetLog());
3495 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
3496 EXPECT_EQ(spdy_stream2
->send_window_size(), window_size
);
3497 spdy_stream2
->Cancel();
3498 EXPECT_EQ(NULL
, spdy_stream2
.get());
3501 // The tests below are only for SPDY/3.1 and above.
3503 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3504 // adjust the session receive window size for SPDY 3.1 and higher. In
3505 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3506 // sending a WINDOW_UPDATE frame for a large enough delta.
3507 TEST_P(SpdySessionTest
, AdjustRecvWindowSize
) {
3508 if (GetParam() < kProtoSPDY31
)
3511 session_deps_
.host_resolver
->set_synchronous_mode(true);
3513 const int32 delta_window_size
= 100;
3515 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3516 MockRead reads
[] = {
3517 MockRead(ASYNC
, 0, 1) // EOF
3519 scoped_ptr
<SpdyFrame
> window_update(
3520 spdy_util_
.ConstructSpdyWindowUpdate(
3521 kSessionFlowControlStreamId
,
3522 kSpdySessionInitialWindowSize
+ delta_window_size
));
3523 MockWrite writes
[] = {
3524 CreateMockWrite(*window_update
, 0),
3526 DeterministicSocketData
data(reads
, arraysize(reads
),
3527 writes
, arraysize(writes
));
3528 data
.set_connect_data(connect_data
);
3529 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3531 CreateDeterministicNetworkSession();
3532 base::WeakPtr
<SpdySession
> session
=
3533 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3534 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3535 session
->flow_control_state());
3537 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3538 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3540 session
->IncreaseRecvWindowSize(delta_window_size
);
3541 EXPECT_EQ(kSpdySessionInitialWindowSize
+ delta_window_size
,
3542 session
->session_recv_window_size_
);
3543 EXPECT_EQ(delta_window_size
, session
->session_unacked_recv_window_bytes_
);
3545 // Should trigger sending a WINDOW_UPDATE frame.
3546 session
->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize
);
3547 EXPECT_EQ(kSpdySessionInitialWindowSize
+ delta_window_size
+
3548 kSpdySessionInitialWindowSize
,
3549 session
->session_recv_window_size_
);
3550 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3554 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3555 session
->in_io_loop_
= true;
3556 session
->DecreaseRecvWindowSize(
3557 kSpdySessionInitialWindowSize
+ delta_window_size
+
3558 kSpdySessionInitialWindowSize
);
3559 session
->in_io_loop_
= false;
3560 EXPECT_EQ(0, session
->session_recv_window_size_
);
3561 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3564 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3565 // adjust the session send window size when the "enable_spdy_31" flag
3567 TEST_P(SpdySessionTest
, AdjustSendWindowSize
) {
3568 if (GetParam() < kProtoSPDY31
)
3571 session_deps_
.host_resolver
->set_synchronous_mode(true);
3573 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3574 MockRead reads
[] = {
3575 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3577 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3578 data
.set_connect_data(connect_data
);
3579 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3581 CreateNetworkSession();
3582 base::WeakPtr
<SpdySession
> session
=
3583 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3584 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3585 session
->flow_control_state());
3587 const int32 delta_window_size
= 100;
3589 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3591 session
->IncreaseSendWindowSize(delta_window_size
);
3592 EXPECT_EQ(kSpdySessionInitialWindowSize
+ delta_window_size
,
3593 session
->session_send_window_size_
);
3595 session
->DecreaseSendWindowSize(delta_window_size
);
3596 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3599 // Incoming data for an inactive stream should not cause the session
3600 // receive window size to decrease, but it should cause the unacked
3601 // bytes to increase.
3602 TEST_P(SpdySessionTest
, SessionFlowControlInactiveStream
) {
3603 if (GetParam() < kProtoSPDY31
)
3606 session_deps_
.host_resolver
->set_synchronous_mode(true);
3608 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3609 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(1, false));
3610 MockRead reads
[] = {
3611 CreateMockRead(*resp
, 0),
3612 MockRead(ASYNC
, 0, 1) // EOF
3614 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
3615 data
.set_connect_data(connect_data
);
3616 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3618 CreateDeterministicNetworkSession();
3619 base::WeakPtr
<SpdySession
> session
=
3620 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3621 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3622 session
->flow_control_state());
3624 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3625 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3629 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3630 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
3635 // A delegate that drops any received data.
3636 class DropReceivedDataDelegate
: public test::StreamDelegateSendImmediate
{
3638 DropReceivedDataDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3639 base::StringPiece data
)
3640 : StreamDelegateSendImmediate(stream
, data
) {}
3642 ~DropReceivedDataDelegate() override
{}
3644 // Drop any received data.
3645 void OnDataReceived(scoped_ptr
<SpdyBuffer
> buffer
) override
{}
3648 // Send data back and forth but use a delegate that drops its received
3649 // data. The receive window should still increase to its original
3650 // value, i.e. we shouldn't "leak" receive window bytes.
3651 TEST_P(SpdySessionTest
, SessionFlowControlNoReceiveLeaks
) {
3652 if (GetParam() < kProtoSPDY31
)
3655 const char kStreamUrl
[] = "http://www.google.com/";
3657 const int32 msg_data_size
= 100;
3658 const std::string
msg_data(msg_data_size
, 'a');
3660 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3662 scoped_ptr
<SpdyFrame
> req(
3663 spdy_util_
.ConstructSpdyPost(
3664 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3665 scoped_ptr
<SpdyFrame
> msg(
3666 spdy_util_
.ConstructSpdyBodyFrame(
3667 1, msg_data
.data(), msg_data_size
, false));
3668 MockWrite writes
[] = {
3669 CreateMockWrite(*req
, 0),
3670 CreateMockWrite(*msg
, 2),
3673 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3674 scoped_ptr
<SpdyFrame
> echo(
3675 spdy_util_
.ConstructSpdyBodyFrame(
3676 1, msg_data
.data(), msg_data_size
, false));
3677 scoped_ptr
<SpdyFrame
> window_update(
3678 spdy_util_
.ConstructSpdyWindowUpdate(
3679 kSessionFlowControlStreamId
, msg_data_size
));
3680 MockRead reads
[] = {
3681 CreateMockRead(*resp
, 1),
3682 CreateMockRead(*echo
, 3),
3683 MockRead(ASYNC
, 0, 4) // EOF
3686 // Create SpdySession and SpdyStream and send the request.
3687 DeterministicSocketData
data(reads
, arraysize(reads
),
3688 writes
, arraysize(writes
));
3689 data
.set_connect_data(connect_data
);
3690 session_deps_
.host_resolver
->set_synchronous_mode(true);
3691 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3693 CreateDeterministicNetworkSession();
3695 base::WeakPtr
<SpdySession
> session
=
3696 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3698 GURL
url(kStreamUrl
);
3699 base::WeakPtr
<SpdyStream
> stream
=
3700 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3701 session
, url
, MEDIUM
, BoundNetLog());
3702 ASSERT_TRUE(stream
.get() != NULL
);
3703 EXPECT_EQ(0u, stream
->stream_id());
3705 DropReceivedDataDelegate
delegate(stream
, msg_data
);
3706 stream
->SetDelegate(&delegate
);
3708 scoped_ptr
<SpdyHeaderBlock
> headers(
3709 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3710 EXPECT_EQ(ERR_IO_PENDING
,
3711 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3712 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3714 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3715 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3719 EXPECT_TRUE(data
.at_write_eof());
3720 EXPECT_TRUE(data
.at_read_eof());
3722 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3723 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3726 EXPECT_EQ(NULL
, stream
.get());
3728 EXPECT_EQ(OK
, delegate
.WaitForClose());
3730 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3731 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3734 // Send data back and forth but close the stream before its data frame
3735 // can be written to the socket. The send window should then increase
3736 // to its original value, i.e. we shouldn't "leak" send window bytes.
3737 TEST_P(SpdySessionTest
, SessionFlowControlNoSendLeaks
) {
3738 if (GetParam() < kProtoSPDY31
)
3741 const char kStreamUrl
[] = "http://www.google.com/";
3743 const int32 msg_data_size
= 100;
3744 const std::string
msg_data(msg_data_size
, 'a');
3746 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3748 scoped_ptr
<SpdyFrame
> req(
3749 spdy_util_
.ConstructSpdyPost(
3750 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3751 MockWrite writes
[] = {
3752 CreateMockWrite(*req
, 0),
3755 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3756 MockRead reads
[] = {
3757 CreateMockRead(*resp
, 1),
3758 MockRead(ASYNC
, 0, 2) // EOF
3761 // Create SpdySession and SpdyStream and send the request.
3762 DeterministicSocketData
data(reads
, arraysize(reads
),
3763 writes
, arraysize(writes
));
3764 data
.set_connect_data(connect_data
);
3765 session_deps_
.host_resolver
->set_synchronous_mode(true);
3766 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3768 CreateDeterministicNetworkSession();
3770 base::WeakPtr
<SpdySession
> session
=
3771 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3773 GURL
url(kStreamUrl
);
3774 base::WeakPtr
<SpdyStream
> stream
=
3775 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3776 session
, url
, MEDIUM
, BoundNetLog());
3777 ASSERT_TRUE(stream
.get() != NULL
);
3778 EXPECT_EQ(0u, stream
->stream_id());
3780 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3781 stream
->SetDelegate(&delegate
);
3783 scoped_ptr
<SpdyHeaderBlock
> headers(
3784 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3785 EXPECT_EQ(ERR_IO_PENDING
,
3786 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3787 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3789 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3793 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3797 EXPECT_TRUE(data
.at_write_eof());
3798 EXPECT_TRUE(data
.at_read_eof());
3800 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3801 session
->session_send_window_size_
);
3803 // Closing the stream should increase the session's send window.
3805 EXPECT_EQ(NULL
, stream
.get());
3807 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3809 EXPECT_EQ(OK
, delegate
.WaitForClose());
3812 // Send data back and forth; the send and receive windows should
3813 // change appropriately.
3814 TEST_P(SpdySessionTest
, SessionFlowControlEndToEnd
) {
3815 if (GetParam() < kProtoSPDY31
)
3818 const char kStreamUrl
[] = "http://www.google.com/";
3820 const int32 msg_data_size
= 100;
3821 const std::string
msg_data(msg_data_size
, 'a');
3823 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3825 scoped_ptr
<SpdyFrame
> req(
3826 spdy_util_
.ConstructSpdyPost(
3827 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3828 scoped_ptr
<SpdyFrame
> msg(
3829 spdy_util_
.ConstructSpdyBodyFrame(
3830 1, msg_data
.data(), msg_data_size
, false));
3831 MockWrite writes
[] = {
3832 CreateMockWrite(*req
, 0),
3833 CreateMockWrite(*msg
, 2),
3836 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3837 scoped_ptr
<SpdyFrame
> echo(
3838 spdy_util_
.ConstructSpdyBodyFrame(
3839 1, msg_data
.data(), msg_data_size
, false));
3840 scoped_ptr
<SpdyFrame
> window_update(
3841 spdy_util_
.ConstructSpdyWindowUpdate(
3842 kSessionFlowControlStreamId
, msg_data_size
));
3843 MockRead reads
[] = {
3844 CreateMockRead(*resp
, 1),
3845 CreateMockRead(*echo
, 3),
3846 CreateMockRead(*window_update
, 4),
3847 MockRead(ASYNC
, 0, 5) // EOF
3850 // Create SpdySession and SpdyStream and send the request.
3851 DeterministicSocketData
data(reads
, arraysize(reads
),
3852 writes
, arraysize(writes
));
3853 data
.set_connect_data(connect_data
);
3854 session_deps_
.host_resolver
->set_synchronous_mode(true);
3855 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3857 CreateDeterministicNetworkSession();
3859 base::WeakPtr
<SpdySession
> session
=
3860 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3862 GURL
url(kStreamUrl
);
3863 base::WeakPtr
<SpdyStream
> stream
=
3864 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3865 session
, url
, MEDIUM
, BoundNetLog());
3866 ASSERT_TRUE(stream
.get() != NULL
);
3867 EXPECT_EQ(0u, stream
->stream_id());
3869 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3870 stream
->SetDelegate(&delegate
);
3872 scoped_ptr
<SpdyHeaderBlock
> headers(
3873 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3874 EXPECT_EQ(ERR_IO_PENDING
,
3875 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3876 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3878 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3879 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3880 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3884 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3885 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3886 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3890 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3891 session
->session_send_window_size_
);
3892 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3893 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3897 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3898 session
->session_send_window_size_
);
3899 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3900 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3904 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3905 session
->session_send_window_size_
);
3906 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3907 session
->session_recv_window_size_
);
3908 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3912 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3913 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3914 session
->session_recv_window_size_
);
3915 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3917 EXPECT_TRUE(data
.at_write_eof());
3918 EXPECT_TRUE(data
.at_read_eof());
3920 EXPECT_EQ(msg_data
, delegate
.TakeReceivedData());
3922 // Draining the delegate's read queue should increase the session's
3924 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3925 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3926 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3929 EXPECT_EQ(NULL
, stream
.get());
3931 EXPECT_EQ(OK
, delegate
.WaitForClose());
3933 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3934 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3935 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3938 // Given a stall function and an unstall function, runs a test to make
3939 // sure that a stream resumes after unstall.
3940 void SpdySessionTest::RunResumeAfterUnstallTest(
3941 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
3942 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
3944 const char kStreamUrl
[] = "http://www.google.com/";
3945 GURL
url(kStreamUrl
);
3947 session_deps_
.host_resolver
->set_synchronous_mode(true);
3949 scoped_ptr
<SpdyFrame
> req(
3950 spdy_util_
.ConstructSpdyPost(
3951 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
3952 scoped_ptr
<SpdyFrame
> body(
3953 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
3954 MockWrite writes
[] = {
3955 CreateMockWrite(*req
, 0),
3956 CreateMockWrite(*body
, 1),
3959 scoped_ptr
<SpdyFrame
> resp(
3960 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3961 scoped_ptr
<SpdyFrame
> echo(
3962 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
3963 MockRead reads
[] = {
3964 CreateMockRead(*resp
, 2),
3965 MockRead(ASYNC
, 0, 0, 3), // EOF
3968 DeterministicSocketData
data(reads
, arraysize(reads
),
3969 writes
, arraysize(writes
));
3970 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3971 data
.set_connect_data(connect_data
);
3973 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3975 CreateDeterministicNetworkSession();
3976 base::WeakPtr
<SpdySession
> session
=
3977 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3978 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3979 session
->flow_control_state());
3981 base::WeakPtr
<SpdyStream
> stream
=
3982 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3983 session
, url
, LOWEST
, BoundNetLog());
3984 ASSERT_TRUE(stream
.get() != NULL
);
3986 test::StreamDelegateWithBody
delegate(stream
, kBodyDataStringPiece
);
3987 stream
->SetDelegate(&delegate
);
3989 EXPECT_FALSE(stream
->HasUrlFromHeaders());
3990 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
3992 scoped_ptr
<SpdyHeaderBlock
> headers(
3993 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
3994 EXPECT_EQ(ERR_IO_PENDING
,
3995 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3996 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3997 EXPECT_EQ(kStreamUrl
, stream
->GetUrlFromHeaders().spec());
3999 stall_function
.Run(session
.get(), stream
.get());
4003 EXPECT_TRUE(stream
->send_stalled_by_flow_control());
4005 unstall_function
.Run(session
.get(), stream
.get(), kBodyDataSize
);
4007 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4011 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
4013 EXPECT_TRUE(delegate
.send_headers_completed());
4014 EXPECT_EQ("200", delegate
.GetResponseHeaderValue(":status"));
4015 EXPECT_EQ(std::string(), delegate
.TakeReceivedData());
4016 EXPECT_TRUE(data
.at_write_eof());
4019 // Run the resume-after-unstall test with all possible stall and
4020 // unstall sequences.
4022 TEST_P(SpdySessionTest
, ResumeAfterUnstallSession
) {
4023 if (GetParam() < kProtoSPDY31
)
4026 RunResumeAfterUnstallTest(
4027 base::Bind(&SpdySessionTest::StallSessionOnly
,
4028 base::Unretained(this)),
4029 base::Bind(&SpdySessionTest::UnstallSessionOnly
,
4030 base::Unretained(this)));
4034 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4035 TEST_P(SpdySessionTest
, ResumeAfterUnstallStream
) {
4036 if (GetParam() < kProtoSPDY31
)
4039 RunResumeAfterUnstallTest(
4040 base::Bind(&SpdySessionTest::StallStreamOnly
,
4041 base::Unretained(this)),
4042 base::Bind(&SpdySessionTest::UnstallStreamOnly
,
4043 base::Unretained(this)));
4046 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallSessionStream
) {
4047 if (GetParam() < kProtoSPDY31
)
4050 RunResumeAfterUnstallTest(
4051 base::Bind(&SpdySessionTest::StallSessionStream
,
4052 base::Unretained(this)),
4053 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4054 base::Unretained(this)));
4057 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallSessionStream
) {
4058 if (GetParam() < kProtoSPDY31
)
4061 RunResumeAfterUnstallTest(
4062 base::Bind(&SpdySessionTest::StallStreamSession
,
4063 base::Unretained(this)),
4064 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4065 base::Unretained(this)));
4068 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallStreamSession
) {
4069 if (GetParam() < kProtoSPDY31
)
4072 RunResumeAfterUnstallTest(
4073 base::Bind(&SpdySessionTest::StallStreamSession
,
4074 base::Unretained(this)),
4075 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4076 base::Unretained(this)));
4079 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallStreamSession
) {
4080 if (GetParam() < kProtoSPDY31
)
4083 RunResumeAfterUnstallTest(
4084 base::Bind(&SpdySessionTest::StallSessionStream
,
4085 base::Unretained(this)),
4086 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4087 base::Unretained(this)));
4090 // Cause a stall by reducing the flow control send window to 0. The
4091 // streams should resume in priority order when that window is then
4093 TEST_P(SpdySessionTest
, ResumeByPriorityAfterSendWindowSizeIncrease
) {
4094 if (GetParam() < kProtoSPDY31
)
4097 const char kStreamUrl
[] = "http://www.google.com/";
4098 GURL
url(kStreamUrl
);
4100 session_deps_
.host_resolver
->set_synchronous_mode(true);
4102 scoped_ptr
<SpdyFrame
> req1(
4103 spdy_util_
.ConstructSpdyPost(
4104 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4105 scoped_ptr
<SpdyFrame
> req2(
4106 spdy_util_
.ConstructSpdyPost(
4107 kStreamUrl
, 3, kBodyDataSize
, MEDIUM
, NULL
, 0));
4108 scoped_ptr
<SpdyFrame
> body1(
4109 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
4110 scoped_ptr
<SpdyFrame
> body2(
4111 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4112 MockWrite writes
[] = {
4113 CreateMockWrite(*req1
, 0),
4114 CreateMockWrite(*req2
, 1),
4115 CreateMockWrite(*body2
, 2),
4116 CreateMockWrite(*body1
, 3),
4119 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4120 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4121 MockRead reads
[] = {
4122 CreateMockRead(*resp1
, 4),
4123 CreateMockRead(*resp2
, 5),
4124 MockRead(ASYNC
, 0, 0, 6), // EOF
4127 DeterministicSocketData
data(reads
, arraysize(reads
),
4128 writes
, arraysize(writes
));
4129 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4130 data
.set_connect_data(connect_data
);
4132 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4134 CreateDeterministicNetworkSession();
4135 base::WeakPtr
<SpdySession
> session
=
4136 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4137 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4138 session
->flow_control_state());
4140 base::WeakPtr
<SpdyStream
> stream1
=
4141 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4142 session
, url
, LOWEST
, BoundNetLog());
4143 ASSERT_TRUE(stream1
.get() != NULL
);
4145 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4146 stream1
->SetDelegate(&delegate1
);
4148 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4150 base::WeakPtr
<SpdyStream
> stream2
=
4151 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4152 session
, url
, MEDIUM
, BoundNetLog());
4153 ASSERT_TRUE(stream2
.get() != NULL
);
4155 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4156 stream2
->SetDelegate(&delegate2
);
4158 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4160 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4161 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4163 StallSessionSend(session
.get());
4165 scoped_ptr
<SpdyHeaderBlock
> headers1(
4166 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4167 EXPECT_EQ(ERR_IO_PENDING
,
4168 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4169 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4170 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4173 EXPECT_EQ(1u, stream1
->stream_id());
4174 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4176 scoped_ptr
<SpdyHeaderBlock
> headers2(
4177 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4178 EXPECT_EQ(ERR_IO_PENDING
,
4179 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4180 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4181 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4184 EXPECT_EQ(3u, stream2
->stream_id());
4185 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4187 // This should unstall only stream2.
4188 UnstallSessionSend(session
.get(), kBodyDataSize
);
4190 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4191 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4195 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4196 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4198 // This should then unstall stream1.
4199 UnstallSessionSend(session
.get(), kBodyDataSize
);
4201 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4202 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4206 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4207 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4209 EXPECT_TRUE(delegate1
.send_headers_completed());
4210 EXPECT_EQ("200", delegate1
.GetResponseHeaderValue(":status"));
4211 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4213 EXPECT_TRUE(delegate2
.send_headers_completed());
4214 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4215 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4217 EXPECT_TRUE(data
.at_write_eof());
4220 // Delegate that closes a given stream after sending its body.
4221 class StreamClosingDelegate
: public test::StreamDelegateWithBody
{
4223 StreamClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
4224 base::StringPiece data
)
4225 : StreamDelegateWithBody(stream
, data
) {}
4227 ~StreamClosingDelegate() override
{}
4229 void set_stream_to_close(const base::WeakPtr
<SpdyStream
>& stream_to_close
) {
4230 stream_to_close_
= stream_to_close
;
4233 void OnDataSent() override
{
4234 test::StreamDelegateWithBody::OnDataSent();
4235 if (stream_to_close_
.get()) {
4236 stream_to_close_
->Close();
4237 EXPECT_EQ(NULL
, stream_to_close_
.get());
4242 base::WeakPtr
<SpdyStream
> stream_to_close_
;
4245 // Cause a stall by reducing the flow control send window to
4246 // 0. Unstalling the session should properly handle deleted streams.
4247 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedStreams
) {
4248 if (GetParam() < kProtoSPDY31
)
4251 const char kStreamUrl
[] = "http://www.google.com/";
4252 GURL
url(kStreamUrl
);
4254 session_deps_
.host_resolver
->set_synchronous_mode(true);
4256 scoped_ptr
<SpdyFrame
> req1(
4257 spdy_util_
.ConstructSpdyPost(
4258 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4259 scoped_ptr
<SpdyFrame
> req2(
4260 spdy_util_
.ConstructSpdyPost(
4261 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, NULL
, 0));
4262 scoped_ptr
<SpdyFrame
> req3(
4263 spdy_util_
.ConstructSpdyPost(
4264 kStreamUrl
, 5, kBodyDataSize
, LOWEST
, NULL
, 0));
4265 scoped_ptr
<SpdyFrame
> body2(
4266 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4267 MockWrite writes
[] = {
4268 CreateMockWrite(*req1
, 0),
4269 CreateMockWrite(*req2
, 1),
4270 CreateMockWrite(*req3
, 2),
4271 CreateMockWrite(*body2
, 3),
4274 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4275 MockRead reads
[] = {
4276 CreateMockRead(*resp2
, 4),
4277 MockRead(ASYNC
, 0, 0, 5), // EOF
4280 DeterministicSocketData
data(reads
, arraysize(reads
),
4281 writes
, arraysize(writes
));
4282 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4283 data
.set_connect_data(connect_data
);
4285 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4287 CreateDeterministicNetworkSession();
4288 base::WeakPtr
<SpdySession
> session
=
4289 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4290 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4291 session
->flow_control_state());
4293 base::WeakPtr
<SpdyStream
> stream1
=
4294 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4295 session
, url
, LOWEST
, BoundNetLog());
4296 ASSERT_TRUE(stream1
.get() != NULL
);
4298 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4299 stream1
->SetDelegate(&delegate1
);
4301 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4303 base::WeakPtr
<SpdyStream
> stream2
=
4304 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4305 session
, url
, LOWEST
, BoundNetLog());
4306 ASSERT_TRUE(stream2
.get() != NULL
);
4308 StreamClosingDelegate
delegate2(stream2
, kBodyDataStringPiece
);
4309 stream2
->SetDelegate(&delegate2
);
4311 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4313 base::WeakPtr
<SpdyStream
> stream3
=
4314 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4315 session
, url
, LOWEST
, BoundNetLog());
4316 ASSERT_TRUE(stream3
.get() != NULL
);
4318 test::StreamDelegateWithBody
delegate3(stream3
, kBodyDataStringPiece
);
4319 stream3
->SetDelegate(&delegate3
);
4321 EXPECT_FALSE(stream3
->HasUrlFromHeaders());
4323 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4324 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4325 EXPECT_FALSE(stream3
->send_stalled_by_flow_control());
4327 StallSessionSend(session
.get());
4329 scoped_ptr
<SpdyHeaderBlock
> headers1(
4330 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4331 EXPECT_EQ(ERR_IO_PENDING
,
4332 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4333 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4334 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4337 EXPECT_EQ(1u, stream1
->stream_id());
4338 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4340 scoped_ptr
<SpdyHeaderBlock
> headers2(
4341 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4342 EXPECT_EQ(ERR_IO_PENDING
,
4343 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4344 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4345 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4348 EXPECT_EQ(3u, stream2
->stream_id());
4349 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4351 scoped_ptr
<SpdyHeaderBlock
> headers3(
4352 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4353 EXPECT_EQ(ERR_IO_PENDING
,
4354 stream3
->SendRequestHeaders(headers3
.Pass(), MORE_DATA_TO_SEND
));
4355 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
4356 EXPECT_EQ(kStreamUrl
, stream3
->GetUrlFromHeaders().spec());
4359 EXPECT_EQ(5u, stream3
->stream_id());
4360 EXPECT_TRUE(stream3
->send_stalled_by_flow_control());
4362 SpdyStreamId stream_id1
= stream1
->stream_id();
4363 SpdyStreamId stream_id2
= stream2
->stream_id();
4364 SpdyStreamId stream_id3
= stream3
->stream_id();
4366 // Close stream1 preemptively.
4367 session
->CloseActiveStream(stream_id1
, ERR_CONNECTION_CLOSED
);
4368 EXPECT_EQ(NULL
, stream1
.get());
4370 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4371 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4372 EXPECT_TRUE(session
->IsStreamActive(stream_id3
));
4374 // Unstall stream2, which should then close stream3.
4375 delegate2
.set_stream_to_close(stream3
);
4376 UnstallSessionSend(session
.get(), kBodyDataSize
);
4379 EXPECT_EQ(NULL
, stream3
.get());
4381 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4382 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4383 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4384 EXPECT_FALSE(session
->IsStreamActive(stream_id3
));
4387 EXPECT_EQ(NULL
, stream2
.get());
4389 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4390 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4391 EXPECT_EQ(OK
, delegate3
.WaitForClose());
4393 EXPECT_TRUE(delegate1
.send_headers_completed());
4394 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4396 EXPECT_TRUE(delegate2
.send_headers_completed());
4397 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4398 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4400 EXPECT_TRUE(delegate3
.send_headers_completed());
4401 EXPECT_EQ(std::string(), delegate3
.TakeReceivedData());
4403 EXPECT_TRUE(data
.at_write_eof());
4406 // Cause a stall by reducing the flow control send window to
4407 // 0. Unstalling the session should properly handle the session itself
4409 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedSession
) {
4410 if (GetParam() < kProtoSPDY31
)
4413 const char kStreamUrl
[] = "http://www.google.com/";
4414 GURL
url(kStreamUrl
);
4416 session_deps_
.host_resolver
->set_synchronous_mode(true);
4418 scoped_ptr
<SpdyFrame
> req1(
4419 spdy_util_
.ConstructSpdyPost(
4420 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4421 scoped_ptr
<SpdyFrame
> req2(
4422 spdy_util_
.ConstructSpdyPost(
4423 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, NULL
, 0));
4424 scoped_ptr
<SpdyFrame
> body1(
4425 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4426 MockWrite writes
[] = {
4427 CreateMockWrite(*req1
, 0),
4428 CreateMockWrite(*req2
, 1),
4431 MockRead reads
[] = {
4432 MockRead(ASYNC
, 0, 0, 2), // EOF
4435 DeterministicSocketData
data(reads
, arraysize(reads
),
4436 writes
, arraysize(writes
));
4437 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4438 data
.set_connect_data(connect_data
);
4440 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4442 CreateDeterministicNetworkSession();
4443 base::WeakPtr
<SpdySession
> session
=
4444 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4445 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4446 session
->flow_control_state());
4448 base::WeakPtr
<SpdyStream
> stream1
=
4449 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4450 session
, url
, LOWEST
, BoundNetLog());
4451 ASSERT_TRUE(stream1
.get() != NULL
);
4453 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4454 stream1
->SetDelegate(&delegate1
);
4456 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4458 base::WeakPtr
<SpdyStream
> stream2
=
4459 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4460 session
, url
, LOWEST
, BoundNetLog());
4461 ASSERT_TRUE(stream2
.get() != NULL
);
4463 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4464 stream2
->SetDelegate(&delegate2
);
4466 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4468 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4469 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4471 StallSessionSend(session
.get());
4473 scoped_ptr
<SpdyHeaderBlock
> headers1(
4474 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4475 EXPECT_EQ(ERR_IO_PENDING
,
4476 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4477 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4478 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4481 EXPECT_EQ(1u, stream1
->stream_id());
4482 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4484 scoped_ptr
<SpdyHeaderBlock
> headers2(
4485 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4486 EXPECT_EQ(ERR_IO_PENDING
,
4487 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4488 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4489 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4492 EXPECT_EQ(3u, stream2
->stream_id());
4493 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4495 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
4498 UnstallSessionSend(session
.get(), kBodyDataSize
);
4500 // Close the session (since we can't do it from within the delegate
4501 // method, since it's in the stream's loop).
4502 session
->CloseSessionOnError(ERR_CONNECTION_CLOSED
, "Closing session");
4503 base::RunLoop().RunUntilIdle();
4504 EXPECT_TRUE(session
== NULL
);
4506 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
4508 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4509 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4511 EXPECT_TRUE(delegate1
.send_headers_completed());
4512 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4514 EXPECT_TRUE(delegate2
.send_headers_completed());
4515 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4517 EXPECT_TRUE(data
.at_write_eof());
4520 TEST_P(SpdySessionTest
, GoAwayOnSessionFlowControlError
) {
4521 if (GetParam() < kProtoSPDY31
)
4524 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4526 scoped_ptr
<SpdyFrame
> req(
4527 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4528 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
4530 GOAWAY_FLOW_CONTROL_ERROR
,
4531 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4532 "the receive window size of 1"));
4533 MockWrite writes
[] = {
4534 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 3),
4537 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4538 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4539 MockRead reads
[] = {
4540 CreateMockRead(*resp
, 1), CreateMockRead(*body
, 2),
4543 DeterministicSocketData
data(
4544 reads
, arraysize(reads
), writes
, arraysize(writes
));
4545 data
.set_connect_data(connect_data
);
4546 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4548 CreateDeterministicNetworkSession();
4550 base::WeakPtr
<SpdySession
> session
=
4551 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4553 GURL
url(kDefaultURL
);
4554 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
4555 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, LOWEST
, BoundNetLog());
4556 ASSERT_TRUE(spdy_stream
.get() != NULL
);
4557 test::StreamDelegateDoNothing
delegate(spdy_stream
);
4558 spdy_stream
->SetDelegate(&delegate
);
4560 scoped_ptr
<SpdyHeaderBlock
> headers(
4561 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
4562 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4564 data
.RunFor(1); // Write request.
4566 // Put session on the edge of overflowing it's recv window.
4567 session
->session_recv_window_size_
= 1;
4569 // Read response headers & body. Body overflows the session window, and a
4570 // goaway is written.
4572 base::MessageLoop::current()->RunUntilIdle();
4574 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR
, delegate
.WaitForClose());
4575 EXPECT_TRUE(session
== NULL
);
4578 TEST_P(SpdySessionTest
, SplitHeaders
) {
4579 GURL
kStreamUrl("http://www.google.com/foo.dat");
4580 SpdyHeaderBlock headers
;
4581 spdy_util_
.AddUrlToHeaderBlock(kStreamUrl
.spec(), &headers
);
4582 headers
["alpha"] = "beta";
4584 SpdyHeaderBlock request_headers
;
4585 SpdyHeaderBlock response_headers
;
4587 SplitPushedHeadersToRequestAndResponse(
4588 headers
, spdy_util_
.spdy_version(), &request_headers
, &response_headers
);
4590 SpdyHeaderBlock::const_iterator it
= response_headers
.find("alpha");
4591 std::string alpha_val
=
4592 (it
== response_headers
.end()) ? std::string() : it
->second
;
4593 EXPECT_EQ("beta", alpha_val
);
4596 GetUrlFromHeaderBlock(request_headers
, spdy_util_
.spdy_version(), true);
4597 EXPECT_EQ(kStreamUrl
, request_url
);
4600 // Regression. Sorta. Push streams and client streams were sharing a single
4601 // limit for a long time.
4602 TEST_P(SpdySessionTest
, PushedStreamShouldNotCountToClientConcurrencyLimit
) {
4603 SettingsMap new_settings
;
4604 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4605 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, 2);
4606 scoped_ptr
<SpdyFrame
> settings_frame(
4607 spdy_util_
.ConstructSpdySettings(new_settings
));
4608 scoped_ptr
<SpdyFrame
> pushed(spdy_util_
.ConstructSpdyPush(
4609 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4610 MockRead reads
[] = {
4611 CreateMockRead(*settings_frame
), CreateMockRead(*pushed
, 3),
4612 MockRead(ASYNC
, 0, 4),
4615 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
4616 scoped_ptr
<SpdyFrame
> req(
4617 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4618 MockWrite writes
[] = {
4619 CreateMockWrite(*settings_ack
, 1), CreateMockWrite(*req
, 2),
4622 DeterministicSocketData
data(
4623 reads
, arraysize(reads
), writes
, arraysize(writes
));
4624 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4625 data
.set_connect_data(connect_data
);
4626 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4628 CreateDeterministicNetworkSession();
4630 base::WeakPtr
<SpdySession
> session
=
4631 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4633 // Read the settings frame.
4636 GURL
url1(kDefaultURL
);
4637 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4638 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4639 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4640 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4641 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4642 spdy_stream1
->SetDelegate(&delegate1
);
4644 EXPECT_EQ(0u, session
->num_active_streams());
4645 EXPECT_EQ(1u, session
->num_created_streams());
4646 EXPECT_EQ(0u, session
->num_pushed_streams());
4647 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4649 scoped_ptr
<SpdyHeaderBlock
> headers(
4650 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4651 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4652 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4654 // Run until 1st stream is activated.
4655 EXPECT_EQ(0u, delegate1
.stream_id());
4657 EXPECT_EQ(1u, delegate1
.stream_id());
4658 EXPECT_EQ(1u, session
->num_active_streams());
4659 EXPECT_EQ(0u, session
->num_created_streams());
4660 EXPECT_EQ(0u, session
->num_pushed_streams());
4661 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4663 // Run until pushed stream is created.
4665 EXPECT_EQ(2u, session
->num_active_streams());
4666 EXPECT_EQ(0u, session
->num_created_streams());
4667 EXPECT_EQ(1u, session
->num_pushed_streams());
4668 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4670 // Second stream should not be stalled, although we have 2 active streams, but
4671 // one of them is push stream and should not be taken into account when we
4672 // create streams on the client.
4673 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
4674 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4675 EXPECT_TRUE(spdy_stream2
.get() != NULL
);
4676 EXPECT_EQ(2u, session
->num_active_streams());
4677 EXPECT_EQ(1u, session
->num_created_streams());
4678 EXPECT_EQ(1u, session
->num_pushed_streams());
4679 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4685 TEST_P(SpdySessionTest
, RejectPushedStreamExceedingConcurrencyLimit
) {
4686 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4687 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4688 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
4689 NULL
, 0, 4, 1, "http://www.google.com/b.dat"));
4690 MockRead reads
[] = {
4691 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
4692 MockRead(ASYNC
, 0, 4),
4695 scoped_ptr
<SpdyFrame
> req(
4696 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4697 scoped_ptr
<SpdyFrame
> rst(
4698 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4699 MockWrite writes
[] = {
4700 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 3),
4703 DeterministicSocketData
data(
4704 reads
, arraysize(reads
), writes
, arraysize(writes
));
4705 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4706 data
.set_connect_data(connect_data
);
4707 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4709 CreateDeterministicNetworkSession();
4711 base::WeakPtr
<SpdySession
> session
=
4712 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4713 session
->set_max_concurrent_pushed_streams(1);
4715 GURL
url1(kDefaultURL
);
4716 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4717 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4718 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4719 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4720 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4721 spdy_stream1
->SetDelegate(&delegate1
);
4723 EXPECT_EQ(0u, session
->num_active_streams());
4724 EXPECT_EQ(1u, session
->num_created_streams());
4725 EXPECT_EQ(0u, session
->num_pushed_streams());
4726 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4728 scoped_ptr
<SpdyHeaderBlock
> headers(
4729 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4730 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4731 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4733 // Run until 1st stream is activated.
4734 EXPECT_EQ(0u, delegate1
.stream_id());
4736 EXPECT_EQ(1u, delegate1
.stream_id());
4737 EXPECT_EQ(1u, session
->num_active_streams());
4738 EXPECT_EQ(0u, session
->num_created_streams());
4739 EXPECT_EQ(0u, session
->num_pushed_streams());
4740 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4742 // Run until pushed stream is created.
4744 EXPECT_EQ(2u, session
->num_active_streams());
4745 EXPECT_EQ(0u, session
->num_created_streams());
4746 EXPECT_EQ(1u, session
->num_pushed_streams());
4747 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4749 // Reset incoming pushed stream.
4751 EXPECT_EQ(2u, session
->num_active_streams());
4752 EXPECT_EQ(0u, session
->num_created_streams());
4753 EXPECT_EQ(1u, session
->num_pushed_streams());
4754 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4760 TEST_P(SpdySessionTest
, IgnoreReservedRemoteStreamsCount
) {
4761 // Streams in reserved remote state exist only in SPDY4.
4762 if (spdy_util_
.spdy_version() < SPDY4
)
4765 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4766 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4767 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4768 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/b.dat",
4769 push_headers
.get());
4770 scoped_ptr
<SpdyFrame
> push_b(
4771 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 4, 1));
4772 scoped_ptr
<SpdyFrame
> headers_b(
4773 spdy_util_
.ConstructSpdyPushHeaders(4, NULL
, 0));
4774 MockRead reads
[] = {
4775 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
4776 CreateMockRead(*headers_b
, 3), MockRead(ASYNC
, 0, 5),
4779 scoped_ptr
<SpdyFrame
> req(
4780 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4781 scoped_ptr
<SpdyFrame
> rst(
4782 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4783 MockWrite writes
[] = {
4784 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 4),
4787 DeterministicSocketData
data(
4788 reads
, arraysize(reads
), writes
, arraysize(writes
));
4789 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4790 data
.set_connect_data(connect_data
);
4791 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4793 CreateDeterministicNetworkSession();
4795 base::WeakPtr
<SpdySession
> session
=
4796 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4797 session
->set_max_concurrent_pushed_streams(1);
4799 GURL
url1(kDefaultURL
);
4800 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4801 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4802 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4803 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4804 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4805 spdy_stream1
->SetDelegate(&delegate1
);
4807 EXPECT_EQ(0u, session
->num_active_streams());
4808 EXPECT_EQ(1u, session
->num_created_streams());
4809 EXPECT_EQ(0u, session
->num_pushed_streams());
4810 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4812 scoped_ptr
<SpdyHeaderBlock
> headers(
4813 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4814 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4815 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4817 // Run until 1st stream is activated.
4818 EXPECT_EQ(0u, delegate1
.stream_id());
4820 EXPECT_EQ(1u, delegate1
.stream_id());
4821 EXPECT_EQ(1u, session
->num_active_streams());
4822 EXPECT_EQ(0u, session
->num_created_streams());
4823 EXPECT_EQ(0u, session
->num_pushed_streams());
4824 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4826 // Run until pushed stream is created.
4828 EXPECT_EQ(2u, session
->num_active_streams());
4829 EXPECT_EQ(0u, session
->num_created_streams());
4830 EXPECT_EQ(1u, session
->num_pushed_streams());
4831 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4833 // Accept promised stream. It should not count towards pushed stream limit.
4835 EXPECT_EQ(3u, session
->num_active_streams());
4836 EXPECT_EQ(0u, session
->num_created_streams());
4837 EXPECT_EQ(2u, session
->num_pushed_streams());
4838 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4840 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4841 // while we accept only one.
4843 EXPECT_EQ(2u, session
->num_active_streams());
4844 EXPECT_EQ(0u, session
->num_created_streams());
4845 EXPECT_EQ(1u, session
->num_pushed_streams());
4846 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4852 TEST_P(SpdySessionTest
, CancelReservedStreamOnHeadersReceived
) {
4853 // Streams in reserved remote state exist only in SPDY4.
4854 if (spdy_util_
.spdy_version() < SPDY4
)
4857 const char kPushedUrl
[] = "http://www.google.com/a.dat";
4858 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4859 spdy_util_
.AddUrlToHeaderBlock(kPushedUrl
, push_headers
.get());
4860 scoped_ptr
<SpdyFrame
> push_promise(
4861 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 2, 1));
4862 scoped_ptr
<SpdyFrame
> headers_frame(
4863 spdy_util_
.ConstructSpdyPushHeaders(2, NULL
, 0));
4864 MockRead reads
[] = {
4865 CreateMockRead(*push_promise
, 1), CreateMockRead(*headers_frame
, 2),
4866 MockRead(ASYNC
, 0, 4),
4869 scoped_ptr
<SpdyFrame
> req(
4870 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4871 scoped_ptr
<SpdyFrame
> rst(
4872 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
4873 MockWrite writes
[] = {
4874 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 3),
4877 DeterministicSocketData
data(
4878 reads
, arraysize(reads
), writes
, arraysize(writes
));
4879 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4880 data
.set_connect_data(connect_data
);
4881 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4883 CreateDeterministicNetworkSession();
4885 base::WeakPtr
<SpdySession
> session
=
4886 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4888 GURL
url1(kDefaultURL
);
4889 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4890 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4891 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4892 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4893 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4894 spdy_stream1
->SetDelegate(&delegate1
);
4896 EXPECT_EQ(0u, session
->num_active_streams());
4897 EXPECT_EQ(1u, session
->num_created_streams());
4898 EXPECT_EQ(0u, session
->num_pushed_streams());
4899 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4901 scoped_ptr
<SpdyHeaderBlock
> headers(
4902 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4903 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4904 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4906 // Run until 1st stream is activated.
4907 EXPECT_EQ(0u, delegate1
.stream_id());
4909 EXPECT_EQ(1u, delegate1
.stream_id());
4910 EXPECT_EQ(1u, session
->num_active_streams());
4911 EXPECT_EQ(0u, session
->num_created_streams());
4912 EXPECT_EQ(0u, session
->num_pushed_streams());
4913 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4915 // Run until pushed stream is created.
4917 EXPECT_EQ(2u, session
->num_active_streams());
4918 EXPECT_EQ(0u, session
->num_created_streams());
4919 EXPECT_EQ(1u, session
->num_pushed_streams());
4920 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4922 base::WeakPtr
<SpdyStream
> pushed_stream
;
4924 session
->GetPushStream(GURL(kPushedUrl
), &pushed_stream
, BoundNetLog());
4926 ASSERT_TRUE(pushed_stream
.get() != NULL
);
4927 test::StreamDelegateCloseOnHeaders
delegate2(pushed_stream
);
4928 pushed_stream
->SetDelegate(&delegate2
);
4930 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4931 // that all our counters are in consistent state.
4933 EXPECT_EQ(1u, session
->num_active_streams());
4934 EXPECT_EQ(0u, session
->num_created_streams());
4935 EXPECT_EQ(0u, session
->num_pushed_streams());
4936 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4942 TEST_P(SpdySessionTest
, RejectInvalidUnknownFrames
) {
4943 session_deps_
.host_resolver
->set_synchronous_mode(true);
4945 MockRead reads
[] = {
4946 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
4949 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
4951 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4952 data
.set_connect_data(connect_data
);
4953 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4955 CreateNetworkSession();
4956 base::WeakPtr
<SpdySession
> session
=
4957 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4959 session
->stream_hi_water_mark_
= 5;
4960 // Low client (odd) ids are fine.
4961 EXPECT_TRUE(session
->OnUnknownFrame(3, 0));
4962 // Client id exceeding watermark.
4963 EXPECT_FALSE(session
->OnUnknownFrame(9, 0));
4965 session
->last_accepted_push_stream_id_
= 6;
4966 // Low server (even) ids are fine.
4967 EXPECT_TRUE(session
->OnUnknownFrame(2, 0));
4968 // Server id exceeding last accepted id.
4969 EXPECT_FALSE(session
->OnUnknownFrame(8, 0));
4972 TEST(MapFramerErrorToProtocolError
, MapsValues
) {
4974 SPDY_ERROR_INVALID_CONTROL_FRAME
,
4975 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4977 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS
,
4978 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
4980 SPDY_ERROR_GOAWAY_FRAME_CORRUPT
,
4981 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT
));
4982 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME
,
4983 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME
));
4986 TEST(MapFramerErrorToNetError
, MapsValue
) {
4987 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR
,
4988 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4989 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
4990 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE
));
4991 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
4992 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE
));
4994 ERR_SPDY_FRAME_SIZE_ERROR
,
4995 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
));
4998 TEST(MapRstStreamStatusToProtocolError
, MapsValues
) {
4999 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR
,
5000 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR
));
5001 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR
,
5002 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR
));
5003 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM
,
5004 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM
));
5005 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY
,
5006 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY
));
5007 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED
,
5008 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED
));
5011 TEST(MapNetErrorToGoAwayStatus
, MapsValue
) {
5012 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY
,
5013 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
));
5014 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR
,
5015 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR
));
5016 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
,
5017 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR
));
5018 CHECK_EQ(GOAWAY_COMPRESSION_ERROR
,
5019 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR
));
5020 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR
,
5021 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR
));
5022 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED
));
5025 TEST(CanPoolTest
, CanPool
) {
5026 // Load a cert that is valid for:
5031 TransportSecurityState tss
;
5033 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5034 "spdy_pooling.pem");
5036 EXPECT_TRUE(SpdySession::CanPool(
5037 &tss
, ssl_info
, "www.example.org", "www.example.org"));
5038 EXPECT_TRUE(SpdySession::CanPool(
5039 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5040 EXPECT_TRUE(SpdySession::CanPool(
5041 &tss
, ssl_info
, "www.example.org", "mail.example.com"));
5042 EXPECT_FALSE(SpdySession::CanPool(
5043 &tss
, ssl_info
, "www.example.org", "mail.google.com"));
5046 TEST(CanPoolTest
, CanNotPoolWithCertErrors
) {
5047 // Load a cert that is valid for:
5052 TransportSecurityState tss
;
5054 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5055 "spdy_pooling.pem");
5056 ssl_info
.cert_status
= CERT_STATUS_REVOKED
;
5058 EXPECT_FALSE(SpdySession::CanPool(
5059 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5062 TEST(CanPoolTest
, CanNotPoolWithClientCerts
) {
5063 // Load a cert that is valid for:
5068 TransportSecurityState tss
;
5070 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5071 "spdy_pooling.pem");
5072 ssl_info
.client_cert_sent
= true;
5074 EXPECT_FALSE(SpdySession::CanPool(
5075 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5078 TEST(CanPoolTest
, CanNotPoolAcrossETLDsWithChannelID
) {
5079 // Load a cert that is valid for:
5084 TransportSecurityState tss
;
5086 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5087 "spdy_pooling.pem");
5088 ssl_info
.channel_id_sent
= true;
5090 EXPECT_TRUE(SpdySession::CanPool(
5091 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5092 EXPECT_FALSE(SpdySession::CanPool(
5093 &tss
, ssl_info
, "www.example.org", "www.example.com"));
5096 TEST(CanPoolTest
, CanNotPoolWithBadPins
) {
5097 uint8 primary_pin
= 1;
5098 uint8 backup_pin
= 2;
5100 TransportSecurityState tss
;
5101 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5104 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5105 "spdy_pooling.pem");
5106 ssl_info
.is_issued_by_known_root
= true;
5107 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(bad_pin
));
5109 EXPECT_FALSE(SpdySession::CanPool(
5110 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5113 TEST(CanPoolTest
, CanPoolWithAcceptablePins
) {
5114 uint8 primary_pin
= 1;
5115 uint8 backup_pin
= 2;
5116 TransportSecurityState tss
;
5117 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5120 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5121 "spdy_pooling.pem");
5122 ssl_info
.is_issued_by_known_root
= true;
5123 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(primary_pin
));
5125 EXPECT_TRUE(SpdySession::CanPool(
5126 &tss
, ssl_info
, "www.example.org", "mail.example.org"));