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 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1198 // iterators inside. See http://crbug.com/443490
1199 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
1200 NULL
, 0, 4, 1, "http://www.google.com/0.dat"));
1201 MockWrite writes
[] = {CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 4)};
1202 MockRead reads
[] = {
1203 CreateMockRead(*push_a
, 1), CreateMockRead(*push_a_body
, 2),
1204 CreateMockRead(*push_b
, 3), MockRead(ASYNC
, 0, 5), // EOF
1206 DeterministicSocketData
data(
1207 reads
, arraysize(reads
), writes
, arraysize(writes
));
1209 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1210 data
.set_connect_data(connect_data
);
1211 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1213 CreateDeterministicNetworkSession();
1214 base::WeakPtr
<SpdySession
> session
=
1215 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1217 // Process the principal request, and the first push stream request & body.
1218 GURL
url(kDefaultURL
);
1219 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1220 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1221 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1222 spdy_stream
->SetDelegate(&delegate
);
1224 scoped_ptr
<SpdyHeaderBlock
> headers(
1225 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1226 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1230 // Verify that there is one unclaimed push stream.
1231 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
1232 SpdySession::PushedStreamMap::iterator iter
=
1233 session
->unclaimed_pushed_streams_
.find(
1234 GURL("http://www.google.com/a.dat"));
1235 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
1237 if (session
->flow_control_state_
==
1238 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1239 // Unclaimed push body consumed bytes from the session window.
1240 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()) - kUploadDataSize
,
1241 session
->session_recv_window_size_
);
1242 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
1245 // Shift time to expire the push stream. Read the second SYN_STREAM,
1246 // and verify a RST_STREAM was written.
1247 g_time_delta
= base::TimeDelta::FromSeconds(301);
1250 // Verify that the second pushed stream evicted the first pushed stream.
1251 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
1252 iter
= session
->unclaimed_pushed_streams_
.find(
1253 GURL("http://www.google.com/0.dat"));
1254 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
1256 if (session
->flow_control_state_
==
1257 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1258 // Verify that the session window reclaimed the evicted stream body.
1259 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
1260 session
->session_recv_window_size_
);
1261 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
1264 // Read and process EOF.
1266 base::MessageLoop::current()->RunUntilIdle();
1267 EXPECT_TRUE(session
== NULL
);
1270 TEST_P(SpdySessionTest
, FailedPing
) {
1271 session_deps_
.host_resolver
->set_synchronous_mode(true);
1273 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1274 MockRead reads
[] = {
1275 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1277 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
1278 scoped_ptr
<SpdyFrame
> goaway(
1279 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Failed ping."));
1280 MockWrite writes
[] = {CreateMockWrite(*write_ping
), CreateMockWrite(*goaway
)};
1281 StaticSocketDataProvider
data(
1282 reads
, arraysize(reads
), writes
, arraysize(writes
));
1283 data
.set_connect_data(connect_data
);
1284 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1286 CreateNetworkSession();
1288 base::WeakPtr
<SpdySession
> session
=
1289 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1291 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1292 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1293 session
, test_url_
, MEDIUM
, BoundNetLog());
1294 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1295 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
1296 spdy_stream1
->SetDelegate(&delegate
);
1298 session
->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1299 session
->set_hung_interval(base::TimeDelta::FromSeconds(0));
1301 // Send a PING frame.
1302 session
->WritePingFrame(1, false);
1303 EXPECT_LT(0, session
->pings_in_flight());
1304 EXPECT_GE(session
->next_ping_id(), 1U);
1305 EXPECT_TRUE(session
->check_ping_status_pending());
1307 // Assert session is not closed.
1308 EXPECT_TRUE(session
->IsAvailable());
1309 EXPECT_LT(0u, session
->num_active_streams() + session
->num_created_streams());
1310 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1312 // We set last time we have received any data in 1 sec less than now.
1313 // CheckPingStatus will trigger timeout because hung interval is zero.
1314 base::TimeTicks now
= base::TimeTicks::Now();
1315 session
->last_activity_time_
= now
- base::TimeDelta::FromSeconds(1);
1316 session
->CheckPingStatus(now
);
1317 base::MessageLoop::current()->RunUntilIdle();
1319 EXPECT_TRUE(session
== NULL
);
1320 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1321 EXPECT_EQ(NULL
, spdy_stream1
.get());
1324 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1325 // settings frame increasing the max concurrent streams by 1. Make
1326 // sure nothing blows up. This is a regression test for
1327 // http://crbug.com/57331 .
1328 TEST_P(SpdySessionTest
, OnSettings
) {
1329 session_deps_
.host_resolver
->set_synchronous_mode(true);
1331 const SpdySettingsIds kSpdySettingsIds
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1333 SettingsMap new_settings
;
1334 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1335 new_settings
[kSpdySettingsIds
] =
1336 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1337 scoped_ptr
<SpdyFrame
> settings_frame(
1338 spdy_util_
.ConstructSpdySettings(new_settings
));
1339 MockRead reads
[] = {
1340 CreateMockRead(*settings_frame
, 0),
1341 MockRead(ASYNC
, 0, 1),
1344 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1345 MockWrite writes
[] = {
1346 CreateMockWrite(*settings_ack
, 2),
1349 DeterministicSocketData
data(reads
, arraysize(reads
),
1350 writes
, arraysize(writes
));
1351 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1352 data
.set_connect_data(connect_data
);
1353 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1355 CreateDeterministicNetworkSession();
1357 base::WeakPtr
<SpdySession
> session
=
1358 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1360 // Create the maximum number of concurrent streams.
1361 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1362 base::WeakPtr
<SpdyStream
> spdy_stream
=
1363 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1364 session
, test_url_
, MEDIUM
, BoundNetLog());
1365 ASSERT_TRUE(spdy_stream
!= NULL
);
1368 StreamReleaserCallback stream_releaser
;
1369 SpdyStreamRequest request
;
1370 ASSERT_EQ(ERR_IO_PENDING
,
1371 request
.StartRequest(
1372 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1374 stream_releaser
.MakeCallback(&request
)));
1378 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1381 if (spdy_util_
.spdy_version() >= SPDY4
) {
1382 // Allow the SETTINGS+ACK to write, so the session finishes draining.
1385 base::MessageLoop::current()->RunUntilIdle();
1386 EXPECT_TRUE(session
== NULL
);
1389 // Start with a persisted value for max concurrent streams. Receive a
1390 // settings frame increasing the max concurrent streams by 1 and which
1391 // also clears the persisted data. Verify that persisted data is
1393 TEST_P(SpdySessionTest
, ClearSettings
) {
1394 if (spdy_util_
.spdy_version() >= SPDY4
) {
1395 // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1396 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4.
1399 session_deps_
.host_resolver
->set_synchronous_mode(true);
1401 SettingsMap new_settings
;
1402 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1403 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1404 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1405 scoped_ptr
<SpdyFrame
> settings_frame(
1406 spdy_util_
.ConstructSpdySettings(new_settings
));
1407 uint8 flags
= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
1408 test::SetFrameFlags(settings_frame
.get(), flags
, spdy_util_
.spdy_version());
1409 MockRead reads
[] = {
1410 CreateMockRead(*settings_frame
, 0),
1411 MockRead(ASYNC
, 0, 1),
1414 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
1415 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1416 data
.set_connect_data(connect_data
);
1417 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1419 CreateDeterministicNetworkSession();
1421 // Initialize the SpdySetting with the default.
1422 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1423 test_host_port_pair_
,
1424 SETTINGS_MAX_CONCURRENT_STREAMS
,
1425 SETTINGS_FLAG_PLEASE_PERSIST
,
1426 kInitialMaxConcurrentStreams
);
1429 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1430 test_host_port_pair_
).empty());
1432 base::WeakPtr
<SpdySession
> session
=
1433 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1435 // Create the maximum number of concurrent streams.
1436 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1437 base::WeakPtr
<SpdyStream
> spdy_stream
=
1438 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1439 session
, test_url_
, MEDIUM
, BoundNetLog());
1440 ASSERT_TRUE(spdy_stream
!= NULL
);
1443 StreamReleaserCallback stream_releaser
;
1445 SpdyStreamRequest request
;
1446 ASSERT_EQ(ERR_IO_PENDING
,
1447 request
.StartRequest(
1448 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1450 stream_releaser
.MakeCallback(&request
)));
1454 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1456 // Make sure that persisted data is cleared.
1458 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1459 test_host_port_pair_
).empty());
1461 // Make sure session's max_concurrent_streams is correct.
1462 EXPECT_EQ(kInitialMaxConcurrentStreams
+ 1,
1463 session
->max_concurrent_streams());
1466 EXPECT_TRUE(session
== NULL
);
1469 // Start with max concurrent streams set to 1. Request two streams.
1470 // When the first completes, have the callback close its stream, which
1471 // should trigger the second stream creation. Then cancel that one
1472 // immediately. Don't crash. This is a regression test for
1473 // http://crbug.com/63532 .
1474 TEST_P(SpdySessionTest
, CancelPendingCreateStream
) {
1475 session_deps_
.host_resolver
->set_synchronous_mode(true);
1477 MockRead reads
[] = {
1478 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1481 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1482 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1484 data
.set_connect_data(connect_data
);
1485 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1487 CreateNetworkSession();
1489 // Initialize the SpdySetting with 1 max concurrent streams.
1490 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1491 test_host_port_pair_
,
1492 SETTINGS_MAX_CONCURRENT_STREAMS
,
1493 SETTINGS_FLAG_PLEASE_PERSIST
,
1496 base::WeakPtr
<SpdySession
> session
=
1497 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1499 // Leave room for only one more stream to be created.
1500 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
1501 base::WeakPtr
<SpdyStream
> spdy_stream
=
1502 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1503 session
, test_url_
, MEDIUM
, BoundNetLog());
1504 ASSERT_TRUE(spdy_stream
!= NULL
);
1507 // Create 2 more streams. First will succeed. Second will be pending.
1508 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1509 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1510 session
, test_url_
, MEDIUM
, BoundNetLog());
1511 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1513 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1514 // a valgrind error if the callback is invoked when it's not supposed to be.
1515 scoped_ptr
<TestCompletionCallback
> callback(new TestCompletionCallback
);
1517 SpdyStreamRequest request
;
1518 ASSERT_EQ(ERR_IO_PENDING
,
1519 request
.StartRequest(
1520 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1522 callback
->callback()));
1524 // Release the first one, this will allow the second to be created.
1525 spdy_stream1
->Cancel();
1526 EXPECT_EQ(NULL
, spdy_stream1
.get());
1528 request
.CancelRequest();
1531 // Should not crash when running the pending callback.
1532 base::MessageLoop::current()->RunUntilIdle();
1535 TEST_P(SpdySessionTest
, SendInitialDataOnNewSession
) {
1536 session_deps_
.host_resolver
->set_synchronous_mode(true);
1538 MockRead reads
[] = {
1539 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1542 SettingsMap settings
;
1543 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1544 const SpdySettingsIds kSpdySettingsIds2
= SETTINGS_INITIAL_WINDOW_SIZE
;
1545 const uint32 kInitialRecvWindowSize
= 10 * 1024 * 1024;
1546 settings
[kSpdySettingsIds1
] =
1547 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
1548 if (spdy_util_
.spdy_version() >= SPDY3
) {
1549 settings
[kSpdySettingsIds2
] =
1550 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kInitialRecvWindowSize
);
1552 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1553 scoped_ptr
<SpdyFrame
> settings_frame(
1554 spdy_util_
.ConstructSpdySettings(settings
));
1555 scoped_ptr
<SpdyFrame
> initial_window_update(
1556 spdy_util_
.ConstructSpdyWindowUpdate(
1557 kSessionFlowControlStreamId
,
1558 kDefaultInitialRecvWindowSize
-
1559 SpdySession::GetInitialWindowSize(GetParam())));
1560 std::vector
<MockWrite
> writes
;
1561 if ((GetParam() >= kProtoSPDY4MinimumVersion
) &&
1562 (GetParam() <= kProtoSPDY4MaximumVersion
)) {
1565 kHttp2ConnectionHeaderPrefix
,
1566 kHttp2ConnectionHeaderPrefixSize
));
1568 writes
.push_back(CreateMockWrite(*settings_frame
));
1569 if (GetParam() >= kProtoSPDY31
) {
1570 writes
.push_back(CreateMockWrite(*initial_window_update
));
1573 SettingsMap server_settings
;
1574 const uint32 initial_max_concurrent_streams
= 1;
1575 server_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1576 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED
,
1577 initial_max_concurrent_streams
);
1578 scoped_ptr
<SpdyFrame
> server_settings_frame(
1579 spdy_util_
.ConstructSpdySettings(server_settings
));
1580 if (GetParam() <= kProtoSPDY31
) {
1581 writes
.push_back(CreateMockWrite(*server_settings_frame
));
1584 session_deps_
.stream_initial_recv_window_size
= kInitialRecvWindowSize
;
1586 StaticSocketDataProvider
data(reads
, arraysize(reads
),
1587 vector_as_array(&writes
), writes
.size());
1588 data
.set_connect_data(connect_data
);
1589 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1591 CreateNetworkSession();
1593 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1594 test_host_port_pair_
,
1595 SETTINGS_MAX_CONCURRENT_STREAMS
,
1596 SETTINGS_FLAG_PLEASE_PERSIST
,
1597 initial_max_concurrent_streams
);
1599 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
1600 pool_peer
.SetEnableSendingInitialData(true);
1602 base::WeakPtr
<SpdySession
> session
=
1603 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1605 base::MessageLoop::current()->RunUntilIdle();
1606 EXPECT_TRUE(data
.at_write_eof());
1609 TEST_P(SpdySessionTest
, ClearSettingsStorageOnIPAddressChanged
) {
1610 CreateNetworkSession();
1612 base::WeakPtr
<HttpServerProperties
> test_http_server_properties
=
1613 spdy_session_pool_
->http_server_properties();
1614 SettingsFlagsAndValue
flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST
, 2);
1615 test_http_server_properties
->SetSpdySetting(
1616 test_host_port_pair_
,
1617 SETTINGS_MAX_CONCURRENT_STREAMS
,
1618 SETTINGS_FLAG_PLEASE_PERSIST
,
1620 EXPECT_NE(0u, test_http_server_properties
->GetSpdySettings(
1621 test_host_port_pair_
).size());
1622 spdy_session_pool_
->OnIPAddressChanged();
1623 EXPECT_EQ(0u, test_http_server_properties
->GetSpdySettings(
1624 test_host_port_pair_
).size());
1627 TEST_P(SpdySessionTest
, Initialize
) {
1628 CapturingBoundNetLog log
;
1629 session_deps_
.net_log
= log
.bound().net_log();
1630 session_deps_
.host_resolver
->set_synchronous_mode(true);
1632 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1633 MockRead reads
[] = {
1634 MockRead(ASYNC
, 0, 0) // EOF
1637 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1638 data
.set_connect_data(connect_data
);
1639 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1641 CreateNetworkSession();
1643 base::WeakPtr
<SpdySession
> session
=
1644 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1645 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1647 // Flush the read completion task.
1648 base::MessageLoop::current()->RunUntilIdle();
1650 net::CapturingNetLog::CapturedEntryList entries
;
1651 log
.GetEntries(&entries
);
1652 EXPECT_LT(0u, entries
.size());
1654 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1655 int pos
= net::ExpectLogContainsSomewhere(
1656 entries
, 0, net::NetLog::TYPE_HTTP2_SESSION_INITIALIZED
,
1657 net::NetLog::PHASE_NONE
);
1660 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1661 NetLog::Source socket_source
;
1662 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry
.params
.get(),
1664 EXPECT_TRUE(socket_source
.IsValid());
1665 EXPECT_NE(log
.bound().source().id
, socket_source
.id
);
1668 TEST_P(SpdySessionTest
, NetLogOnSessionGoaway
) {
1669 session_deps_
.host_resolver
->set_synchronous_mode(true);
1671 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1672 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
1673 MockRead reads
[] = {
1674 CreateMockRead(*goaway
),
1675 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1678 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1679 data
.set_connect_data(connect_data
);
1680 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1682 CreateNetworkSession();
1684 CapturingBoundNetLog log
;
1685 base::WeakPtr
<SpdySession
> session
=
1686 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1687 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1689 // Flush the read completion task.
1690 base::MessageLoop::current()->RunUntilIdle();
1692 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1693 EXPECT_TRUE(session
== NULL
);
1695 // Check that the NetLog was filled reasonably.
1696 net::CapturingNetLog::CapturedEntryList entries
;
1697 log
.GetEntries(&entries
);
1698 EXPECT_LT(0u, entries
.size());
1700 // Check that we logged SPDY_SESSION_CLOSE correctly.
1701 int pos
= net::ExpectLogContainsSomewhere(
1702 entries
, 0, net::NetLog::TYPE_HTTP2_SESSION_CLOSE
,
1703 net::NetLog::PHASE_NONE
);
1705 if (pos
< static_cast<int>(entries
.size())) {
1706 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1708 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1709 EXPECT_EQ(OK
, error_code
);
1715 TEST_P(SpdySessionTest
, NetLogOnSessionEOF
) {
1716 session_deps_
.host_resolver
->set_synchronous_mode(true);
1718 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1719 MockRead reads
[] = {
1720 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1723 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1724 data
.set_connect_data(connect_data
);
1725 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1727 CreateNetworkSession();
1729 CapturingBoundNetLog log
;
1730 base::WeakPtr
<SpdySession
> session
=
1731 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1732 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1734 // Flush the read completion task.
1735 base::MessageLoop::current()->RunUntilIdle();
1737 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1738 EXPECT_TRUE(session
== NULL
);
1740 // Check that the NetLog was filled reasonably.
1741 net::CapturingNetLog::CapturedEntryList entries
;
1742 log
.GetEntries(&entries
);
1743 EXPECT_LT(0u, entries
.size());
1745 // Check that we logged SPDY_SESSION_CLOSE correctly.
1746 int pos
= net::ExpectLogContainsSomewhere(
1747 entries
, 0, net::NetLog::TYPE_HTTP2_SESSION_CLOSE
,
1748 net::NetLog::PHASE_NONE
);
1750 if (pos
< static_cast<int>(entries
.size())) {
1751 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1753 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1754 EXPECT_EQ(ERR_CONNECTION_CLOSED
, error_code
);
1760 TEST_P(SpdySessionTest
, SynCompressionHistograms
) {
1761 session_deps_
.enable_compression
= true;
1763 scoped_ptr
<SpdyFrame
> req(
1764 spdy_util_
.ConstructSpdyGet(NULL
, 0, true, 1, MEDIUM
, true));
1765 MockWrite writes
[] = {
1766 CreateMockWrite(*req
, 0),
1768 MockRead reads
[] = {
1769 MockRead(ASYNC
, 0, 1) // EOF
1771 DeterministicSocketData
data(reads
, arraysize(reads
),
1772 writes
, arraysize(writes
));
1773 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1774 data
.set_connect_data(connect_data
);
1775 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1777 CreateDeterministicNetworkSession();
1778 base::WeakPtr
<SpdySession
> session
=
1779 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1781 GURL
url(kDefaultURL
);
1782 base::WeakPtr
<SpdyStream
> spdy_stream
=
1783 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1784 session
, url
, MEDIUM
, BoundNetLog());
1785 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1786 spdy_stream
->SetDelegate(&delegate
);
1788 scoped_ptr
<SpdyHeaderBlock
> headers(
1789 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1790 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1791 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
1793 // Write request headers & capture resulting histogram update.
1794 base::HistogramTester histogram_tester
;
1797 // Regression test of compression performance under the request fixture.
1798 switch (spdy_util_
.spdy_version()) {
1800 histogram_tester
.ExpectBucketCount(
1801 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1804 histogram_tester
.ExpectBucketCount(
1805 "Net.SpdySynStreamCompressionPercentage", 82, 1);
1811 // Read and process EOF.
1813 base::MessageLoop::current()->RunUntilIdle();
1814 EXPECT_TRUE(session
== NULL
);
1817 // Queue up a low-priority SYN_STREAM followed by a high-priority
1818 // one. The high priority one should still send first and receive
1820 TEST_P(SpdySessionTest
, OutOfOrderSynStreams
) {
1821 // Construct the request.
1822 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1823 scoped_ptr
<SpdyFrame
> req_highest(
1824 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, HIGHEST
, true));
1825 scoped_ptr
<SpdyFrame
> req_lowest(
1826 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1827 MockWrite writes
[] = {
1828 CreateMockWrite(*req_highest
, 0),
1829 CreateMockWrite(*req_lowest
, 1),
1832 scoped_ptr
<SpdyFrame
> resp_highest(
1833 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1834 scoped_ptr
<SpdyFrame
> body_highest(
1835 spdy_util_
.ConstructSpdyBodyFrame(1, true));
1836 scoped_ptr
<SpdyFrame
> resp_lowest(
1837 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1838 scoped_ptr
<SpdyFrame
> body_lowest(
1839 spdy_util_
.ConstructSpdyBodyFrame(3, true));
1840 MockRead reads
[] = {
1841 CreateMockRead(*resp_highest
, 2),
1842 CreateMockRead(*body_highest
, 3),
1843 CreateMockRead(*resp_lowest
, 4),
1844 CreateMockRead(*body_lowest
, 5),
1845 MockRead(ASYNC
, 0, 6) // EOF
1848 session_deps_
.host_resolver
->set_synchronous_mode(true);
1850 DeterministicSocketData
data(reads
, arraysize(reads
),
1851 writes
, arraysize(writes
));
1852 data
.set_connect_data(connect_data
);
1853 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1855 CreateDeterministicNetworkSession();
1857 base::WeakPtr
<SpdySession
> session
=
1858 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1860 GURL
url(kDefaultURL
);
1862 base::WeakPtr
<SpdyStream
> spdy_stream_lowest
=
1863 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1864 session
, url
, LOWEST
, BoundNetLog());
1865 ASSERT_TRUE(spdy_stream_lowest
);
1866 EXPECT_EQ(0u, spdy_stream_lowest
->stream_id());
1867 test::StreamDelegateDoNothing
delegate_lowest(spdy_stream_lowest
);
1868 spdy_stream_lowest
->SetDelegate(&delegate_lowest
);
1870 base::WeakPtr
<SpdyStream
> spdy_stream_highest
=
1871 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1872 session
, url
, HIGHEST
, BoundNetLog());
1873 ASSERT_TRUE(spdy_stream_highest
);
1874 EXPECT_EQ(0u, spdy_stream_highest
->stream_id());
1875 test::StreamDelegateDoNothing
delegate_highest(spdy_stream_highest
);
1876 spdy_stream_highest
->SetDelegate(&delegate_highest
);
1878 // Queue the lower priority one first.
1880 scoped_ptr
<SpdyHeaderBlock
> headers_lowest(
1881 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1882 spdy_stream_lowest
->SendRequestHeaders(
1883 headers_lowest
.Pass(), NO_MORE_DATA_TO_SEND
);
1884 EXPECT_TRUE(spdy_stream_lowest
->HasUrlFromHeaders());
1886 scoped_ptr
<SpdyHeaderBlock
> headers_highest(
1887 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1888 spdy_stream_highest
->SendRequestHeaders(
1889 headers_highest
.Pass(), NO_MORE_DATA_TO_SEND
);
1890 EXPECT_TRUE(spdy_stream_highest
->HasUrlFromHeaders());
1894 EXPECT_FALSE(spdy_stream_lowest
);
1895 EXPECT_FALSE(spdy_stream_highest
);
1896 EXPECT_EQ(3u, delegate_lowest
.stream_id());
1897 EXPECT_EQ(1u, delegate_highest
.stream_id());
1900 TEST_P(SpdySessionTest
, CancelStream
) {
1901 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1902 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1903 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1904 scoped_ptr
<SpdyFrame
> req2(
1905 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1906 MockWrite writes
[] = {
1907 CreateMockWrite(*req2
, 0),
1910 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1911 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1912 MockRead reads
[] = {
1913 CreateMockRead(*resp2
, 1),
1914 CreateMockRead(*body2
, 2),
1915 MockRead(ASYNC
, 0, 3) // EOF
1918 session_deps_
.host_resolver
->set_synchronous_mode(true);
1920 DeterministicSocketData
data(reads
, arraysize(reads
),
1921 writes
, arraysize(writes
));
1922 data
.set_connect_data(connect_data
);
1923 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1925 CreateDeterministicNetworkSession();
1927 base::WeakPtr
<SpdySession
> session
=
1928 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1930 GURL
url1(kDefaultURL
);
1931 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1932 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1933 session
, url1
, HIGHEST
, BoundNetLog());
1934 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1935 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1936 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
1937 spdy_stream1
->SetDelegate(&delegate1
);
1939 GURL
url2(kDefaultURL
);
1940 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1941 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1942 session
, url2
, LOWEST
, BoundNetLog());
1943 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1944 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1945 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
1946 spdy_stream2
->SetDelegate(&delegate2
);
1948 scoped_ptr
<SpdyHeaderBlock
> headers(
1949 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1950 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1951 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1953 scoped_ptr
<SpdyHeaderBlock
> headers2(
1954 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1955 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1956 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1958 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1960 spdy_stream1
->Cancel();
1961 EXPECT_EQ(NULL
, spdy_stream1
.get());
1963 EXPECT_EQ(0u, delegate1
.stream_id());
1967 EXPECT_EQ(0u, delegate1
.stream_id());
1968 EXPECT_EQ(1u, delegate2
.stream_id());
1970 spdy_stream2
->Cancel();
1971 EXPECT_EQ(NULL
, spdy_stream2
.get());
1974 // Create two streams that are set to re-close themselves on close,
1975 // and then close the session. Nothing should blow up. Also a
1976 // regression test for http://crbug.com/139518 .
1977 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedSelfClosingStreams
) {
1978 session_deps_
.host_resolver
->set_synchronous_mode(true);
1980 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1982 // No actual data will be sent.
1983 MockWrite writes
[] = {
1984 MockWrite(ASYNC
, 0, 1) // EOF
1987 MockRead reads
[] = {
1988 MockRead(ASYNC
, 0, 0) // EOF
1990 DeterministicSocketData
data(reads
, arraysize(reads
),
1991 writes
, arraysize(writes
));
1992 data
.set_connect_data(connect_data
);
1993 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1995 CreateDeterministicNetworkSession();
1997 base::WeakPtr
<SpdySession
> session
=
1998 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2000 GURL
url1(kDefaultURL
);
2001 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2002 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2003 session
, url1
, HIGHEST
, BoundNetLog());
2004 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2005 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2007 GURL
url2(kDefaultURL
);
2008 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2009 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2010 session
, url2
, LOWEST
, BoundNetLog());
2011 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2012 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2014 test::ClosingDelegate
delegate1(spdy_stream1
);
2015 spdy_stream1
->SetDelegate(&delegate1
);
2017 test::ClosingDelegate
delegate2(spdy_stream2
);
2018 spdy_stream2
->SetDelegate(&delegate2
);
2020 scoped_ptr
<SpdyHeaderBlock
> headers(
2021 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2022 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2023 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2025 scoped_ptr
<SpdyHeaderBlock
> headers2(
2026 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2027 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2028 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2030 // Ensure that the streams have not yet been activated and assigned an id.
2031 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2032 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2034 // Ensure we don't crash while closing the session.
2035 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2037 EXPECT_EQ(NULL
, spdy_stream1
.get());
2038 EXPECT_EQ(NULL
, spdy_stream2
.get());
2040 EXPECT_TRUE(delegate1
.StreamIsClosed());
2041 EXPECT_TRUE(delegate2
.StreamIsClosed());
2043 base::MessageLoop::current()->RunUntilIdle();
2044 EXPECT_TRUE(session
== NULL
);
2047 // Create two streams that are set to close each other on close, and
2048 // then close the session. Nothing should blow up.
2049 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedMutuallyClosingStreams
) {
2050 session_deps_
.host_resolver
->set_synchronous_mode(true);
2052 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2054 // No actual data will be sent.
2055 MockWrite writes
[] = {
2056 MockWrite(ASYNC
, 0, 1) // EOF
2059 MockRead reads
[] = {
2060 MockRead(ASYNC
, 0, 0) // EOF
2062 DeterministicSocketData
data(reads
, arraysize(reads
),
2063 writes
, arraysize(writes
));
2064 data
.set_connect_data(connect_data
);
2065 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2067 CreateDeterministicNetworkSession();
2069 base::WeakPtr
<SpdySession
> session
=
2070 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2072 GURL
url1(kDefaultURL
);
2073 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2074 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2075 session
, url1
, HIGHEST
, BoundNetLog());
2076 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2077 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2079 GURL
url2(kDefaultURL
);
2080 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2081 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2082 session
, url2
, LOWEST
, BoundNetLog());
2083 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2084 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2086 // Make |spdy_stream1| close |spdy_stream2|.
2087 test::ClosingDelegate
delegate1(spdy_stream2
);
2088 spdy_stream1
->SetDelegate(&delegate1
);
2090 // Make |spdy_stream2| close |spdy_stream1|.
2091 test::ClosingDelegate
delegate2(spdy_stream1
);
2092 spdy_stream2
->SetDelegate(&delegate2
);
2094 scoped_ptr
<SpdyHeaderBlock
> headers(
2095 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2096 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2097 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2099 scoped_ptr
<SpdyHeaderBlock
> headers2(
2100 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2101 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2102 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2104 // Ensure that the streams have not yet been activated and assigned an id.
2105 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2106 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2108 // Ensure we don't crash while closing the session.
2109 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2111 EXPECT_EQ(NULL
, spdy_stream1
.get());
2112 EXPECT_EQ(NULL
, spdy_stream2
.get());
2114 EXPECT_TRUE(delegate1
.StreamIsClosed());
2115 EXPECT_TRUE(delegate2
.StreamIsClosed());
2117 base::MessageLoop::current()->RunUntilIdle();
2118 EXPECT_TRUE(session
== NULL
);
2121 // Create two streams that are set to re-close themselves on close,
2122 // activate them, and then close the session. Nothing should blow up.
2123 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedSelfClosingStreams
) {
2124 session_deps_
.host_resolver
->set_synchronous_mode(true);
2126 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2128 scoped_ptr
<SpdyFrame
> req1(
2129 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2130 scoped_ptr
<SpdyFrame
> req2(
2131 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
2132 MockWrite writes
[] = {
2133 CreateMockWrite(*req1
, 0),
2134 CreateMockWrite(*req2
, 1),
2137 MockRead reads
[] = {
2138 MockRead(ASYNC
, 0, 2) // EOF
2141 DeterministicSocketData
data(reads
, arraysize(reads
),
2142 writes
, arraysize(writes
));
2143 data
.set_connect_data(connect_data
);
2144 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2146 CreateDeterministicNetworkSession();
2148 base::WeakPtr
<SpdySession
> session
=
2149 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2151 GURL
url1(kDefaultURL
);
2152 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2153 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2154 session
, url1
, MEDIUM
, BoundNetLog());
2155 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2156 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2158 GURL
url2(kDefaultURL
);
2159 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2160 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2161 session
, url2
, MEDIUM
, BoundNetLog());
2162 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2163 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2165 test::ClosingDelegate
delegate1(spdy_stream1
);
2166 spdy_stream1
->SetDelegate(&delegate1
);
2168 test::ClosingDelegate
delegate2(spdy_stream2
);
2169 spdy_stream2
->SetDelegate(&delegate2
);
2171 scoped_ptr
<SpdyHeaderBlock
> headers(
2172 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2173 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2174 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2176 scoped_ptr
<SpdyHeaderBlock
> headers2(
2177 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2178 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2179 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2181 // Ensure that the streams have not yet been activated and assigned an id.
2182 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2183 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2187 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2188 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2190 // Ensure we don't crash while closing the session.
2191 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2193 EXPECT_EQ(NULL
, spdy_stream1
.get());
2194 EXPECT_EQ(NULL
, spdy_stream2
.get());
2196 EXPECT_TRUE(delegate1
.StreamIsClosed());
2197 EXPECT_TRUE(delegate2
.StreamIsClosed());
2199 base::MessageLoop::current()->RunUntilIdle();
2200 EXPECT_TRUE(session
== NULL
);
2203 // Create two streams that are set to close each other on close,
2204 // activate them, and then close the session. Nothing should blow up.
2205 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedMutuallyClosingStreams
) {
2206 session_deps_
.host_resolver
->set_synchronous_mode(true);
2208 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2210 scoped_ptr
<SpdyFrame
> req1(
2211 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2212 scoped_ptr
<SpdyFrame
> req2(
2213 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
2214 MockWrite writes
[] = {
2215 CreateMockWrite(*req1
, 0),
2216 CreateMockWrite(*req2
, 1),
2219 MockRead reads
[] = {
2220 MockRead(ASYNC
, 0, 2) // EOF
2223 DeterministicSocketData
data(reads
, arraysize(reads
),
2224 writes
, arraysize(writes
));
2225 data
.set_connect_data(connect_data
);
2226 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2228 CreateDeterministicNetworkSession();
2230 base::WeakPtr
<SpdySession
> session
=
2231 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2233 GURL
url1(kDefaultURL
);
2234 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2235 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2236 session
, url1
, MEDIUM
, BoundNetLog());
2237 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2238 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2240 GURL
url2(kDefaultURL
);
2241 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2242 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2243 session
, url2
, MEDIUM
, BoundNetLog());
2244 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2245 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2247 // Make |spdy_stream1| close |spdy_stream2|.
2248 test::ClosingDelegate
delegate1(spdy_stream2
);
2249 spdy_stream1
->SetDelegate(&delegate1
);
2251 // Make |spdy_stream2| close |spdy_stream1|.
2252 test::ClosingDelegate
delegate2(spdy_stream1
);
2253 spdy_stream2
->SetDelegate(&delegate2
);
2255 scoped_ptr
<SpdyHeaderBlock
> headers(
2256 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2257 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2258 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2260 scoped_ptr
<SpdyHeaderBlock
> headers2(
2261 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2262 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2263 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2265 // Ensure that the streams have not yet been activated and assigned an id.
2266 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2267 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2271 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2272 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2274 // Ensure we don't crash while closing the session.
2275 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2277 EXPECT_EQ(NULL
, spdy_stream1
.get());
2278 EXPECT_EQ(NULL
, spdy_stream2
.get());
2280 EXPECT_TRUE(delegate1
.StreamIsClosed());
2281 EXPECT_TRUE(delegate2
.StreamIsClosed());
2283 base::MessageLoop::current()->RunUntilIdle();
2284 EXPECT_TRUE(session
== NULL
);
2287 // Delegate that closes a given session when the stream is closed.
2288 class SessionClosingDelegate
: public test::StreamDelegateDoNothing
{
2290 SessionClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
2291 const base::WeakPtr
<SpdySession
>& session_to_close
)
2292 : StreamDelegateDoNothing(stream
),
2293 session_to_close_(session_to_close
) {}
2295 ~SessionClosingDelegate() override
{}
2297 void OnClose(int status
) override
{
2298 session_to_close_
->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR
, "Error");
2302 base::WeakPtr
<SpdySession
> session_to_close_
;
2305 // Close an activated stream that closes its session. Nothing should
2306 // blow up. This is a regression test for http://crbug.com/263691 .
2307 TEST_P(SpdySessionTest
, CloseActivatedStreamThatClosesSession
) {
2308 session_deps_
.host_resolver
->set_synchronous_mode(true);
2310 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2312 scoped_ptr
<SpdyFrame
> req(
2313 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2314 scoped_ptr
<SpdyFrame
> rst(
2315 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2316 scoped_ptr
<SpdyFrame
> goaway(
2317 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Error"));
2318 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2319 // despite being queued second.
2320 MockWrite writes
[] = {
2321 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 1),
2322 CreateMockWrite(*rst
, 2),
2325 MockRead reads
[] = {
2326 MockRead(ASYNC
, 0, 3) // EOF
2328 DeterministicSocketData
data(reads
, arraysize(reads
),
2329 writes
, arraysize(writes
));
2330 data
.set_connect_data(connect_data
);
2331 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2333 CreateDeterministicNetworkSession();
2335 base::WeakPtr
<SpdySession
> session
=
2336 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2338 GURL
url(kDefaultURL
);
2339 base::WeakPtr
<SpdyStream
> spdy_stream
=
2340 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2341 session
, url
, MEDIUM
, BoundNetLog());
2342 ASSERT_TRUE(spdy_stream
.get() != NULL
);
2343 EXPECT_EQ(0u, spdy_stream
->stream_id());
2345 SessionClosingDelegate
delegate(spdy_stream
, session
);
2346 spdy_stream
->SetDelegate(&delegate
);
2348 scoped_ptr
<SpdyHeaderBlock
> headers(
2349 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
2350 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2351 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
2353 EXPECT_EQ(0u, spdy_stream
->stream_id());
2357 EXPECT_EQ(1u, spdy_stream
->stream_id());
2359 // Ensure we don't crash while closing the stream (which closes the
2361 spdy_stream
->Cancel();
2363 EXPECT_EQ(NULL
, spdy_stream
.get());
2364 EXPECT_TRUE(delegate
.StreamIsClosed());
2366 data
.RunFor(2); // Write the RST_STREAM & GOAWAY.
2367 base::MessageLoop::current()->RunUntilIdle();
2368 EXPECT_TRUE(session
== NULL
);
2371 TEST_P(SpdySessionTest
, VerifyDomainAuthentication
) {
2372 session_deps_
.host_resolver
->set_synchronous_mode(true);
2374 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2376 // No actual data will be sent.
2377 MockWrite writes
[] = {
2378 MockWrite(ASYNC
, 0, 1) // EOF
2381 MockRead reads
[] = {
2382 MockRead(ASYNC
, 0, 0) // EOF
2384 DeterministicSocketData
data(reads
, arraysize(reads
),
2385 writes
, arraysize(writes
));
2386 data
.set_connect_data(connect_data
);
2387 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2389 // Load a cert that is valid for:
2393 base::FilePath certs_dir
= GetTestCertsDirectory();
2394 scoped_refptr
<X509Certificate
> test_cert(
2395 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2396 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
.get());
2398 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2399 ssl
.cert
= test_cert
;
2400 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2402 CreateDeterministicNetworkSession();
2404 base::WeakPtr
<SpdySession
> session
=
2405 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2407 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2408 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2409 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.com"));
2410 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2413 TEST_P(SpdySessionTest
, ConnectionPooledWithTlsChannelId
) {
2414 session_deps_
.host_resolver
->set_synchronous_mode(true);
2416 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2418 // No actual data will be sent.
2419 MockWrite writes
[] = {
2420 MockWrite(ASYNC
, 0, 1) // EOF
2423 MockRead reads
[] = {
2424 MockRead(ASYNC
, 0, 0) // EOF
2426 DeterministicSocketData
data(reads
, arraysize(reads
),
2427 writes
, arraysize(writes
));
2428 data
.set_connect_data(connect_data
);
2429 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2431 // Load a cert that is valid for:
2435 base::FilePath certs_dir
= GetTestCertsDirectory();
2436 scoped_refptr
<X509Certificate
> test_cert(
2437 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2438 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
.get());
2440 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2441 ssl
.channel_id_sent
= true;
2442 ssl
.cert
= test_cert
;
2443 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2445 CreateDeterministicNetworkSession();
2447 base::WeakPtr
<SpdySession
> session
=
2448 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2450 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2451 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2452 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.example.com"));
2453 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2456 TEST_P(SpdySessionTest
, CloseTwoStalledCreateStream
) {
2457 // TODO(rtenneti): Define a helper class/methods and move the common code in
2459 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2461 SettingsMap new_settings
;
2462 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
2463 const uint32 max_concurrent_streams
= 1;
2464 new_settings
[kSpdySettingsIds1
] =
2465 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
2467 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
2468 scoped_ptr
<SpdyFrame
> req1(
2469 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2470 scoped_ptr
<SpdyFrame
> req2(
2471 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
2472 scoped_ptr
<SpdyFrame
> req3(
2473 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
2474 MockWrite writes
[] = {
2475 CreateMockWrite(*settings_ack
, 1),
2476 CreateMockWrite(*req1
, 2),
2477 CreateMockWrite(*req2
, 5),
2478 CreateMockWrite(*req3
, 8),
2481 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2483 scoped_ptr
<SpdyFrame
> settings_frame(
2484 spdy_util_
.ConstructSpdySettings(new_settings
));
2486 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2487 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2489 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
2490 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
2492 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
2493 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
2495 MockRead reads
[] = {
2496 CreateMockRead(*settings_frame
),
2497 CreateMockRead(*resp1
, 3),
2498 CreateMockRead(*body1
, 4),
2499 CreateMockRead(*resp2
, 6),
2500 CreateMockRead(*body2
, 7),
2501 CreateMockRead(*resp3
, 9),
2502 CreateMockRead(*body3
, 10),
2503 MockRead(ASYNC
, 0, 11) // EOF
2506 DeterministicSocketData
data(reads
, arraysize(reads
),
2507 writes
, arraysize(writes
));
2508 data
.set_connect_data(connect_data
);
2509 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2511 CreateDeterministicNetworkSession();
2513 base::WeakPtr
<SpdySession
> session
=
2514 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2516 // Read the settings frame.
2519 GURL
url1(kDefaultURL
);
2520 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2521 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2522 session
, url1
, LOWEST
, BoundNetLog());
2523 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2524 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2525 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2526 spdy_stream1
->SetDelegate(&delegate1
);
2528 TestCompletionCallback callback2
;
2529 GURL
url2(kDefaultURL
);
2530 SpdyStreamRequest request2
;
2531 ASSERT_EQ(ERR_IO_PENDING
,
2532 request2
.StartRequest(
2533 SPDY_REQUEST_RESPONSE_STREAM
,
2534 session
, url2
, LOWEST
, BoundNetLog(), callback2
.callback()));
2536 TestCompletionCallback callback3
;
2537 GURL
url3(kDefaultURL
);
2538 SpdyStreamRequest request3
;
2539 ASSERT_EQ(ERR_IO_PENDING
,
2540 request3
.StartRequest(
2541 SPDY_REQUEST_RESPONSE_STREAM
,
2542 session
, url3
, LOWEST
, BoundNetLog(), callback3
.callback()));
2544 EXPECT_EQ(0u, session
->num_active_streams());
2545 EXPECT_EQ(1u, session
->num_created_streams());
2546 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2548 scoped_ptr
<SpdyHeaderBlock
> headers(
2549 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2550 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2551 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2553 // Run until 1st stream is activated and then closed.
2554 EXPECT_EQ(0u, delegate1
.stream_id());
2556 EXPECT_EQ(NULL
, spdy_stream1
.get());
2557 EXPECT_EQ(1u, delegate1
.stream_id());
2559 EXPECT_EQ(0u, session
->num_active_streams());
2560 EXPECT_EQ(0u, session
->num_created_streams());
2561 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2563 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2564 // create the 2nd stream.
2565 base::MessageLoop::current()->RunUntilIdle();
2567 EXPECT_EQ(0u, session
->num_active_streams());
2568 EXPECT_EQ(1u, session
->num_created_streams());
2569 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2571 base::WeakPtr
<SpdyStream
> stream2
= request2
.ReleaseStream();
2572 test::StreamDelegateDoNothing
delegate2(stream2
);
2573 stream2
->SetDelegate(&delegate2
);
2574 scoped_ptr
<SpdyHeaderBlock
> headers2(
2575 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2576 stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2577 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
2579 // Run until 2nd stream is activated and then closed.
2580 EXPECT_EQ(0u, delegate2
.stream_id());
2582 EXPECT_EQ(NULL
, stream2
.get());
2583 EXPECT_EQ(3u, delegate2
.stream_id());
2585 EXPECT_EQ(0u, session
->num_active_streams());
2586 EXPECT_EQ(0u, session
->num_created_streams());
2587 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2589 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2590 // create the 3rd stream.
2591 base::MessageLoop::current()->RunUntilIdle();
2593 EXPECT_EQ(0u, session
->num_active_streams());
2594 EXPECT_EQ(1u, session
->num_created_streams());
2595 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2597 base::WeakPtr
<SpdyStream
> stream3
= request3
.ReleaseStream();
2598 test::StreamDelegateDoNothing
delegate3(stream3
);
2599 stream3
->SetDelegate(&delegate3
);
2600 scoped_ptr
<SpdyHeaderBlock
> headers3(
2601 spdy_util_
.ConstructGetHeaderBlock(url3
.spec()));
2602 stream3
->SendRequestHeaders(headers3
.Pass(), NO_MORE_DATA_TO_SEND
);
2603 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
2605 // Run until 2nd stream is activated and then closed.
2606 EXPECT_EQ(0u, delegate3
.stream_id());
2608 EXPECT_EQ(NULL
, stream3
.get());
2609 EXPECT_EQ(5u, delegate3
.stream_id());
2611 EXPECT_EQ(0u, session
->num_active_streams());
2612 EXPECT_EQ(0u, session
->num_created_streams());
2613 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2618 TEST_P(SpdySessionTest
, CancelTwoStalledCreateStream
) {
2619 session_deps_
.host_resolver
->set_synchronous_mode(true);
2621 MockRead reads
[] = {
2622 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2625 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
2626 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2628 data
.set_connect_data(connect_data
);
2629 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2631 CreateNetworkSession();
2633 base::WeakPtr
<SpdySession
> session
=
2634 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2636 // Leave room for only one more stream to be created.
2637 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
2638 base::WeakPtr
<SpdyStream
> spdy_stream
=
2639 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2640 session
, test_url_
, MEDIUM
, BoundNetLog());
2641 ASSERT_TRUE(spdy_stream
!= NULL
);
2644 GURL
url1(kDefaultURL
);
2645 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2646 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2647 session
, url1
, LOWEST
, BoundNetLog());
2648 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2649 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2651 TestCompletionCallback callback2
;
2652 GURL
url2(kDefaultURL
);
2653 SpdyStreamRequest request2
;
2654 ASSERT_EQ(ERR_IO_PENDING
,
2655 request2
.StartRequest(
2656 SPDY_BIDIRECTIONAL_STREAM
, session
, url2
, LOWEST
, BoundNetLog(),
2657 callback2
.callback()));
2659 TestCompletionCallback callback3
;
2660 GURL
url3(kDefaultURL
);
2661 SpdyStreamRequest request3
;
2662 ASSERT_EQ(ERR_IO_PENDING
,
2663 request3
.StartRequest(
2664 SPDY_BIDIRECTIONAL_STREAM
, session
, url3
, LOWEST
, BoundNetLog(),
2665 callback3
.callback()));
2667 EXPECT_EQ(0u, session
->num_active_streams());
2668 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2669 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2671 // Cancel the first stream; this will allow the second stream to be created.
2672 EXPECT_TRUE(spdy_stream1
.get() != NULL
);
2673 spdy_stream1
->Cancel();
2674 EXPECT_EQ(NULL
, spdy_stream1
.get());
2676 EXPECT_EQ(OK
, callback2
.WaitForResult());
2677 EXPECT_EQ(0u, session
->num_active_streams());
2678 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2679 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2681 // Cancel the second stream; this will allow the third stream to be created.
2682 base::WeakPtr
<SpdyStream
> spdy_stream2
= request2
.ReleaseStream();
2683 spdy_stream2
->Cancel();
2684 EXPECT_EQ(NULL
, spdy_stream2
.get());
2686 EXPECT_EQ(OK
, callback3
.WaitForResult());
2687 EXPECT_EQ(0u, session
->num_active_streams());
2688 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2689 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2691 // Cancel the third stream.
2692 base::WeakPtr
<SpdyStream
> spdy_stream3
= request3
.ReleaseStream();
2693 spdy_stream3
->Cancel();
2694 EXPECT_EQ(NULL
, spdy_stream3
.get());
2695 EXPECT_EQ(0u, session
->num_active_streams());
2696 EXPECT_EQ(kInitialMaxConcurrentStreams
- 1, session
->num_created_streams());
2697 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2700 // Test that SpdySession::DoReadLoop reads data from the socket
2701 // without yielding. This test makes 32k - 1 bytes of data available
2702 // on the socket for reading. It then verifies that it has read all
2703 // the available data without yielding.
2704 TEST_P(SpdySessionTest
, ReadDataWithoutYielding
) {
2705 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2706 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2708 scoped_ptr
<SpdyFrame
> req1(
2709 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2710 MockWrite writes
[] = {
2711 CreateMockWrite(*req1
, 0),
2714 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2715 // (-spdy_data_frame_size).
2716 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2717 const int kPayloadSize
=
2718 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2719 TestDataStream test_stream
;
2720 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
2721 char* payload_data
= payload
->data();
2722 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2724 scoped_ptr
<SpdyFrame
> partial_data_frame(
2725 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2726 scoped_ptr
<SpdyFrame
> finish_data_frame(
2727 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
- 1, DATA_FLAG_FIN
));
2729 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2731 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2733 MockRead reads
[] = {
2734 CreateMockRead(*resp1
, 1),
2735 CreateMockRead(*partial_data_frame
, 2),
2736 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2737 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2738 CreateMockRead(*finish_data_frame
, 5, SYNCHRONOUS
),
2739 MockRead(ASYNC
, 0, 6) // EOF
2742 // Create SpdySession and SpdyStream and send the request.
2743 DeterministicSocketData
data(reads
, arraysize(reads
),
2744 writes
, arraysize(writes
));
2745 data
.set_connect_data(connect_data
);
2746 session_deps_
.host_resolver
->set_synchronous_mode(true);
2747 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2749 CreateDeterministicNetworkSession();
2751 base::WeakPtr
<SpdySession
> session
=
2752 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2754 GURL
url1(kDefaultURL
);
2755 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2756 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2757 session
, url1
, MEDIUM
, BoundNetLog());
2758 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2759 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2760 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2761 spdy_stream1
->SetDelegate(&delegate1
);
2763 scoped_ptr
<SpdyHeaderBlock
> headers1(
2764 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2765 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2766 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2768 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2770 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2772 // Run until 1st read.
2773 EXPECT_EQ(0u, delegate1
.stream_id());
2775 EXPECT_EQ(1u, delegate1
.stream_id());
2776 EXPECT_EQ(0u, observer
.executed_count());
2778 // Read all the data and verify SpdySession::DoReadLoop has not
2781 EXPECT_EQ(NULL
, spdy_stream1
.get());
2783 // Verify task observer's executed_count is zero, which indicates DoRead read
2784 // all the available data.
2785 EXPECT_EQ(0u, observer
.executed_count());
2786 EXPECT_TRUE(data
.at_write_eof());
2787 EXPECT_TRUE(data
.at_read_eof());
2790 // Test that SpdySession::DoReadLoop yields while reading the
2791 // data. This test makes 32k + 1 bytes of data available on the socket
2792 // for reading. It then verifies that DoRead has yielded even though
2793 // there is data available for it to read (i.e, socket()->Read didn't
2794 // return ERR_IO_PENDING during socket reads).
2795 TEST_P(SpdySessionTest
, TestYieldingDuringReadData
) {
2796 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2797 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2799 scoped_ptr
<SpdyFrame
> req1(
2800 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2801 MockWrite writes
[] = {
2802 CreateMockWrite(*req1
, 0),
2805 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2806 // (-spdy_data_frame_size).
2807 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2808 const int kPayloadSize
=
2809 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2810 TestDataStream test_stream
;
2811 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
2812 char* payload_data
= payload
->data();
2813 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2815 scoped_ptr
<SpdyFrame
> partial_data_frame(
2816 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2817 scoped_ptr
<SpdyFrame
> finish_data_frame(
2818 framer
.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN
));
2820 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2822 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2823 MockRead reads
[] = {
2824 CreateMockRead(*resp1
, 1),
2825 CreateMockRead(*partial_data_frame
, 2),
2826 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2827 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2828 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2829 CreateMockRead(*finish_data_frame
, 6, SYNCHRONOUS
),
2830 MockRead(ASYNC
, 0, 7) // EOF
2833 // Create SpdySession and SpdyStream and send the request.
2834 DeterministicSocketData
data(reads
, arraysize(reads
),
2835 writes
, arraysize(writes
));
2836 data
.set_connect_data(connect_data
);
2837 session_deps_
.host_resolver
->set_synchronous_mode(true);
2838 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2840 CreateDeterministicNetworkSession();
2842 base::WeakPtr
<SpdySession
> session
=
2843 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2845 GURL
url1(kDefaultURL
);
2846 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2847 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2848 session
, url1
, MEDIUM
, BoundNetLog());
2849 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2850 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2851 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2852 spdy_stream1
->SetDelegate(&delegate1
);
2854 scoped_ptr
<SpdyHeaderBlock
> headers1(
2855 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2856 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2857 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2859 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2861 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2863 // Run until 1st read.
2864 EXPECT_EQ(0u, delegate1
.stream_id());
2866 EXPECT_EQ(1u, delegate1
.stream_id());
2867 EXPECT_EQ(0u, observer
.executed_count());
2869 // Read all the data and verify SpdySession::DoReadLoop has posted a
2872 EXPECT_EQ(NULL
, spdy_stream1
.get());
2874 // Verify task observer's executed_count is 1, which indicates DoRead has
2875 // posted only one task and thus yielded though there is data available for it
2877 EXPECT_EQ(1u, observer
.executed_count());
2878 EXPECT_TRUE(data
.at_write_eof());
2879 EXPECT_TRUE(data
.at_read_eof());
2882 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2883 // + async, by doing the following MockReads.
2885 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2886 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2888 // The above reads 26K synchronously. Since that is less that 32K, we
2889 // will attempt to read again. However, that DoRead() will return
2890 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2891 // yield. When we come back, DoRead() will read the results from the
2892 // async read, and rest of the data synchronously.
2893 TEST_P(SpdySessionTest
, TestYieldingDuringAsyncReadData
) {
2894 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2895 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2897 scoped_ptr
<SpdyFrame
> req1(
2898 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2899 MockWrite writes
[] = {
2900 CreateMockWrite(*req1
, 0),
2903 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2904 // (-spdy_data_frame_size).
2905 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2906 TestDataStream test_stream
;
2907 const int kEightKPayloadSize
=
2908 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2909 scoped_refptr
<net::IOBuffer
> eightk_payload(
2910 new net::IOBuffer(kEightKPayloadSize
));
2911 char* eightk_payload_data
= eightk_payload
->data();
2912 test_stream
.GetBytes(eightk_payload_data
, kEightKPayloadSize
);
2914 // Build buffer of 2k size.
2915 TestDataStream test_stream2
;
2916 const int kTwoKPayloadSize
= kEightKPayloadSize
- 6 * 1024;
2917 scoped_refptr
<net::IOBuffer
> twok_payload(
2918 new net::IOBuffer(kTwoKPayloadSize
));
2919 char* twok_payload_data
= twok_payload
->data();
2920 test_stream2
.GetBytes(twok_payload_data
, kTwoKPayloadSize
);
2922 scoped_ptr
<SpdyFrame
> eightk_data_frame(framer
.CreateDataFrame(
2923 1, eightk_payload_data
, kEightKPayloadSize
, DATA_FLAG_NONE
));
2924 scoped_ptr
<SpdyFrame
> twok_data_frame(framer
.CreateDataFrame(
2925 1, twok_payload_data
, kTwoKPayloadSize
, DATA_FLAG_NONE
));
2926 scoped_ptr
<SpdyFrame
> finish_data_frame(framer
.CreateDataFrame(
2927 1, "h", 1, DATA_FLAG_FIN
));
2929 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2931 MockRead reads
[] = {
2932 CreateMockRead(*resp1
, 1),
2933 CreateMockRead(*eightk_data_frame
, 2),
2934 CreateMockRead(*eightk_data_frame
, 3, SYNCHRONOUS
),
2935 CreateMockRead(*eightk_data_frame
, 4, SYNCHRONOUS
),
2936 CreateMockRead(*twok_data_frame
, 5, SYNCHRONOUS
),
2937 CreateMockRead(*eightk_data_frame
, 6, ASYNC
),
2938 CreateMockRead(*eightk_data_frame
, 7, SYNCHRONOUS
),
2939 CreateMockRead(*eightk_data_frame
, 8, SYNCHRONOUS
),
2940 CreateMockRead(*eightk_data_frame
, 9, SYNCHRONOUS
),
2941 CreateMockRead(*twok_data_frame
, 10, SYNCHRONOUS
),
2942 CreateMockRead(*finish_data_frame
, 11, SYNCHRONOUS
),
2943 MockRead(ASYNC
, 0, 12) // EOF
2946 // Create SpdySession and SpdyStream and send the request.
2947 DeterministicSocketData
data(reads
, arraysize(reads
),
2948 writes
, arraysize(writes
));
2949 data
.set_connect_data(connect_data
);
2950 session_deps_
.host_resolver
->set_synchronous_mode(true);
2951 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2953 CreateDeterministicNetworkSession();
2955 base::WeakPtr
<SpdySession
> session
=
2956 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2958 GURL
url1(kDefaultURL
);
2959 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2960 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2961 session
, url1
, MEDIUM
, BoundNetLog());
2962 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2963 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2964 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2965 spdy_stream1
->SetDelegate(&delegate1
);
2967 scoped_ptr
<SpdyHeaderBlock
> headers1(
2968 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2969 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2970 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2972 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2973 // posting of tasks.
2974 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2976 // Run until 1st read.
2977 EXPECT_EQ(0u, delegate1
.stream_id());
2979 EXPECT_EQ(1u, delegate1
.stream_id());
2980 EXPECT_EQ(0u, observer
.executed_count());
2982 // Read all the data and verify SpdySession::DoReadLoop has posted a
2985 EXPECT_EQ(NULL
, spdy_stream1
.get());
2987 // Verify task observer's executed_count is 1, which indicates DoRead has
2988 // posted only one task and thus yielded though there is data available for
2990 EXPECT_EQ(1u, observer
.executed_count());
2991 EXPECT_TRUE(data
.at_write_eof());
2992 EXPECT_TRUE(data
.at_read_eof());
2995 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2996 // nothing blows up.
2997 TEST_P(SpdySessionTest
, GoAwayWhileInDoReadLoop
) {
2998 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2999 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3001 scoped_ptr
<SpdyFrame
> req1(
3002 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
3003 MockWrite writes
[] = {
3004 CreateMockWrite(*req1
, 0),
3007 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3008 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3009 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
3011 MockRead reads
[] = {
3012 CreateMockRead(*resp1
, 1),
3013 CreateMockRead(*body1
, 2),
3014 CreateMockRead(*goaway
, 3),
3017 // Create SpdySession and SpdyStream and send the request.
3018 DeterministicSocketData
data(reads
, arraysize(reads
),
3019 writes
, arraysize(writes
));
3020 data
.set_connect_data(connect_data
);
3021 session_deps_
.host_resolver
->set_synchronous_mode(true);
3022 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3024 CreateDeterministicNetworkSession();
3026 base::WeakPtr
<SpdySession
> session
=
3027 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3029 GURL
url1(kDefaultURL
);
3030 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3031 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3032 session
, url1
, MEDIUM
, BoundNetLog());
3033 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3034 spdy_stream1
->SetDelegate(&delegate1
);
3035 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
3036 EXPECT_EQ(0u, spdy_stream1
->stream_id());
3038 scoped_ptr
<SpdyHeaderBlock
> headers1(
3039 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
3040 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
3041 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3043 // Run until 1st read.
3044 EXPECT_EQ(0u, spdy_stream1
->stream_id());
3046 EXPECT_EQ(1u, spdy_stream1
->stream_id());
3048 // Run until GoAway.
3050 EXPECT_EQ(NULL
, spdy_stream1
.get());
3051 EXPECT_TRUE(data
.at_write_eof());
3052 EXPECT_TRUE(data
.at_read_eof());
3053 EXPECT_TRUE(session
== NULL
);
3056 // Within this framework, a SpdySession should be initialized with
3057 // flow control disabled for protocol version 2, with flow control
3058 // enabled only for streams for protocol version 3, and with flow
3059 // control enabled for streams and sessions for higher versions.
3060 TEST_P(SpdySessionTest
, ProtocolNegotiation
) {
3061 session_deps_
.host_resolver
->set_synchronous_mode(true);
3063 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3064 MockRead reads
[] = {
3065 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3067 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3068 data
.set_connect_data(connect_data
);
3069 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3071 CreateNetworkSession();
3072 base::WeakPtr
<SpdySession
> session
=
3073 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3075 EXPECT_EQ(spdy_util_
.spdy_version(),
3076 session
->buffered_spdy_framer_
->protocol_version());
3077 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3078 session
->flow_control_state());
3079 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3080 session
->session_send_window_size_
);
3081 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3082 session
->session_recv_window_size_
);
3083 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3086 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3087 // pointers to the idle session are currently held.
3088 TEST_P(SpdySessionTest
, CloseOneIdleConnection
) {
3089 ClientSocketPoolManager::set_max_sockets_per_group(
3090 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3091 ClientSocketPoolManager::set_max_sockets_per_pool(
3092 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3094 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3095 MockRead reads
[] = {
3096 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3098 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3099 data
.set_connect_data(connect_data
);
3100 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3101 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3103 CreateNetworkSession();
3105 TransportClientSocketPool
* pool
=
3106 http_session_
->GetTransportSocketPool(
3107 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3109 // Create an idle SPDY session.
3110 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3111 PRIVACY_MODE_DISABLED
);
3112 base::WeakPtr
<SpdySession
> session1
=
3113 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3114 EXPECT_FALSE(pool
->IsStalled());
3116 // Trying to create a new connection should cause the pool to be stalled, and
3117 // post a task asynchronously to try and close the session.
3118 TestCompletionCallback callback2
;
3119 HostPortPair
host_port2("2.com", 80);
3120 scoped_refptr
<TransportSocketParams
> params2(
3121 new TransportSocketParams(
3122 host_port2
, false, false, OnHostResolutionCallback(),
3123 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3124 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3125 EXPECT_EQ(ERR_IO_PENDING
,
3126 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3127 callback2
.callback(), pool
, BoundNetLog()));
3128 EXPECT_TRUE(pool
->IsStalled());
3130 // The socket pool should close the connection asynchronously and establish a
3132 EXPECT_EQ(OK
, callback2
.WaitForResult());
3133 EXPECT_FALSE(pool
->IsStalled());
3134 EXPECT_TRUE(session1
== NULL
);
3137 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3138 // pointers to the idle session are currently held, in the case the SPDY session
3140 TEST_P(SpdySessionTest
, CloseOneIdleConnectionWithAlias
) {
3141 ClientSocketPoolManager::set_max_sockets_per_group(
3142 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3143 ClientSocketPoolManager::set_max_sockets_per_pool(
3144 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3146 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3147 MockRead reads
[] = {
3148 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3150 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3151 data
.set_connect_data(connect_data
);
3152 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3153 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3155 session_deps_
.host_resolver
->set_synchronous_mode(true);
3156 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3157 "1.com", "192.168.0.2", std::string());
3158 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3159 "2.com", "192.168.0.2", std::string());
3160 // Not strictly needed.
3161 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3162 "3.com", "192.168.0.3", std::string());
3164 CreateNetworkSession();
3166 TransportClientSocketPool
* pool
=
3167 http_session_
->GetTransportSocketPool(
3168 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3170 // Create an idle SPDY session.
3171 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3172 PRIVACY_MODE_DISABLED
);
3173 base::WeakPtr
<SpdySession
> session1
=
3174 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3175 EXPECT_FALSE(pool
->IsStalled());
3177 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3178 SpdySessionKey
key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3179 PRIVACY_MODE_DISABLED
);
3180 HostResolver::RequestInfo
info(key2
.host_port_pair());
3181 AddressList addresses
;
3182 // Pre-populate the DNS cache, since a synchronous resolution is required in
3183 // order to create the alias.
3184 session_deps_
.host_resolver
->Resolve(info
,
3187 CompletionCallback(),
3190 // Get a session for |key2|, which should return the session created earlier.
3191 base::WeakPtr
<SpdySession
> session2
=
3192 spdy_session_pool_
->FindAvailableSession(key2
, BoundNetLog());
3193 ASSERT_EQ(session1
.get(), session2
.get());
3194 EXPECT_FALSE(pool
->IsStalled());
3196 // Trying to create a new connection should cause the pool to be stalled, and
3197 // post a task asynchronously to try and close the session.
3198 TestCompletionCallback callback3
;
3199 HostPortPair
host_port3("3.com", 80);
3200 scoped_refptr
<TransportSocketParams
> params3(
3201 new TransportSocketParams(
3202 host_port3
, false, false, OnHostResolutionCallback(),
3203 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3204 scoped_ptr
<ClientSocketHandle
> connection3(new ClientSocketHandle
);
3205 EXPECT_EQ(ERR_IO_PENDING
,
3206 connection3
->Init(host_port3
.ToString(), params3
, DEFAULT_PRIORITY
,
3207 callback3
.callback(), pool
, BoundNetLog()));
3208 EXPECT_TRUE(pool
->IsStalled());
3210 // The socket pool should close the connection asynchronously and establish a
3212 EXPECT_EQ(OK
, callback3
.WaitForResult());
3213 EXPECT_FALSE(pool
->IsStalled());
3214 EXPECT_TRUE(session1
== NULL
);
3215 EXPECT_TRUE(session2
== NULL
);
3218 // Tests that when a SPDY session becomes idle, it closes itself if there is
3219 // a lower layer pool stalled on the per-pool socket limit.
3220 TEST_P(SpdySessionTest
, CloseSessionOnIdleWhenPoolStalled
) {
3221 ClientSocketPoolManager::set_max_sockets_per_group(
3222 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3223 ClientSocketPoolManager::set_max_sockets_per_pool(
3224 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3226 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3227 MockRead reads
[] = {
3228 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3230 scoped_ptr
<SpdyFrame
> req1(
3231 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3232 scoped_ptr
<SpdyFrame
> cancel1(
3233 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3234 MockWrite writes
[] = {
3235 CreateMockWrite(*req1
, 1),
3236 CreateMockWrite(*cancel1
, 1),
3238 StaticSocketDataProvider
data(reads
, arraysize(reads
),
3239 writes
, arraysize(writes
));
3240 data
.set_connect_data(connect_data
);
3241 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3243 MockRead http_reads
[] = {
3244 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3246 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
3248 http_data
.set_connect_data(connect_data
);
3249 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
3252 CreateNetworkSession();
3254 TransportClientSocketPool
* pool
=
3255 http_session_
->GetTransportSocketPool(
3256 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3258 // Create a SPDY session.
3259 GURL
url1(kDefaultURL
);
3260 SpdySessionKey
key1(HostPortPair(url1
.host(), 80),
3261 ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3262 base::WeakPtr
<SpdySession
> session1
=
3263 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3264 EXPECT_FALSE(pool
->IsStalled());
3266 // Create a stream using the session, and send a request.
3268 TestCompletionCallback callback1
;
3269 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3270 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3271 session1
, url1
, DEFAULT_PRIORITY
,
3273 ASSERT_TRUE(spdy_stream1
.get());
3274 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3275 spdy_stream1
->SetDelegate(&delegate1
);
3277 scoped_ptr
<SpdyHeaderBlock
> headers1(
3278 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
3279 EXPECT_EQ(ERR_IO_PENDING
,
3280 spdy_stream1
->SendRequestHeaders(
3281 headers1
.Pass(), NO_MORE_DATA_TO_SEND
));
3282 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3284 base::MessageLoop::current()->RunUntilIdle();
3286 // Trying to create a new connection should cause the pool to be stalled, and
3287 // post a task asynchronously to try and close the session.
3288 TestCompletionCallback callback2
;
3289 HostPortPair
host_port2("2.com", 80);
3290 scoped_refptr
<TransportSocketParams
> params2(
3291 new TransportSocketParams(
3292 host_port2
, false, false, OnHostResolutionCallback(),
3293 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3294 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3295 EXPECT_EQ(ERR_IO_PENDING
,
3296 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3297 callback2
.callback(), pool
, BoundNetLog()));
3298 EXPECT_TRUE(pool
->IsStalled());
3300 // Running the message loop should cause the socket pool to ask the SPDY
3301 // session to close an idle socket, but since the socket is in use, nothing
3303 base::RunLoop().RunUntilIdle();
3304 EXPECT_TRUE(pool
->IsStalled());
3305 EXPECT_FALSE(callback2
.have_result());
3307 // Cancelling the request should result in the session's socket being
3308 // closed, since the pool is stalled.
3309 ASSERT_TRUE(spdy_stream1
.get());
3310 spdy_stream1
->Cancel();
3311 base::RunLoop().RunUntilIdle();
3312 ASSERT_FALSE(pool
->IsStalled());
3313 EXPECT_EQ(OK
, callback2
.WaitForResult());
3316 // Verify that SpdySessionKey and therefore SpdySession is different when
3317 // privacy mode is enabled or disabled.
3318 TEST_P(SpdySessionTest
, SpdySessionKeyPrivacyMode
) {
3319 CreateDeterministicNetworkSession();
3321 HostPortPair
host_port_pair("www.google.com", 443);
3322 SpdySessionKey
key_privacy_enabled(host_port_pair
, ProxyServer::Direct(),
3323 PRIVACY_MODE_ENABLED
);
3324 SpdySessionKey
key_privacy_disabled(host_port_pair
, ProxyServer::Direct(),
3325 PRIVACY_MODE_DISABLED
);
3327 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3328 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3330 // Add SpdySession with PrivacyMode Enabled to the pool.
3331 base::WeakPtr
<SpdySession
> session_privacy_enabled
=
3332 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_enabled
);
3334 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3335 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3337 // Add SpdySession with PrivacyMode Disabled to the pool.
3338 base::WeakPtr
<SpdySession
> session_privacy_disabled
=
3339 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_disabled
);
3341 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3342 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3344 session_privacy_enabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3345 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3346 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3348 session_privacy_disabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3349 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3350 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3353 // Delegate that creates another stream when its stream is closed.
3354 class StreamCreatingDelegate
: public test::StreamDelegateDoNothing
{
3356 StreamCreatingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3357 const base::WeakPtr
<SpdySession
>& session
)
3358 : StreamDelegateDoNothing(stream
),
3359 session_(session
) {}
3361 ~StreamCreatingDelegate() override
{}
3363 void OnClose(int status
) override
{
3364 GURL
url(kDefaultURL
);
3366 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3367 session_
, url
, MEDIUM
, BoundNetLog()));
3371 const base::WeakPtr
<SpdySession
> session_
;
3374 // Create another stream in response to a stream being reset. Nothing
3375 // should blow up. This is a regression test for
3376 // http://crbug.com/263690 .
3377 TEST_P(SpdySessionTest
, CreateStreamOnStreamReset
) {
3378 session_deps_
.host_resolver
->set_synchronous_mode(true);
3380 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3382 scoped_ptr
<SpdyFrame
> req(
3383 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
3384 MockWrite writes
[] = {
3385 CreateMockWrite(*req
, 0),
3388 scoped_ptr
<SpdyFrame
> rst(
3389 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
3390 MockRead reads
[] = {
3391 CreateMockRead(*rst
, 1),
3392 MockRead(ASYNC
, 0, 2) // EOF
3394 DeterministicSocketData
data(reads
, arraysize(reads
),
3395 writes
, arraysize(writes
));
3396 data
.set_connect_data(connect_data
);
3397 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3399 CreateDeterministicNetworkSession();
3401 base::WeakPtr
<SpdySession
> session
=
3402 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3404 GURL
url(kDefaultURL
);
3405 base::WeakPtr
<SpdyStream
> spdy_stream
=
3406 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3407 session
, url
, MEDIUM
, BoundNetLog());
3408 ASSERT_TRUE(spdy_stream
.get() != NULL
);
3409 EXPECT_EQ(0u, spdy_stream
->stream_id());
3411 StreamCreatingDelegate
delegate(spdy_stream
, session
);
3412 spdy_stream
->SetDelegate(&delegate
);
3414 scoped_ptr
<SpdyHeaderBlock
> headers(
3415 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
3416 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
3417 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
3419 EXPECT_EQ(0u, spdy_stream
->stream_id());
3423 EXPECT_EQ(1u, spdy_stream
->stream_id());
3425 // Cause the stream to be reset, which should cause another stream
3429 EXPECT_EQ(NULL
, spdy_stream
.get());
3430 EXPECT_TRUE(delegate
.StreamIsClosed());
3431 EXPECT_EQ(0u, session
->num_active_streams());
3432 EXPECT_EQ(1u, session
->num_created_streams());
3435 // The tests below are only for SPDY/3 and above.
3437 TEST_P(SpdySessionTest
, UpdateStreamsSendWindowSize
) {
3438 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3440 SettingsMap new_settings
;
3441 int32 window_size
= 1;
3442 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
3443 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, window_size
);
3445 // Set up the socket so we read a SETTINGS frame that sets
3446 // INITIAL_WINDOW_SIZE.
3447 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3448 scoped_ptr
<SpdyFrame
> settings_frame(
3449 spdy_util_
.ConstructSpdySettings(new_settings
));
3450 MockRead reads
[] = {
3451 CreateMockRead(*settings_frame
, 0),
3452 MockRead(ASYNC
, 0, 1) // EOF
3455 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
3456 MockWrite writes
[] = {
3457 CreateMockWrite(*settings_ack
, 2),
3460 session_deps_
.host_resolver
->set_synchronous_mode(true);
3462 DeterministicSocketData
data(reads
, arraysize(reads
),
3463 writes
, arraysize(writes
));
3464 data
.set_connect_data(connect_data
);
3465 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3467 CreateDeterministicNetworkSession();
3469 base::WeakPtr
<SpdySession
> session
=
3470 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3471 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3472 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3473 session
, test_url_
, MEDIUM
, BoundNetLog());
3474 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
3475 TestCompletionCallback callback1
;
3476 EXPECT_NE(spdy_stream1
->send_window_size(), window_size
);
3478 data
.RunFor(1); // Process the SETTINGS frame, but not the EOF
3479 base::MessageLoop::current()->RunUntilIdle();
3480 EXPECT_EQ(session
->stream_initial_send_window_size(), window_size
);
3481 EXPECT_EQ(spdy_stream1
->send_window_size(), window_size
);
3483 // Release the first one, this will allow the second to be created.
3484 spdy_stream1
->Cancel();
3485 EXPECT_EQ(NULL
, spdy_stream1
.get());
3487 base::WeakPtr
<SpdyStream
> spdy_stream2
=
3488 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3489 session
, test_url_
, MEDIUM
, BoundNetLog());
3490 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
3491 EXPECT_EQ(spdy_stream2
->send_window_size(), window_size
);
3492 spdy_stream2
->Cancel();
3493 EXPECT_EQ(NULL
, spdy_stream2
.get());
3496 // The tests below are only for SPDY/3.1 and above.
3498 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3499 // adjust the session receive window size for SPDY 3.1 and higher. In
3500 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3501 // sending a WINDOW_UPDATE frame for a large enough delta.
3502 TEST_P(SpdySessionTest
, AdjustRecvWindowSize
) {
3503 if (GetParam() < kProtoSPDY31
)
3506 session_deps_
.host_resolver
->set_synchronous_mode(true);
3508 const int32 initial_window_size
=
3509 SpdySession::GetInitialWindowSize(GetParam());
3510 const int32 delta_window_size
= 100;
3512 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3513 MockRead reads
[] = {
3514 MockRead(ASYNC
, 0, 1) // EOF
3516 scoped_ptr
<SpdyFrame
> window_update(spdy_util_
.ConstructSpdyWindowUpdate(
3517 kSessionFlowControlStreamId
, initial_window_size
+ delta_window_size
));
3518 MockWrite writes
[] = {
3519 CreateMockWrite(*window_update
, 0),
3521 DeterministicSocketData
data(reads
, arraysize(reads
),
3522 writes
, arraysize(writes
));
3523 data
.set_connect_data(connect_data
);
3524 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3526 CreateDeterministicNetworkSession();
3527 base::WeakPtr
<SpdySession
> session
=
3528 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3529 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3530 session
->flow_control_state());
3532 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3533 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3535 session
->IncreaseRecvWindowSize(delta_window_size
);
3536 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3537 session
->session_recv_window_size_
);
3538 EXPECT_EQ(delta_window_size
, session
->session_unacked_recv_window_bytes_
);
3540 // Should trigger sending a WINDOW_UPDATE frame.
3541 session
->IncreaseRecvWindowSize(initial_window_size
);
3542 EXPECT_EQ(initial_window_size
+ delta_window_size
+ initial_window_size
,
3543 session
->session_recv_window_size_
);
3544 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3548 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3549 session
->in_io_loop_
= true;
3550 session
->DecreaseRecvWindowSize(initial_window_size
+ delta_window_size
+
3551 initial_window_size
);
3552 session
->in_io_loop_
= false;
3553 EXPECT_EQ(0, session
->session_recv_window_size_
);
3554 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3557 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3558 // adjust the session send window size when the "enable_spdy_31" flag
3560 TEST_P(SpdySessionTest
, AdjustSendWindowSize
) {
3561 if (GetParam() < kProtoSPDY31
)
3564 session_deps_
.host_resolver
->set_synchronous_mode(true);
3566 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3567 MockRead reads
[] = {
3568 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3570 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3571 data
.set_connect_data(connect_data
);
3572 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3574 CreateNetworkSession();
3575 base::WeakPtr
<SpdySession
> session
=
3576 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3577 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3578 session
->flow_control_state());
3580 const int32 initial_window_size
=
3581 SpdySession::GetInitialWindowSize(GetParam());
3582 const int32 delta_window_size
= 100;
3584 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3586 session
->IncreaseSendWindowSize(delta_window_size
);
3587 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3588 session
->session_send_window_size_
);
3590 session
->DecreaseSendWindowSize(delta_window_size
);
3591 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3594 // Incoming data for an inactive stream should not cause the session
3595 // receive window size to decrease, but it should cause the unacked
3596 // bytes to increase.
3597 TEST_P(SpdySessionTest
, SessionFlowControlInactiveStream
) {
3598 if (GetParam() < kProtoSPDY31
)
3601 session_deps_
.host_resolver
->set_synchronous_mode(true);
3603 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3604 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(1, false));
3605 MockRead reads
[] = {
3606 CreateMockRead(*resp
, 0),
3607 MockRead(ASYNC
, 0, 1) // EOF
3609 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
3610 data
.set_connect_data(connect_data
);
3611 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3613 CreateDeterministicNetworkSession();
3614 base::WeakPtr
<SpdySession
> session
=
3615 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3616 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3617 session
->flow_control_state());
3619 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3620 session
->session_recv_window_size_
);
3621 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3625 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3626 session
->session_recv_window_size_
);
3627 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
3632 // A delegate that drops any received data.
3633 class DropReceivedDataDelegate
: public test::StreamDelegateSendImmediate
{
3635 DropReceivedDataDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3636 base::StringPiece data
)
3637 : StreamDelegateSendImmediate(stream
, data
) {}
3639 ~DropReceivedDataDelegate() override
{}
3641 // Drop any received data.
3642 void OnDataReceived(scoped_ptr
<SpdyBuffer
> buffer
) override
{}
3645 // Send data back and forth but use a delegate that drops its received
3646 // data. The receive window should still increase to its original
3647 // value, i.e. we shouldn't "leak" receive window bytes.
3648 TEST_P(SpdySessionTest
, SessionFlowControlNoReceiveLeaks
) {
3649 if (GetParam() < kProtoSPDY31
)
3652 const char kStreamUrl
[] = "http://www.google.com/";
3654 const int32 msg_data_size
= 100;
3655 const std::string
msg_data(msg_data_size
, 'a');
3657 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3659 scoped_ptr
<SpdyFrame
> req(
3660 spdy_util_
.ConstructSpdyPost(
3661 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3662 scoped_ptr
<SpdyFrame
> msg(
3663 spdy_util_
.ConstructSpdyBodyFrame(
3664 1, msg_data
.data(), msg_data_size
, false));
3665 MockWrite writes
[] = {
3666 CreateMockWrite(*req
, 0),
3667 CreateMockWrite(*msg
, 2),
3670 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3671 scoped_ptr
<SpdyFrame
> echo(
3672 spdy_util_
.ConstructSpdyBodyFrame(
3673 1, msg_data
.data(), msg_data_size
, false));
3674 scoped_ptr
<SpdyFrame
> window_update(
3675 spdy_util_
.ConstructSpdyWindowUpdate(
3676 kSessionFlowControlStreamId
, msg_data_size
));
3677 MockRead reads
[] = {
3678 CreateMockRead(*resp
, 1),
3679 CreateMockRead(*echo
, 3),
3680 MockRead(ASYNC
, 0, 4) // EOF
3683 // Create SpdySession and SpdyStream and send the request.
3684 DeterministicSocketData
data(reads
, arraysize(reads
),
3685 writes
, arraysize(writes
));
3686 data
.set_connect_data(connect_data
);
3687 session_deps_
.host_resolver
->set_synchronous_mode(true);
3688 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3690 CreateDeterministicNetworkSession();
3692 base::WeakPtr
<SpdySession
> session
=
3693 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3695 GURL
url(kStreamUrl
);
3696 base::WeakPtr
<SpdyStream
> stream
=
3697 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3698 session
, url
, MEDIUM
, BoundNetLog());
3699 ASSERT_TRUE(stream
.get() != NULL
);
3700 EXPECT_EQ(0u, stream
->stream_id());
3702 DropReceivedDataDelegate
delegate(stream
, msg_data
);
3703 stream
->SetDelegate(&delegate
);
3705 scoped_ptr
<SpdyHeaderBlock
> headers(
3706 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3707 EXPECT_EQ(ERR_IO_PENDING
,
3708 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3709 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3711 const int32 initial_window_size
=
3712 SpdySession::GetInitialWindowSize(GetParam());
3713 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3714 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3718 EXPECT_TRUE(data
.at_write_eof());
3719 EXPECT_TRUE(data
.at_read_eof());
3721 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3722 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3725 EXPECT_EQ(NULL
, stream
.get());
3727 EXPECT_EQ(OK
, delegate
.WaitForClose());
3729 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3730 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3733 // Send data back and forth but close the stream before its data frame
3734 // can be written to the socket. The send window should then increase
3735 // to its original value, i.e. we shouldn't "leak" send window bytes.
3736 TEST_P(SpdySessionTest
, SessionFlowControlNoSendLeaks
) {
3737 if (GetParam() < kProtoSPDY31
)
3740 const char kStreamUrl
[] = "http://www.google.com/";
3742 const int32 msg_data_size
= 100;
3743 const std::string
msg_data(msg_data_size
, 'a');
3745 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3747 scoped_ptr
<SpdyFrame
> req(
3748 spdy_util_
.ConstructSpdyPost(
3749 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3750 MockWrite writes
[] = {
3751 CreateMockWrite(*req
, 0),
3754 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3755 MockRead reads
[] = {
3756 CreateMockRead(*resp
, 1),
3757 MockRead(ASYNC
, 0, 2) // EOF
3760 // Create SpdySession and SpdyStream and send the request.
3761 DeterministicSocketData
data(reads
, arraysize(reads
),
3762 writes
, arraysize(writes
));
3763 data
.set_connect_data(connect_data
);
3764 session_deps_
.host_resolver
->set_synchronous_mode(true);
3765 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3767 CreateDeterministicNetworkSession();
3769 base::WeakPtr
<SpdySession
> session
=
3770 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3772 GURL
url(kStreamUrl
);
3773 base::WeakPtr
<SpdyStream
> stream
=
3774 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3775 session
, url
, MEDIUM
, BoundNetLog());
3776 ASSERT_TRUE(stream
.get() != NULL
);
3777 EXPECT_EQ(0u, stream
->stream_id());
3779 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3780 stream
->SetDelegate(&delegate
);
3782 scoped_ptr
<SpdyHeaderBlock
> headers(
3783 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3784 EXPECT_EQ(ERR_IO_PENDING
,
3785 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3786 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3788 const int32 initial_window_size
=
3789 SpdySession::GetInitialWindowSize(GetParam());
3790 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3794 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3798 EXPECT_TRUE(data
.at_write_eof());
3799 EXPECT_TRUE(data
.at_read_eof());
3801 EXPECT_EQ(initial_window_size
- msg_data_size
,
3802 session
->session_send_window_size_
);
3804 // Closing the stream should increase the session's send window.
3806 EXPECT_EQ(NULL
, stream
.get());
3808 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3810 EXPECT_EQ(OK
, delegate
.WaitForClose());
3813 // Send data back and forth; the send and receive windows should
3814 // change appropriately.
3815 TEST_P(SpdySessionTest
, SessionFlowControlEndToEnd
) {
3816 if (GetParam() < kProtoSPDY31
)
3819 const char kStreamUrl
[] = "http://www.google.com/";
3821 const int32 msg_data_size
= 100;
3822 const std::string
msg_data(msg_data_size
, 'a');
3824 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3826 scoped_ptr
<SpdyFrame
> req(
3827 spdy_util_
.ConstructSpdyPost(
3828 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3829 scoped_ptr
<SpdyFrame
> msg(
3830 spdy_util_
.ConstructSpdyBodyFrame(
3831 1, msg_data
.data(), msg_data_size
, false));
3832 MockWrite writes
[] = {
3833 CreateMockWrite(*req
, 0),
3834 CreateMockWrite(*msg
, 2),
3837 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3838 scoped_ptr
<SpdyFrame
> echo(
3839 spdy_util_
.ConstructSpdyBodyFrame(
3840 1, msg_data
.data(), msg_data_size
, false));
3841 scoped_ptr
<SpdyFrame
> window_update(
3842 spdy_util_
.ConstructSpdyWindowUpdate(
3843 kSessionFlowControlStreamId
, msg_data_size
));
3844 MockRead reads
[] = {
3845 CreateMockRead(*resp
, 1),
3846 CreateMockRead(*echo
, 3),
3847 CreateMockRead(*window_update
, 4),
3848 MockRead(ASYNC
, 0, 5) // EOF
3851 // Create SpdySession and SpdyStream and send the request.
3852 DeterministicSocketData
data(reads
, arraysize(reads
),
3853 writes
, arraysize(writes
));
3854 data
.set_connect_data(connect_data
);
3855 session_deps_
.host_resolver
->set_synchronous_mode(true);
3856 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3858 CreateDeterministicNetworkSession();
3860 base::WeakPtr
<SpdySession
> session
=
3861 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3863 GURL
url(kStreamUrl
);
3864 base::WeakPtr
<SpdyStream
> stream
=
3865 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3866 session
, url
, MEDIUM
, BoundNetLog());
3867 ASSERT_TRUE(stream
.get() != NULL
);
3868 EXPECT_EQ(0u, stream
->stream_id());
3870 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3871 stream
->SetDelegate(&delegate
);
3873 scoped_ptr
<SpdyHeaderBlock
> headers(
3874 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3875 EXPECT_EQ(ERR_IO_PENDING
,
3876 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3877 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3879 const int32 initial_window_size
=
3880 SpdySession::GetInitialWindowSize(GetParam());
3881 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3882 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3883 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3887 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3888 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3889 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3893 EXPECT_EQ(initial_window_size
- msg_data_size
,
3894 session
->session_send_window_size_
);
3895 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3896 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3900 EXPECT_EQ(initial_window_size
- msg_data_size
,
3901 session
->session_send_window_size_
);
3902 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3903 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3907 EXPECT_EQ(initial_window_size
- msg_data_size
,
3908 session
->session_send_window_size_
);
3909 EXPECT_EQ(initial_window_size
- msg_data_size
,
3910 session
->session_recv_window_size_
);
3911 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3915 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3916 EXPECT_EQ(initial_window_size
- msg_data_size
,
3917 session
->session_recv_window_size_
);
3918 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3920 EXPECT_TRUE(data
.at_write_eof());
3921 EXPECT_TRUE(data
.at_read_eof());
3923 EXPECT_EQ(msg_data
, delegate
.TakeReceivedData());
3925 // Draining the delegate's read queue should increase the session's
3927 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3928 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3929 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3932 EXPECT_EQ(NULL
, stream
.get());
3934 EXPECT_EQ(OK
, delegate
.WaitForClose());
3936 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3937 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3938 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3941 // Given a stall function and an unstall function, runs a test to make
3942 // sure that a stream resumes after unstall.
3943 void SpdySessionTest::RunResumeAfterUnstallTest(
3944 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
3945 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
3947 const char kStreamUrl
[] = "http://www.google.com/";
3948 GURL
url(kStreamUrl
);
3950 session_deps_
.host_resolver
->set_synchronous_mode(true);
3952 scoped_ptr
<SpdyFrame
> req(
3953 spdy_util_
.ConstructSpdyPost(
3954 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
3955 scoped_ptr
<SpdyFrame
> body(
3956 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
3957 MockWrite writes
[] = {
3958 CreateMockWrite(*req
, 0),
3959 CreateMockWrite(*body
, 1),
3962 scoped_ptr
<SpdyFrame
> resp(
3963 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3964 scoped_ptr
<SpdyFrame
> echo(
3965 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
3966 MockRead reads
[] = {
3967 CreateMockRead(*resp
, 2),
3968 MockRead(ASYNC
, 0, 0, 3), // EOF
3971 DeterministicSocketData
data(reads
, arraysize(reads
),
3972 writes
, arraysize(writes
));
3973 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3974 data
.set_connect_data(connect_data
);
3976 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3978 CreateDeterministicNetworkSession();
3979 base::WeakPtr
<SpdySession
> session
=
3980 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3981 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3982 session
->flow_control_state());
3984 base::WeakPtr
<SpdyStream
> stream
=
3985 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3986 session
, url
, LOWEST
, BoundNetLog());
3987 ASSERT_TRUE(stream
.get() != NULL
);
3989 test::StreamDelegateWithBody
delegate(stream
, kBodyDataStringPiece
);
3990 stream
->SetDelegate(&delegate
);
3992 EXPECT_FALSE(stream
->HasUrlFromHeaders());
3993 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
3995 scoped_ptr
<SpdyHeaderBlock
> headers(
3996 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
3997 EXPECT_EQ(ERR_IO_PENDING
,
3998 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3999 EXPECT_TRUE(stream
->HasUrlFromHeaders());
4000 EXPECT_EQ(kStreamUrl
, stream
->GetUrlFromHeaders().spec());
4002 stall_function
.Run(session
.get(), stream
.get());
4006 EXPECT_TRUE(stream
->send_stalled_by_flow_control());
4008 unstall_function
.Run(session
.get(), stream
.get(), kBodyDataSize
);
4010 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4014 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
4016 EXPECT_TRUE(delegate
.send_headers_completed());
4017 EXPECT_EQ("200", delegate
.GetResponseHeaderValue(":status"));
4018 EXPECT_EQ(std::string(), delegate
.TakeReceivedData());
4019 EXPECT_TRUE(data
.at_write_eof());
4022 // Run the resume-after-unstall test with all possible stall and
4023 // unstall sequences.
4025 TEST_P(SpdySessionTest
, ResumeAfterUnstallSession
) {
4026 if (GetParam() < kProtoSPDY31
)
4029 RunResumeAfterUnstallTest(
4030 base::Bind(&SpdySessionTest::StallSessionOnly
,
4031 base::Unretained(this)),
4032 base::Bind(&SpdySessionTest::UnstallSessionOnly
,
4033 base::Unretained(this)));
4037 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4038 TEST_P(SpdySessionTest
, ResumeAfterUnstallStream
) {
4039 if (GetParam() < kProtoSPDY31
)
4042 RunResumeAfterUnstallTest(
4043 base::Bind(&SpdySessionTest::StallStreamOnly
,
4044 base::Unretained(this)),
4045 base::Bind(&SpdySessionTest::UnstallStreamOnly
,
4046 base::Unretained(this)));
4049 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallSessionStream
) {
4050 if (GetParam() < kProtoSPDY31
)
4053 RunResumeAfterUnstallTest(
4054 base::Bind(&SpdySessionTest::StallSessionStream
,
4055 base::Unretained(this)),
4056 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4057 base::Unretained(this)));
4060 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallSessionStream
) {
4061 if (GetParam() < kProtoSPDY31
)
4064 RunResumeAfterUnstallTest(
4065 base::Bind(&SpdySessionTest::StallStreamSession
,
4066 base::Unretained(this)),
4067 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4068 base::Unretained(this)));
4071 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallStreamSession
) {
4072 if (GetParam() < kProtoSPDY31
)
4075 RunResumeAfterUnstallTest(
4076 base::Bind(&SpdySessionTest::StallStreamSession
,
4077 base::Unretained(this)),
4078 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4079 base::Unretained(this)));
4082 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallStreamSession
) {
4083 if (GetParam() < kProtoSPDY31
)
4086 RunResumeAfterUnstallTest(
4087 base::Bind(&SpdySessionTest::StallSessionStream
,
4088 base::Unretained(this)),
4089 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4090 base::Unretained(this)));
4093 // Cause a stall by reducing the flow control send window to 0. The
4094 // streams should resume in priority order when that window is then
4096 TEST_P(SpdySessionTest
, ResumeByPriorityAfterSendWindowSizeIncrease
) {
4097 if (GetParam() < kProtoSPDY31
)
4100 const char kStreamUrl
[] = "http://www.google.com/";
4101 GURL
url(kStreamUrl
);
4103 session_deps_
.host_resolver
->set_synchronous_mode(true);
4105 scoped_ptr
<SpdyFrame
> req1(
4106 spdy_util_
.ConstructSpdyPost(
4107 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4108 scoped_ptr
<SpdyFrame
> req2(
4109 spdy_util_
.ConstructSpdyPost(
4110 kStreamUrl
, 3, kBodyDataSize
, MEDIUM
, NULL
, 0));
4111 scoped_ptr
<SpdyFrame
> body1(
4112 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
4113 scoped_ptr
<SpdyFrame
> body2(
4114 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4115 MockWrite writes
[] = {
4116 CreateMockWrite(*req1
, 0),
4117 CreateMockWrite(*req2
, 1),
4118 CreateMockWrite(*body2
, 2),
4119 CreateMockWrite(*body1
, 3),
4122 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4123 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4124 MockRead reads
[] = {
4125 CreateMockRead(*resp1
, 4),
4126 CreateMockRead(*resp2
, 5),
4127 MockRead(ASYNC
, 0, 0, 6), // EOF
4130 DeterministicSocketData
data(reads
, arraysize(reads
),
4131 writes
, arraysize(writes
));
4132 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4133 data
.set_connect_data(connect_data
);
4135 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4137 CreateDeterministicNetworkSession();
4138 base::WeakPtr
<SpdySession
> session
=
4139 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4140 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4141 session
->flow_control_state());
4143 base::WeakPtr
<SpdyStream
> stream1
=
4144 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4145 session
, url
, LOWEST
, BoundNetLog());
4146 ASSERT_TRUE(stream1
.get() != NULL
);
4148 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4149 stream1
->SetDelegate(&delegate1
);
4151 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4153 base::WeakPtr
<SpdyStream
> stream2
=
4154 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4155 session
, url
, MEDIUM
, BoundNetLog());
4156 ASSERT_TRUE(stream2
.get() != NULL
);
4158 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4159 stream2
->SetDelegate(&delegate2
);
4161 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4163 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4164 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4166 StallSessionSend(session
.get());
4168 scoped_ptr
<SpdyHeaderBlock
> headers1(
4169 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4170 EXPECT_EQ(ERR_IO_PENDING
,
4171 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4172 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4173 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4176 EXPECT_EQ(1u, stream1
->stream_id());
4177 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4179 scoped_ptr
<SpdyHeaderBlock
> headers2(
4180 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4181 EXPECT_EQ(ERR_IO_PENDING
,
4182 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4183 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4184 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4187 EXPECT_EQ(3u, stream2
->stream_id());
4188 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4190 // This should unstall only stream2.
4191 UnstallSessionSend(session
.get(), kBodyDataSize
);
4193 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4194 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4198 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4199 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4201 // This should then unstall stream1.
4202 UnstallSessionSend(session
.get(), kBodyDataSize
);
4204 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4205 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4209 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4210 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4212 EXPECT_TRUE(delegate1
.send_headers_completed());
4213 EXPECT_EQ("200", delegate1
.GetResponseHeaderValue(":status"));
4214 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4216 EXPECT_TRUE(delegate2
.send_headers_completed());
4217 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4218 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4220 EXPECT_TRUE(data
.at_write_eof());
4223 // Delegate that closes a given stream after sending its body.
4224 class StreamClosingDelegate
: public test::StreamDelegateWithBody
{
4226 StreamClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
4227 base::StringPiece data
)
4228 : StreamDelegateWithBody(stream
, data
) {}
4230 ~StreamClosingDelegate() override
{}
4232 void set_stream_to_close(const base::WeakPtr
<SpdyStream
>& stream_to_close
) {
4233 stream_to_close_
= stream_to_close
;
4236 void OnDataSent() override
{
4237 test::StreamDelegateWithBody::OnDataSent();
4238 if (stream_to_close_
.get()) {
4239 stream_to_close_
->Close();
4240 EXPECT_EQ(NULL
, stream_to_close_
.get());
4245 base::WeakPtr
<SpdyStream
> stream_to_close_
;
4248 // Cause a stall by reducing the flow control send window to
4249 // 0. Unstalling the session should properly handle deleted streams.
4250 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedStreams
) {
4251 if (GetParam() < kProtoSPDY31
)
4254 const char kStreamUrl
[] = "http://www.google.com/";
4255 GURL
url(kStreamUrl
);
4257 session_deps_
.host_resolver
->set_synchronous_mode(true);
4259 scoped_ptr
<SpdyFrame
> req1(
4260 spdy_util_
.ConstructSpdyPost(
4261 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4262 scoped_ptr
<SpdyFrame
> req2(
4263 spdy_util_
.ConstructSpdyPost(
4264 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, NULL
, 0));
4265 scoped_ptr
<SpdyFrame
> req3(
4266 spdy_util_
.ConstructSpdyPost(
4267 kStreamUrl
, 5, kBodyDataSize
, LOWEST
, NULL
, 0));
4268 scoped_ptr
<SpdyFrame
> body2(
4269 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4270 MockWrite writes
[] = {
4271 CreateMockWrite(*req1
, 0),
4272 CreateMockWrite(*req2
, 1),
4273 CreateMockWrite(*req3
, 2),
4274 CreateMockWrite(*body2
, 3),
4277 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4278 MockRead reads
[] = {
4279 CreateMockRead(*resp2
, 4),
4280 MockRead(ASYNC
, 0, 0, 5), // EOF
4283 DeterministicSocketData
data(reads
, arraysize(reads
),
4284 writes
, arraysize(writes
));
4285 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4286 data
.set_connect_data(connect_data
);
4288 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4290 CreateDeterministicNetworkSession();
4291 base::WeakPtr
<SpdySession
> session
=
4292 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4293 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4294 session
->flow_control_state());
4296 base::WeakPtr
<SpdyStream
> stream1
=
4297 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4298 session
, url
, LOWEST
, BoundNetLog());
4299 ASSERT_TRUE(stream1
.get() != NULL
);
4301 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4302 stream1
->SetDelegate(&delegate1
);
4304 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4306 base::WeakPtr
<SpdyStream
> stream2
=
4307 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4308 session
, url
, LOWEST
, BoundNetLog());
4309 ASSERT_TRUE(stream2
.get() != NULL
);
4311 StreamClosingDelegate
delegate2(stream2
, kBodyDataStringPiece
);
4312 stream2
->SetDelegate(&delegate2
);
4314 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4316 base::WeakPtr
<SpdyStream
> stream3
=
4317 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4318 session
, url
, LOWEST
, BoundNetLog());
4319 ASSERT_TRUE(stream3
.get() != NULL
);
4321 test::StreamDelegateWithBody
delegate3(stream3
, kBodyDataStringPiece
);
4322 stream3
->SetDelegate(&delegate3
);
4324 EXPECT_FALSE(stream3
->HasUrlFromHeaders());
4326 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4327 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4328 EXPECT_FALSE(stream3
->send_stalled_by_flow_control());
4330 StallSessionSend(session
.get());
4332 scoped_ptr
<SpdyHeaderBlock
> headers1(
4333 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4334 EXPECT_EQ(ERR_IO_PENDING
,
4335 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4336 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4337 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4340 EXPECT_EQ(1u, stream1
->stream_id());
4341 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4343 scoped_ptr
<SpdyHeaderBlock
> headers2(
4344 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4345 EXPECT_EQ(ERR_IO_PENDING
,
4346 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4347 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4348 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4351 EXPECT_EQ(3u, stream2
->stream_id());
4352 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4354 scoped_ptr
<SpdyHeaderBlock
> headers3(
4355 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4356 EXPECT_EQ(ERR_IO_PENDING
,
4357 stream3
->SendRequestHeaders(headers3
.Pass(), MORE_DATA_TO_SEND
));
4358 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
4359 EXPECT_EQ(kStreamUrl
, stream3
->GetUrlFromHeaders().spec());
4362 EXPECT_EQ(5u, stream3
->stream_id());
4363 EXPECT_TRUE(stream3
->send_stalled_by_flow_control());
4365 SpdyStreamId stream_id1
= stream1
->stream_id();
4366 SpdyStreamId stream_id2
= stream2
->stream_id();
4367 SpdyStreamId stream_id3
= stream3
->stream_id();
4369 // Close stream1 preemptively.
4370 session
->CloseActiveStream(stream_id1
, ERR_CONNECTION_CLOSED
);
4371 EXPECT_EQ(NULL
, stream1
.get());
4373 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4374 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4375 EXPECT_TRUE(session
->IsStreamActive(stream_id3
));
4377 // Unstall stream2, which should then close stream3.
4378 delegate2
.set_stream_to_close(stream3
);
4379 UnstallSessionSend(session
.get(), kBodyDataSize
);
4382 EXPECT_EQ(NULL
, stream3
.get());
4384 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4385 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4386 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4387 EXPECT_FALSE(session
->IsStreamActive(stream_id3
));
4390 EXPECT_EQ(NULL
, stream2
.get());
4392 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4393 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4394 EXPECT_EQ(OK
, delegate3
.WaitForClose());
4396 EXPECT_TRUE(delegate1
.send_headers_completed());
4397 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4399 EXPECT_TRUE(delegate2
.send_headers_completed());
4400 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4401 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4403 EXPECT_TRUE(delegate3
.send_headers_completed());
4404 EXPECT_EQ(std::string(), delegate3
.TakeReceivedData());
4406 EXPECT_TRUE(data
.at_write_eof());
4409 // Cause a stall by reducing the flow control send window to
4410 // 0. Unstalling the session should properly handle the session itself
4412 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedSession
) {
4413 if (GetParam() < kProtoSPDY31
)
4416 const char kStreamUrl
[] = "http://www.google.com/";
4417 GURL
url(kStreamUrl
);
4419 session_deps_
.host_resolver
->set_synchronous_mode(true);
4421 scoped_ptr
<SpdyFrame
> req1(
4422 spdy_util_
.ConstructSpdyPost(
4423 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4424 scoped_ptr
<SpdyFrame
> req2(
4425 spdy_util_
.ConstructSpdyPost(
4426 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, NULL
, 0));
4427 scoped_ptr
<SpdyFrame
> body1(
4428 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4429 MockWrite writes
[] = {
4430 CreateMockWrite(*req1
, 0),
4431 CreateMockWrite(*req2
, 1),
4434 MockRead reads
[] = {
4435 MockRead(ASYNC
, 0, 0, 2), // EOF
4438 DeterministicSocketData
data(reads
, arraysize(reads
),
4439 writes
, arraysize(writes
));
4440 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4441 data
.set_connect_data(connect_data
);
4443 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4445 CreateDeterministicNetworkSession();
4446 base::WeakPtr
<SpdySession
> session
=
4447 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4448 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4449 session
->flow_control_state());
4451 base::WeakPtr
<SpdyStream
> stream1
=
4452 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4453 session
, url
, LOWEST
, BoundNetLog());
4454 ASSERT_TRUE(stream1
.get() != NULL
);
4456 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4457 stream1
->SetDelegate(&delegate1
);
4459 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4461 base::WeakPtr
<SpdyStream
> stream2
=
4462 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4463 session
, url
, LOWEST
, BoundNetLog());
4464 ASSERT_TRUE(stream2
.get() != NULL
);
4466 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4467 stream2
->SetDelegate(&delegate2
);
4469 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4471 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4472 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4474 StallSessionSend(session
.get());
4476 scoped_ptr
<SpdyHeaderBlock
> headers1(
4477 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4478 EXPECT_EQ(ERR_IO_PENDING
,
4479 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4480 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4481 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4484 EXPECT_EQ(1u, stream1
->stream_id());
4485 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4487 scoped_ptr
<SpdyHeaderBlock
> headers2(
4488 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4489 EXPECT_EQ(ERR_IO_PENDING
,
4490 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4491 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4492 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4495 EXPECT_EQ(3u, stream2
->stream_id());
4496 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4498 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
4501 UnstallSessionSend(session
.get(), kBodyDataSize
);
4503 // Close the session (since we can't do it from within the delegate
4504 // method, since it's in the stream's loop).
4505 session
->CloseSessionOnError(ERR_CONNECTION_CLOSED
, "Closing session");
4506 base::RunLoop().RunUntilIdle();
4507 EXPECT_TRUE(session
== NULL
);
4509 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
4511 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4512 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4514 EXPECT_TRUE(delegate1
.send_headers_completed());
4515 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4517 EXPECT_TRUE(delegate2
.send_headers_completed());
4518 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4520 EXPECT_TRUE(data
.at_write_eof());
4523 TEST_P(SpdySessionTest
, GoAwayOnSessionFlowControlError
) {
4524 if (GetParam() < kProtoSPDY31
)
4527 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4529 scoped_ptr
<SpdyFrame
> req(
4530 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4531 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
4533 GOAWAY_FLOW_CONTROL_ERROR
,
4534 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4535 "the receive window size of 1"));
4536 MockWrite writes
[] = {
4537 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 3),
4540 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4541 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4542 MockRead reads
[] = {
4543 CreateMockRead(*resp
, 1), CreateMockRead(*body
, 2),
4546 DeterministicSocketData
data(
4547 reads
, arraysize(reads
), writes
, arraysize(writes
));
4548 data
.set_connect_data(connect_data
);
4549 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4551 CreateDeterministicNetworkSession();
4553 base::WeakPtr
<SpdySession
> session
=
4554 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4556 GURL
url(kDefaultURL
);
4557 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
4558 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, LOWEST
, BoundNetLog());
4559 ASSERT_TRUE(spdy_stream
.get() != NULL
);
4560 test::StreamDelegateDoNothing
delegate(spdy_stream
);
4561 spdy_stream
->SetDelegate(&delegate
);
4563 scoped_ptr
<SpdyHeaderBlock
> headers(
4564 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
4565 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4567 data
.RunFor(1); // Write request.
4569 // Put session on the edge of overflowing it's recv window.
4570 session
->session_recv_window_size_
= 1;
4572 // Read response headers & body. Body overflows the session window, and a
4573 // goaway is written.
4575 base::MessageLoop::current()->RunUntilIdle();
4577 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR
, delegate
.WaitForClose());
4578 EXPECT_TRUE(session
== NULL
);
4581 TEST_P(SpdySessionTest
, SplitHeaders
) {
4582 GURL
kStreamUrl("http://www.google.com/foo.dat");
4583 SpdyHeaderBlock headers
;
4584 spdy_util_
.AddUrlToHeaderBlock(kStreamUrl
.spec(), &headers
);
4585 headers
["alpha"] = "beta";
4587 SpdyHeaderBlock request_headers
;
4588 SpdyHeaderBlock response_headers
;
4590 SplitPushedHeadersToRequestAndResponse(
4591 headers
, spdy_util_
.spdy_version(), &request_headers
, &response_headers
);
4593 SpdyHeaderBlock::const_iterator it
= response_headers
.find("alpha");
4594 std::string alpha_val
=
4595 (it
== response_headers
.end()) ? std::string() : it
->second
;
4596 EXPECT_EQ("beta", alpha_val
);
4599 GetUrlFromHeaderBlock(request_headers
, spdy_util_
.spdy_version(), true);
4600 EXPECT_EQ(kStreamUrl
, request_url
);
4603 // Regression. Sorta. Push streams and client streams were sharing a single
4604 // limit for a long time.
4605 TEST_P(SpdySessionTest
, PushedStreamShouldNotCountToClientConcurrencyLimit
) {
4606 SettingsMap new_settings
;
4607 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4608 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, 2);
4609 scoped_ptr
<SpdyFrame
> settings_frame(
4610 spdy_util_
.ConstructSpdySettings(new_settings
));
4611 scoped_ptr
<SpdyFrame
> pushed(spdy_util_
.ConstructSpdyPush(
4612 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4613 MockRead reads
[] = {
4614 CreateMockRead(*settings_frame
), CreateMockRead(*pushed
, 3),
4615 MockRead(ASYNC
, 0, 4),
4618 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
4619 scoped_ptr
<SpdyFrame
> req(
4620 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4621 MockWrite writes
[] = {
4622 CreateMockWrite(*settings_ack
, 1), CreateMockWrite(*req
, 2),
4625 DeterministicSocketData
data(
4626 reads
, arraysize(reads
), writes
, arraysize(writes
));
4627 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4628 data
.set_connect_data(connect_data
);
4629 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4631 CreateDeterministicNetworkSession();
4633 base::WeakPtr
<SpdySession
> session
=
4634 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4636 // Read the settings frame.
4639 GURL
url1(kDefaultURL
);
4640 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4641 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4642 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4643 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4644 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4645 spdy_stream1
->SetDelegate(&delegate1
);
4647 EXPECT_EQ(0u, session
->num_active_streams());
4648 EXPECT_EQ(1u, session
->num_created_streams());
4649 EXPECT_EQ(0u, session
->num_pushed_streams());
4650 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4652 scoped_ptr
<SpdyHeaderBlock
> headers(
4653 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4654 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4655 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4657 // Run until 1st stream is activated.
4658 EXPECT_EQ(0u, delegate1
.stream_id());
4660 EXPECT_EQ(1u, delegate1
.stream_id());
4661 EXPECT_EQ(1u, session
->num_active_streams());
4662 EXPECT_EQ(0u, session
->num_created_streams());
4663 EXPECT_EQ(0u, session
->num_pushed_streams());
4664 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4666 // Run until pushed stream is created.
4668 EXPECT_EQ(2u, session
->num_active_streams());
4669 EXPECT_EQ(0u, session
->num_created_streams());
4670 EXPECT_EQ(1u, session
->num_pushed_streams());
4671 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4673 // Second stream should not be stalled, although we have 2 active streams, but
4674 // one of them is push stream and should not be taken into account when we
4675 // create streams on the client.
4676 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
4677 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4678 EXPECT_TRUE(spdy_stream2
.get() != NULL
);
4679 EXPECT_EQ(2u, session
->num_active_streams());
4680 EXPECT_EQ(1u, session
->num_created_streams());
4681 EXPECT_EQ(1u, session
->num_pushed_streams());
4682 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4688 TEST_P(SpdySessionTest
, RejectPushedStreamExceedingConcurrencyLimit
) {
4689 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4690 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4691 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
4692 NULL
, 0, 4, 1, "http://www.google.com/b.dat"));
4693 MockRead reads
[] = {
4694 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
4695 MockRead(ASYNC
, 0, 4),
4698 scoped_ptr
<SpdyFrame
> req(
4699 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4700 scoped_ptr
<SpdyFrame
> rst(
4701 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4702 MockWrite writes
[] = {
4703 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 3),
4706 DeterministicSocketData
data(
4707 reads
, arraysize(reads
), writes
, arraysize(writes
));
4708 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4709 data
.set_connect_data(connect_data
);
4710 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4712 CreateDeterministicNetworkSession();
4714 base::WeakPtr
<SpdySession
> session
=
4715 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4716 session
->set_max_concurrent_pushed_streams(1);
4718 GURL
url1(kDefaultURL
);
4719 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4720 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4721 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4722 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4723 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4724 spdy_stream1
->SetDelegate(&delegate1
);
4726 EXPECT_EQ(0u, session
->num_active_streams());
4727 EXPECT_EQ(1u, session
->num_created_streams());
4728 EXPECT_EQ(0u, session
->num_pushed_streams());
4729 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4731 scoped_ptr
<SpdyHeaderBlock
> headers(
4732 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4733 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4734 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4736 // Run until 1st stream is activated.
4737 EXPECT_EQ(0u, delegate1
.stream_id());
4739 EXPECT_EQ(1u, delegate1
.stream_id());
4740 EXPECT_EQ(1u, session
->num_active_streams());
4741 EXPECT_EQ(0u, session
->num_created_streams());
4742 EXPECT_EQ(0u, session
->num_pushed_streams());
4743 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4745 // Run until pushed stream is created.
4747 EXPECT_EQ(2u, session
->num_active_streams());
4748 EXPECT_EQ(0u, session
->num_created_streams());
4749 EXPECT_EQ(1u, session
->num_pushed_streams());
4750 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4752 // Reset incoming pushed stream.
4754 EXPECT_EQ(2u, session
->num_active_streams());
4755 EXPECT_EQ(0u, session
->num_created_streams());
4756 EXPECT_EQ(1u, session
->num_pushed_streams());
4757 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4763 TEST_P(SpdySessionTest
, IgnoreReservedRemoteStreamsCount
) {
4764 // Streams in reserved remote state exist only in SPDY4.
4765 if (spdy_util_
.spdy_version() < SPDY4
)
4768 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4769 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4770 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4771 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/b.dat",
4772 push_headers
.get());
4773 scoped_ptr
<SpdyFrame
> push_b(
4774 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 4, 1));
4775 scoped_ptr
<SpdyFrame
> headers_b(
4776 spdy_util_
.ConstructSpdyPushHeaders(4, NULL
, 0));
4777 MockRead reads
[] = {
4778 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
4779 CreateMockRead(*headers_b
, 3), MockRead(ASYNC
, 0, 5),
4782 scoped_ptr
<SpdyFrame
> req(
4783 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4784 scoped_ptr
<SpdyFrame
> rst(
4785 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4786 MockWrite writes
[] = {
4787 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 4),
4790 DeterministicSocketData
data(
4791 reads
, arraysize(reads
), writes
, arraysize(writes
));
4792 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4793 data
.set_connect_data(connect_data
);
4794 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4796 CreateDeterministicNetworkSession();
4798 base::WeakPtr
<SpdySession
> session
=
4799 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4800 session
->set_max_concurrent_pushed_streams(1);
4802 GURL
url1(kDefaultURL
);
4803 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4804 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4805 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4806 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4807 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4808 spdy_stream1
->SetDelegate(&delegate1
);
4810 EXPECT_EQ(0u, session
->num_active_streams());
4811 EXPECT_EQ(1u, session
->num_created_streams());
4812 EXPECT_EQ(0u, session
->num_pushed_streams());
4813 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4815 scoped_ptr
<SpdyHeaderBlock
> headers(
4816 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4817 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4818 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4820 // Run until 1st stream is activated.
4821 EXPECT_EQ(0u, delegate1
.stream_id());
4823 EXPECT_EQ(1u, delegate1
.stream_id());
4824 EXPECT_EQ(1u, session
->num_active_streams());
4825 EXPECT_EQ(0u, session
->num_created_streams());
4826 EXPECT_EQ(0u, session
->num_pushed_streams());
4827 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4829 // Run until pushed stream is created.
4831 EXPECT_EQ(2u, session
->num_active_streams());
4832 EXPECT_EQ(0u, session
->num_created_streams());
4833 EXPECT_EQ(1u, session
->num_pushed_streams());
4834 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4836 // Accept promised stream. It should not count towards pushed stream limit.
4838 EXPECT_EQ(3u, session
->num_active_streams());
4839 EXPECT_EQ(0u, session
->num_created_streams());
4840 EXPECT_EQ(2u, session
->num_pushed_streams());
4841 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4843 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4844 // while we accept only one.
4846 EXPECT_EQ(2u, session
->num_active_streams());
4847 EXPECT_EQ(0u, session
->num_created_streams());
4848 EXPECT_EQ(1u, session
->num_pushed_streams());
4849 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4855 TEST_P(SpdySessionTest
, CancelReservedStreamOnHeadersReceived
) {
4856 // Streams in reserved remote state exist only in SPDY4.
4857 if (spdy_util_
.spdy_version() < SPDY4
)
4860 const char kPushedUrl
[] = "http://www.google.com/a.dat";
4861 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4862 spdy_util_
.AddUrlToHeaderBlock(kPushedUrl
, push_headers
.get());
4863 scoped_ptr
<SpdyFrame
> push_promise(
4864 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 2, 1));
4865 scoped_ptr
<SpdyFrame
> headers_frame(
4866 spdy_util_
.ConstructSpdyPushHeaders(2, NULL
, 0));
4867 MockRead reads
[] = {
4868 CreateMockRead(*push_promise
, 1), CreateMockRead(*headers_frame
, 2),
4869 MockRead(ASYNC
, 0, 4),
4872 scoped_ptr
<SpdyFrame
> req(
4873 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4874 scoped_ptr
<SpdyFrame
> rst(
4875 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
4876 MockWrite writes
[] = {
4877 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 3),
4880 DeterministicSocketData
data(
4881 reads
, arraysize(reads
), writes
, arraysize(writes
));
4882 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4883 data
.set_connect_data(connect_data
);
4884 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4886 CreateDeterministicNetworkSession();
4888 base::WeakPtr
<SpdySession
> session
=
4889 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4891 GURL
url1(kDefaultURL
);
4892 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4893 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4894 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4895 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4896 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4897 spdy_stream1
->SetDelegate(&delegate1
);
4899 EXPECT_EQ(0u, session
->num_active_streams());
4900 EXPECT_EQ(1u, session
->num_created_streams());
4901 EXPECT_EQ(0u, session
->num_pushed_streams());
4902 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4904 scoped_ptr
<SpdyHeaderBlock
> headers(
4905 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4906 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4907 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4909 // Run until 1st stream is activated.
4910 EXPECT_EQ(0u, delegate1
.stream_id());
4912 EXPECT_EQ(1u, delegate1
.stream_id());
4913 EXPECT_EQ(1u, session
->num_active_streams());
4914 EXPECT_EQ(0u, session
->num_created_streams());
4915 EXPECT_EQ(0u, session
->num_pushed_streams());
4916 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4918 // Run until pushed stream is created.
4920 EXPECT_EQ(2u, session
->num_active_streams());
4921 EXPECT_EQ(0u, session
->num_created_streams());
4922 EXPECT_EQ(1u, session
->num_pushed_streams());
4923 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4925 base::WeakPtr
<SpdyStream
> pushed_stream
;
4927 session
->GetPushStream(GURL(kPushedUrl
), &pushed_stream
, BoundNetLog());
4929 ASSERT_TRUE(pushed_stream
.get() != NULL
);
4930 test::StreamDelegateCloseOnHeaders
delegate2(pushed_stream
);
4931 pushed_stream
->SetDelegate(&delegate2
);
4933 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4934 // that all our counters are in consistent state.
4936 EXPECT_EQ(1u, session
->num_active_streams());
4937 EXPECT_EQ(0u, session
->num_created_streams());
4938 EXPECT_EQ(0u, session
->num_pushed_streams());
4939 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4945 TEST_P(SpdySessionTest
, RejectInvalidUnknownFrames
) {
4946 session_deps_
.host_resolver
->set_synchronous_mode(true);
4948 MockRead reads
[] = {
4949 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
4952 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
4954 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4955 data
.set_connect_data(connect_data
);
4956 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4958 CreateNetworkSession();
4959 base::WeakPtr
<SpdySession
> session
=
4960 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4962 session
->stream_hi_water_mark_
= 5;
4963 // Low client (odd) ids are fine.
4964 EXPECT_TRUE(session
->OnUnknownFrame(3, 0));
4965 // Client id exceeding watermark.
4966 EXPECT_FALSE(session
->OnUnknownFrame(9, 0));
4968 session
->last_accepted_push_stream_id_
= 6;
4969 // Low server (even) ids are fine.
4970 EXPECT_TRUE(session
->OnUnknownFrame(2, 0));
4971 // Server id exceeding last accepted id.
4972 EXPECT_FALSE(session
->OnUnknownFrame(8, 0));
4975 TEST(MapFramerErrorToProtocolError
, MapsValues
) {
4977 SPDY_ERROR_INVALID_CONTROL_FRAME
,
4978 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4980 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS
,
4981 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
4983 SPDY_ERROR_GOAWAY_FRAME_CORRUPT
,
4984 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT
));
4985 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME
,
4986 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME
));
4989 TEST(MapFramerErrorToNetError
, MapsValue
) {
4990 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR
,
4991 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4992 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
4993 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE
));
4994 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
4995 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE
));
4997 ERR_SPDY_FRAME_SIZE_ERROR
,
4998 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
));
5001 TEST(MapRstStreamStatusToProtocolError
, MapsValues
) {
5002 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR
,
5003 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR
));
5004 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR
,
5005 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR
));
5006 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM
,
5007 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM
));
5008 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY
,
5009 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY
));
5010 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED
,
5011 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED
));
5014 TEST(MapNetErrorToGoAwayStatus
, MapsValue
) {
5015 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY
,
5016 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
));
5017 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR
,
5018 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR
));
5019 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
,
5020 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR
));
5021 CHECK_EQ(GOAWAY_COMPRESSION_ERROR
,
5022 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR
));
5023 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR
,
5024 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR
));
5025 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED
));
5028 TEST(CanPoolTest
, CanPool
) {
5029 // Load a cert that is valid for:
5034 TransportSecurityState tss
;
5036 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5037 "spdy_pooling.pem");
5039 EXPECT_TRUE(SpdySession::CanPool(
5040 &tss
, ssl_info
, "www.example.org", "www.example.org"));
5041 EXPECT_TRUE(SpdySession::CanPool(
5042 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5043 EXPECT_TRUE(SpdySession::CanPool(
5044 &tss
, ssl_info
, "www.example.org", "mail.example.com"));
5045 EXPECT_FALSE(SpdySession::CanPool(
5046 &tss
, ssl_info
, "www.example.org", "mail.google.com"));
5049 TEST(CanPoolTest
, CanNotPoolWithCertErrors
) {
5050 // Load a cert that is valid for:
5055 TransportSecurityState tss
;
5057 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5058 "spdy_pooling.pem");
5059 ssl_info
.cert_status
= CERT_STATUS_REVOKED
;
5061 EXPECT_FALSE(SpdySession::CanPool(
5062 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5065 TEST(CanPoolTest
, CanNotPoolWithClientCerts
) {
5066 // Load a cert that is valid for:
5071 TransportSecurityState tss
;
5073 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5074 "spdy_pooling.pem");
5075 ssl_info
.client_cert_sent
= true;
5077 EXPECT_FALSE(SpdySession::CanPool(
5078 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5081 TEST(CanPoolTest
, CanNotPoolAcrossETLDsWithChannelID
) {
5082 // Load a cert that is valid for:
5087 TransportSecurityState tss
;
5089 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5090 "spdy_pooling.pem");
5091 ssl_info
.channel_id_sent
= true;
5093 EXPECT_TRUE(SpdySession::CanPool(
5094 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5095 EXPECT_FALSE(SpdySession::CanPool(
5096 &tss
, ssl_info
, "www.example.org", "www.example.com"));
5099 TEST(CanPoolTest
, CanNotPoolWithBadPins
) {
5100 uint8 primary_pin
= 1;
5101 uint8 backup_pin
= 2;
5103 TransportSecurityState tss
;
5104 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5107 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5108 "spdy_pooling.pem");
5109 ssl_info
.is_issued_by_known_root
= true;
5110 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(bad_pin
));
5112 EXPECT_FALSE(SpdySession::CanPool(
5113 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5116 TEST(CanPoolTest
, CanPoolWithAcceptablePins
) {
5117 uint8 primary_pin
= 1;
5118 uint8 backup_pin
= 2;
5119 TransportSecurityState tss
;
5120 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5123 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5124 "spdy_pooling.pem");
5125 ssl_info
.is_issued_by_known_root
= true;
5126 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(primary_pin
));
5128 EXPECT_TRUE(SpdySession::CanPool(
5129 &tss
, ssl_info
, "www.example.org", "mail.example.org"));