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 virtual void SetUp() OVERRIDE
{
125 g_time_delta
= base::TimeDelta();
128 void CreateDeterministicNetworkSession() {
130 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
);
131 spdy_session_pool_
= http_session_
->spdy_session_pool();
134 void CreateNetworkSession() {
136 SpdySessionDependencies::SpdyCreateSession(&session_deps_
);
137 spdy_session_pool_
= http_session_
->spdy_session_pool();
140 void StallSessionSend(SpdySession
* session
) {
141 // Reduce the send window size to 0 to stall.
142 while (session
->session_send_window_size_
> 0) {
143 session
->DecreaseSendWindowSize(
144 std::min(kMaxSpdyFrameChunkSize
, session
->session_send_window_size_
));
148 void UnstallSessionSend(SpdySession
* session
, int32 delta_window_size
) {
149 session
->IncreaseSendWindowSize(delta_window_size
);
152 void StallStreamSend(SpdyStream
* stream
) {
153 // Reduce the send window size to 0 to stall.
154 while (stream
->send_window_size() > 0) {
155 stream
->DecreaseSendWindowSize(
156 std::min(kMaxSpdyFrameChunkSize
, stream
->send_window_size()));
160 void UnstallStreamSend(SpdyStream
* stream
, int32 delta_window_size
) {
161 stream
->IncreaseSendWindowSize(delta_window_size
);
164 void RunResumeAfterUnstallTest(
165 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
166 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
169 // Original socket limits. Some tests set these. Safest to always restore
170 // them once each test has been run.
171 int old_max_group_sockets_
;
172 int old_max_pool_sockets_
;
174 SpdyTestUtil spdy_util_
;
175 SpdySessionDependencies session_deps_
;
176 scoped_refptr
<HttpNetworkSession
> http_session_
;
177 SpdySessionPool
* spdy_session_pool_
;
179 HostPortPair test_host_port_pair_
;
183 INSTANTIATE_TEST_CASE_P(
186 testing::Values(kProtoDeprecatedSPDY2
,
187 kProtoSPDY3
, kProtoSPDY31
, kProtoSPDY4
));
189 // Try to create a SPDY session that will fail during
190 // initialization. Nothing should blow up.
191 TEST_P(SpdySessionTest
, InitialReadError
) {
192 CreateDeterministicNetworkSession();
194 base::WeakPtr
<SpdySession
> session
= TryCreateFakeSpdySessionExpectingFailure(
195 spdy_session_pool_
, key_
, ERR_CONNECTION_CLOSED
);
196 EXPECT_TRUE(session
);
198 base::RunLoop().RunUntilIdle();
199 EXPECT_FALSE(session
);
204 // A helper class that vends a callback that, when fired, destroys a
205 // given SpdyStreamRequest.
206 class StreamRequestDestroyingCallback
: public TestCompletionCallbackBase
{
208 StreamRequestDestroyingCallback() {}
210 virtual ~StreamRequestDestroyingCallback() {}
212 void SetRequestToDestroy(scoped_ptr
<SpdyStreamRequest
> request
) {
213 request_
= request
.Pass();
216 CompletionCallback
MakeCallback() {
217 return base::Bind(&StreamRequestDestroyingCallback::OnComplete
,
218 base::Unretained(this));
222 void OnComplete(int result
) {
227 scoped_ptr
<SpdyStreamRequest
> request_
;
232 // Request kInitialMaxConcurrentStreams streams. Request two more
233 // streams, but have the callback for one destroy the second stream
234 // request. Close the session. Nothing should blow up. This is a
235 // regression test for http://crbug.com/250841 .
236 TEST_P(SpdySessionTest
, PendingStreamCancellingAnother
) {
237 session_deps_
.host_resolver
->set_synchronous_mode(true);
239 MockRead reads
[] = {MockRead(ASYNC
, 0, 0), };
241 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
242 MockConnect
connect_data(SYNCHRONOUS
, OK
);
243 data
.set_connect_data(connect_data
);
244 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
246 CreateDeterministicNetworkSession();
248 base::WeakPtr
<SpdySession
> session
=
249 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
251 // Create the maximum number of concurrent streams.
252 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
253 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
254 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
, BoundNetLog());
255 ASSERT_TRUE(spdy_stream
!= NULL
);
258 SpdyStreamRequest request1
;
259 scoped_ptr
<SpdyStreamRequest
> request2(new SpdyStreamRequest
);
261 StreamRequestDestroyingCallback callback1
;
262 ASSERT_EQ(ERR_IO_PENDING
,
263 request1
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
,
268 callback1
.MakeCallback()));
270 // |callback2| is never called.
271 TestCompletionCallback callback2
;
272 ASSERT_EQ(ERR_IO_PENDING
,
273 request2
->StartRequest(SPDY_BIDIRECTIONAL_STREAM
,
278 callback2
.callback()));
280 callback1
.SetRequestToDestroy(request2
.Pass());
282 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
284 EXPECT_EQ(ERR_ABORTED
, callback1
.WaitForResult());
287 // A session receiving a GOAWAY frame with no active streams should close.
288 TEST_P(SpdySessionTest
, GoAwayWithNoActiveStreams
) {
289 session_deps_
.host_resolver
->set_synchronous_mode(true);
291 MockConnect
connect_data(SYNCHRONOUS
, OK
);
292 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
294 CreateMockRead(*goaway
, 0),
296 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
297 data
.set_connect_data(connect_data
);
298 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
300 CreateDeterministicNetworkSession();
302 base::WeakPtr
<SpdySession
> session
=
303 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
305 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
307 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
309 // Read and process the GOAWAY frame.
311 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
312 base::RunLoop().RunUntilIdle();
313 EXPECT_TRUE(session
== NULL
);
316 // A session receiving a GOAWAY frame immediately with no active
317 // streams should then close.
318 TEST_P(SpdySessionTest
, GoAwayImmediatelyWithNoActiveStreams
) {
319 session_deps_
.host_resolver
->set_synchronous_mode(true);
321 MockConnect
connect_data(SYNCHRONOUS
, OK
);
322 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
324 CreateMockRead(*goaway
, 0, SYNCHRONOUS
),
326 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
327 data
.set_connect_data(connect_data
);
328 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
330 CreateDeterministicNetworkSession();
334 base::WeakPtr
<SpdySession
> session
=
335 TryCreateInsecureSpdySessionExpectingFailure(
336 http_session_
, key_
, ERR_CONNECTION_CLOSED
, BoundNetLog());
337 base::RunLoop().RunUntilIdle();
339 EXPECT_FALSE(session
);
340 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
343 // A session receiving a GOAWAY frame with active streams should close
344 // when the last active stream is closed.
345 TEST_P(SpdySessionTest
, GoAwayWithActiveStreams
) {
346 session_deps_
.host_resolver
->set_synchronous_mode(true);
348 MockConnect
connect_data(SYNCHRONOUS
, OK
);
349 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
351 CreateMockRead(*goaway
, 2),
352 MockRead(ASYNC
, 0, 3) // EOF
354 scoped_ptr
<SpdyFrame
> req1(
355 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
356 scoped_ptr
<SpdyFrame
> req2(
357 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
358 MockWrite writes
[] = {
359 CreateMockWrite(*req1
, 0),
360 CreateMockWrite(*req2
, 1),
362 DeterministicSocketData
data(reads
, arraysize(reads
),
363 writes
, arraysize(writes
));
364 data
.set_connect_data(connect_data
);
365 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
367 CreateDeterministicNetworkSession();
369 base::WeakPtr
<SpdySession
> session
=
370 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
372 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
374 GURL
url(kDefaultURL
);
375 base::WeakPtr
<SpdyStream
> spdy_stream1
=
376 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
377 session
, url
, MEDIUM
, BoundNetLog());
378 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
379 spdy_stream1
->SetDelegate(&delegate1
);
381 base::WeakPtr
<SpdyStream
> spdy_stream2
=
382 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
383 session
, url
, MEDIUM
, BoundNetLog());
384 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
385 spdy_stream2
->SetDelegate(&delegate2
);
387 scoped_ptr
<SpdyHeaderBlock
> headers(
388 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
389 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
391 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
392 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
393 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
394 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
398 EXPECT_EQ(1u, spdy_stream1
->stream_id());
399 EXPECT_EQ(3u, spdy_stream2
->stream_id());
401 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
403 // Read and process the GOAWAY frame.
406 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
408 EXPECT_FALSE(session
->IsStreamActive(3));
409 EXPECT_EQ(NULL
, spdy_stream2
.get());
410 EXPECT_TRUE(session
->IsStreamActive(1));
412 EXPECT_TRUE(session
->IsGoingAway());
414 // Should close the session.
415 spdy_stream1
->Close();
416 EXPECT_EQ(NULL
, spdy_stream1
.get());
418 base::MessageLoop::current()->RunUntilIdle();
419 EXPECT_TRUE(session
== NULL
);
422 // Have a session receive two GOAWAY frames, with the last one causing
423 // the last active stream to be closed. The session should then be
424 // closed after the second GOAWAY frame.
425 TEST_P(SpdySessionTest
, GoAwayTwice
) {
426 session_deps_
.host_resolver
->set_synchronous_mode(true);
428 MockConnect
connect_data(SYNCHRONOUS
, OK
);
429 scoped_ptr
<SpdyFrame
> goaway1(spdy_util_
.ConstructSpdyGoAway(1));
430 scoped_ptr
<SpdyFrame
> goaway2(spdy_util_
.ConstructSpdyGoAway(0));
432 CreateMockRead(*goaway1
, 2),
433 CreateMockRead(*goaway2
, 3),
434 MockRead(ASYNC
, 0, 4) // EOF
436 scoped_ptr
<SpdyFrame
> req1(
437 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
438 scoped_ptr
<SpdyFrame
> req2(
439 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
440 MockWrite writes
[] = {
441 CreateMockWrite(*req1
, 0),
442 CreateMockWrite(*req2
, 1),
444 DeterministicSocketData
data(reads
, arraysize(reads
),
445 writes
, arraysize(writes
));
446 data
.set_connect_data(connect_data
);
447 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
449 CreateDeterministicNetworkSession();
451 base::WeakPtr
<SpdySession
> session
=
452 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
454 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
456 GURL
url(kDefaultURL
);
457 base::WeakPtr
<SpdyStream
> spdy_stream1
=
458 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
459 session
, url
, MEDIUM
, BoundNetLog());
460 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
461 spdy_stream1
->SetDelegate(&delegate1
);
463 base::WeakPtr
<SpdyStream
> spdy_stream2
=
464 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
465 session
, url
, MEDIUM
, BoundNetLog());
466 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
467 spdy_stream2
->SetDelegate(&delegate2
);
469 scoped_ptr
<SpdyHeaderBlock
> headers(
470 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
471 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
473 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
474 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
475 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
476 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
480 EXPECT_EQ(1u, spdy_stream1
->stream_id());
481 EXPECT_EQ(3u, spdy_stream2
->stream_id());
483 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
485 // Read and process the first GOAWAY frame.
488 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
490 EXPECT_FALSE(session
->IsStreamActive(3));
491 EXPECT_EQ(NULL
, spdy_stream2
.get());
492 EXPECT_TRUE(session
->IsStreamActive(1));
493 EXPECT_TRUE(session
->IsGoingAway());
495 // Read and process the second GOAWAY frame, which should close the
498 base::MessageLoop::current()->RunUntilIdle();
499 EXPECT_TRUE(session
== NULL
);
502 // Have a session with active streams receive a GOAWAY frame and then
503 // close it. It should handle the close properly (i.e., not try to
504 // make itself unavailable in its pool twice).
505 TEST_P(SpdySessionTest
, GoAwayWithActiveStreamsThenClose
) {
506 session_deps_
.host_resolver
->set_synchronous_mode(true);
508 MockConnect
connect_data(SYNCHRONOUS
, OK
);
509 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
511 CreateMockRead(*goaway
, 2),
512 MockRead(ASYNC
, 0, 3) // EOF
514 scoped_ptr
<SpdyFrame
> req1(
515 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
516 scoped_ptr
<SpdyFrame
> req2(
517 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
518 MockWrite writes
[] = {
519 CreateMockWrite(*req1
, 0),
520 CreateMockWrite(*req2
, 1),
522 DeterministicSocketData
data(reads
, arraysize(reads
),
523 writes
, arraysize(writes
));
524 data
.set_connect_data(connect_data
);
525 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
527 CreateDeterministicNetworkSession();
529 base::WeakPtr
<SpdySession
> session
=
530 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
532 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
534 GURL
url(kDefaultURL
);
535 base::WeakPtr
<SpdyStream
> spdy_stream1
=
536 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
537 session
, url
, MEDIUM
, BoundNetLog());
538 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
539 spdy_stream1
->SetDelegate(&delegate1
);
541 base::WeakPtr
<SpdyStream
> spdy_stream2
=
542 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
543 session
, url
, MEDIUM
, BoundNetLog());
544 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
545 spdy_stream2
->SetDelegate(&delegate2
);
547 scoped_ptr
<SpdyHeaderBlock
> headers(
548 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
549 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
551 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
552 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
553 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
554 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
558 EXPECT_EQ(1u, spdy_stream1
->stream_id());
559 EXPECT_EQ(3u, spdy_stream2
->stream_id());
561 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
563 // Read and process the GOAWAY frame.
566 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
568 EXPECT_FALSE(session
->IsStreamActive(3));
569 EXPECT_EQ(NULL
, spdy_stream2
.get());
570 EXPECT_TRUE(session
->IsStreamActive(1));
571 EXPECT_TRUE(session
->IsGoingAway());
573 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
574 EXPECT_EQ(NULL
, spdy_stream1
.get());
576 base::MessageLoop::current()->RunUntilIdle();
577 EXPECT_TRUE(session
== NULL
);
580 // Process a joint read buffer which causes the session to begin draining, and
581 // then processes a GOAWAY. The session should gracefully drain. Regression test
582 // for crbug.com/379469
583 TEST_P(SpdySessionTest
, GoAwayWhileDraining
) {
584 session_deps_
.host_resolver
->set_synchronous_mode(true);
586 scoped_ptr
<SpdyFrame
> req(
587 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
588 MockWrite writes
[] = {
589 CreateMockWrite(*req
, 0),
592 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
593 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
594 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
595 size_t joint_size
= goaway
->size() * 2 + body
->size();
597 // Compose interleaved |goaway| and |body| frames into a single read.
598 scoped_ptr
<char[]> buffer(new char[joint_size
]);
601 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
602 out
+= goaway
->size();
603 memcpy(&buffer
[out
], body
->data(), body
->size());
605 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
606 out
+= goaway
->size();
607 ASSERT_EQ(out
, joint_size
);
609 SpdyFrame
joint_frames(buffer
.get(), joint_size
, false);
612 CreateMockRead(*resp
, 1), CreateMockRead(joint_frames
, 2),
613 MockRead(ASYNC
, 0, 3) // EOF
616 MockConnect
connect_data(SYNCHRONOUS
, OK
);
617 DeterministicSocketData
data(
618 reads
, arraysize(reads
), writes
, arraysize(writes
));
619 data
.set_connect_data(connect_data
);
620 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
622 CreateDeterministicNetworkSession();
623 base::WeakPtr
<SpdySession
> session
=
624 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
626 GURL
url(kDefaultURL
);
627 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
628 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
629 test::StreamDelegateDoNothing
delegate(spdy_stream
);
630 spdy_stream
->SetDelegate(&delegate
);
632 scoped_ptr
<SpdyHeaderBlock
> headers(
633 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
634 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
635 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
638 base::MessageLoop::current()->RunUntilIdle();
640 // Stream and session closed gracefully.
641 EXPECT_TRUE(delegate
.StreamIsClosed());
642 EXPECT_EQ(OK
, delegate
.WaitForClose());
643 EXPECT_EQ(kUploadData
, delegate
.TakeReceivedData());
644 EXPECT_TRUE(session
== NULL
);
647 // Try to create a stream after receiving a GOAWAY frame. It should
649 TEST_P(SpdySessionTest
, CreateStreamAfterGoAway
) {
650 session_deps_
.host_resolver
->set_synchronous_mode(true);
652 MockConnect
connect_data(SYNCHRONOUS
, OK
);
653 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
655 CreateMockRead(*goaway
, 1),
656 MockRead(ASYNC
, 0, 2) // EOF
658 scoped_ptr
<SpdyFrame
> req(
659 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
660 MockWrite writes
[] = {
661 CreateMockWrite(*req
, 0),
663 DeterministicSocketData
data(reads
, arraysize(reads
),
664 writes
, arraysize(writes
));
665 data
.set_connect_data(connect_data
);
666 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
668 CreateDeterministicNetworkSession();
670 base::WeakPtr
<SpdySession
> session
=
671 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
673 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
675 GURL
url(kDefaultURL
);
676 base::WeakPtr
<SpdyStream
> spdy_stream
=
677 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
678 session
, url
, MEDIUM
, BoundNetLog());
679 test::StreamDelegateDoNothing
delegate(spdy_stream
);
680 spdy_stream
->SetDelegate(&delegate
);
682 scoped_ptr
<SpdyHeaderBlock
> headers(
683 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
684 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
685 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
689 EXPECT_EQ(1u, spdy_stream
->stream_id());
691 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
693 // Read and process the GOAWAY frame.
696 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
697 EXPECT_TRUE(session
->IsStreamActive(1));
699 SpdyStreamRequest stream_request
;
700 int rv
= stream_request
.StartRequest(
701 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog(),
702 CompletionCallback());
703 EXPECT_EQ(ERR_FAILED
, rv
);
705 // Read and process EOF.
708 EXPECT_TRUE(session
== NULL
);
711 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
712 // the stream being refused.
713 TEST_P(SpdySessionTest
, SynStreamAfterGoAway
) {
714 session_deps_
.host_resolver
->set_synchronous_mode(true);
716 MockConnect
connect_data(SYNCHRONOUS
, OK
);
717 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
718 scoped_ptr
<SpdyFrame
>
719 push(spdy_util_
.ConstructSpdyPush(NULL
, 0, 2, 1, kDefaultURL
));
721 CreateMockRead(*goaway
, 1),
722 CreateMockRead(*push
, 2),
723 MockRead(ASYNC
, 0, 4) // EOF
725 scoped_ptr
<SpdyFrame
> req(
726 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
727 scoped_ptr
<SpdyFrame
> rst(
728 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
729 MockWrite writes
[] = {
730 CreateMockWrite(*req
, 0),
731 CreateMockWrite(*rst
, 3)
733 DeterministicSocketData
data(reads
, arraysize(reads
),
734 writes
, arraysize(writes
));
735 data
.set_connect_data(connect_data
);
736 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
738 CreateDeterministicNetworkSession();
740 base::WeakPtr
<SpdySession
> session
=
741 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
743 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
745 GURL
url(kDefaultURL
);
746 base::WeakPtr
<SpdyStream
> spdy_stream
=
747 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
748 session
, url
, MEDIUM
, BoundNetLog());
749 test::StreamDelegateDoNothing
delegate(spdy_stream
);
750 spdy_stream
->SetDelegate(&delegate
);
752 scoped_ptr
<SpdyHeaderBlock
> headers(
753 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
754 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
755 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
759 EXPECT_EQ(1u, spdy_stream
->stream_id());
761 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
763 // Read and process the GOAWAY frame.
766 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
767 EXPECT_TRUE(session
->IsStreamActive(1));
769 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
772 base::MessageLoop::current()->RunUntilIdle();
773 EXPECT_TRUE(session
== NULL
);
776 // A session observing a network change with active streams should close
777 // when the last active stream is closed.
778 TEST_P(SpdySessionTest
, NetworkChangeWithActiveStreams
) {
779 session_deps_
.host_resolver
->set_synchronous_mode(true);
781 MockConnect
connect_data(SYNCHRONOUS
, OK
);
783 MockRead(ASYNC
, 0, 1) // EOF
785 scoped_ptr
<SpdyFrame
> req1(
786 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
787 MockWrite writes
[] = {
788 CreateMockWrite(*req1
, 0),
790 DeterministicSocketData
data(reads
, arraysize(reads
),
791 writes
, arraysize(writes
));
792 data
.set_connect_data(connect_data
);
793 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
795 CreateDeterministicNetworkSession();
797 base::WeakPtr
<SpdySession
> session
=
798 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
800 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
802 base::WeakPtr
<SpdyStream
> spdy_stream
=
803 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
, session
,
804 GURL(kDefaultURL
), MEDIUM
, BoundNetLog());
805 test::StreamDelegateDoNothing
delegate(spdy_stream
);
806 spdy_stream
->SetDelegate(&delegate
);
808 scoped_ptr
<SpdyHeaderBlock
> headers(
809 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
811 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
812 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
816 EXPECT_EQ(1u, spdy_stream
->stream_id());
818 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
820 spdy_session_pool_
->OnIPAddressChanged();
822 // The SpdySessionPool behavior differs based on how the OSs reacts to
823 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
824 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
825 // For OSs where the TCP connections will close upon relevant network
826 // changes, SpdySessionPool doesn't need to force them to close, so in these
827 // cases verify the session has become unavailable but remains open and the
828 // pre-existing stream is still active.
829 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
831 EXPECT_TRUE(session
->IsGoingAway());
833 EXPECT_TRUE(session
->IsStreamActive(1));
835 // Should close the session.
836 spdy_stream
->Close();
838 EXPECT_EQ(NULL
, spdy_stream
.get());
840 base::MessageLoop::current()->RunUntilIdle();
841 EXPECT_TRUE(session
== NULL
);
844 TEST_P(SpdySessionTest
, ClientPing
) {
845 session_deps_
.enable_ping
= true;
846 session_deps_
.host_resolver
->set_synchronous_mode(true);
848 MockConnect
connect_data(SYNCHRONOUS
, OK
);
849 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(1, true));
851 CreateMockRead(*read_ping
, 1),
852 MockRead(ASYNC
, 0, 0, 2) // EOF
854 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
855 MockWrite writes
[] = {
856 CreateMockWrite(*write_ping
, 0),
858 DeterministicSocketData
data(
859 reads
, arraysize(reads
), writes
, arraysize(writes
));
860 data
.set_connect_data(connect_data
);
861 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
863 CreateDeterministicNetworkSession();
865 base::WeakPtr
<SpdySession
> session
=
866 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
868 base::WeakPtr
<SpdyStream
> spdy_stream1
=
869 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
870 session
, test_url_
, MEDIUM
, BoundNetLog());
871 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
872 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
873 spdy_stream1
->SetDelegate(&delegate
);
875 base::TimeTicks before_ping_time
= base::TimeTicks::Now();
877 session
->set_connection_at_risk_of_loss_time(
878 base::TimeDelta::FromSeconds(-1));
879 session
->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
881 session
->SendPrefacePingIfNoneInFlight();
885 session
->CheckPingStatus(before_ping_time
);
887 EXPECT_EQ(0, session
->pings_in_flight());
888 EXPECT_GE(session
->next_ping_id(), static_cast<uint32
>(1));
889 EXPECT_FALSE(session
->check_ping_status_pending());
890 EXPECT_GE(session
->last_activity_time(), before_ping_time
);
894 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
896 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
897 EXPECT_TRUE(session
== NULL
);
900 TEST_P(SpdySessionTest
, ServerPing
) {
901 session_deps_
.host_resolver
->set_synchronous_mode(true);
903 MockConnect
connect_data(SYNCHRONOUS
, OK
);
904 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(2, false));
906 CreateMockRead(*read_ping
),
907 MockRead(SYNCHRONOUS
, 0, 0) // EOF
909 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(2, true));
910 MockWrite writes
[] = {
911 CreateMockWrite(*write_ping
),
913 StaticSocketDataProvider
data(
914 reads
, arraysize(reads
), writes
, arraysize(writes
));
915 data
.set_connect_data(connect_data
);
916 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
918 CreateNetworkSession();
920 base::WeakPtr
<SpdySession
> session
=
921 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
923 base::WeakPtr
<SpdyStream
> spdy_stream1
=
924 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
925 session
, test_url_
, MEDIUM
, BoundNetLog());
926 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
927 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
928 spdy_stream1
->SetDelegate(&delegate
);
930 // Flush the read completion task.
931 base::MessageLoop::current()->RunUntilIdle();
933 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
935 EXPECT_TRUE(session
== NULL
);
936 EXPECT_EQ(NULL
, spdy_stream1
.get());
939 // Cause a ping to be sent out while producing a write. The write loop
940 // should handle this properly, i.e. another DoWriteLoop task should
941 // not be posted. This is a regression test for
942 // http://crbug.com/261043 .
943 TEST_P(SpdySessionTest
, PingAndWriteLoop
) {
944 session_deps_
.enable_ping
= true;
945 session_deps_
.time_func
= TheNearFuture
;
947 MockConnect
connect_data(SYNCHRONOUS
, OK
);
948 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
949 scoped_ptr
<SpdyFrame
> req(
950 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
951 MockWrite writes
[] = {
952 CreateMockWrite(*req
, 0),
953 CreateMockWrite(*write_ping
, 1),
957 MockRead(ASYNC
, 0, 2) // EOF
960 session_deps_
.host_resolver
->set_synchronous_mode(true);
962 DeterministicSocketData
data(reads
, arraysize(reads
),
963 writes
, arraysize(writes
));
964 data
.set_connect_data(connect_data
);
965 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
967 CreateDeterministicNetworkSession();
969 base::WeakPtr
<SpdySession
> session
=
970 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
972 GURL
url(kDefaultURL
);
973 base::WeakPtr
<SpdyStream
> spdy_stream
=
974 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
975 session
, url
, LOWEST
, BoundNetLog());
976 test::StreamDelegateDoNothing
delegate(spdy_stream
);
977 spdy_stream
->SetDelegate(&delegate
);
979 scoped_ptr
<SpdyHeaderBlock
> headers(
980 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
981 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
983 // Shift time so that a ping will be sent out.
984 g_time_delta
= base::TimeDelta::FromSeconds(11);
988 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting");
991 TEST_P(SpdySessionTest
, StreamIdSpaceExhausted
) {
992 const SpdyStreamId kLastStreamId
= 0x7fffffff;
993 session_deps_
.host_resolver
->set_synchronous_mode(true);
995 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
996 // fixed to allow for two stream ID assignments, and three concurrent
997 // streams. Four streams are started, and two are activated. Verify the
998 // session goes away, and that the created (but not activated) and
999 // stalled streams are aborted. Also verify the activated streams complete,
1000 // at which point the session closes.
1002 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyGet(
1003 NULL
, 0, false, kLastStreamId
- 2, MEDIUM
, true));
1004 scoped_ptr
<SpdyFrame
> req2(
1005 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, kLastStreamId
, MEDIUM
, true));
1007 MockWrite writes
[] = {
1008 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
1011 scoped_ptr
<SpdyFrame
> resp1(
1012 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, kLastStreamId
- 2));
1013 scoped_ptr
<SpdyFrame
> resp2(
1014 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, kLastStreamId
));
1016 scoped_ptr
<SpdyFrame
> body1(
1017 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
- 2, true));
1018 scoped_ptr
<SpdyFrame
> body2(
1019 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
, true));
1021 MockRead reads
[] = {
1022 CreateMockRead(*resp1
, 2), CreateMockRead(*resp2
, 3),
1023 CreateMockRead(*body1
, 4), CreateMockRead(*body2
, 5),
1024 MockRead(ASYNC
, 0, 6) // EOF
1027 DeterministicSocketData
data(
1028 reads
, arraysize(reads
), writes
, arraysize(writes
));
1030 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1031 data
.set_connect_data(connect_data
);
1032 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1034 CreateDeterministicNetworkSession();
1035 base::WeakPtr
<SpdySession
> session
=
1036 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1038 // Fix stream_hi_water_mark_ to allow for two stream activations.
1039 session
->stream_hi_water_mark_
= kLastStreamId
- 2;
1040 // Fix max_concurrent_streams to allow for three stream creations.
1041 session
->max_concurrent_streams_
= 3;
1043 // Create three streams synchronously, and begin a fourth (which is stalled).
1044 GURL
url(kDefaultURL
);
1045 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
1046 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1047 test::StreamDelegateDoNothing
delegate1(stream1
);
1048 stream1
->SetDelegate(&delegate1
);
1050 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
1051 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1052 test::StreamDelegateDoNothing
delegate2(stream2
);
1053 stream2
->SetDelegate(&delegate2
);
1055 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
1056 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1057 test::StreamDelegateDoNothing
delegate3(stream3
);
1058 stream3
->SetDelegate(&delegate3
);
1060 SpdyStreamRequest request4
;
1061 TestCompletionCallback callback4
;
1062 EXPECT_EQ(ERR_IO_PENDING
,
1063 request4
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
,
1068 callback4
.callback()));
1070 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1071 EXPECT_EQ(0u, session
->num_active_streams());
1072 EXPECT_EQ(3u, session
->num_created_streams());
1073 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1075 // Activate stream 1. One ID remains available.
1076 stream1
->SendRequestHeaders(
1077 scoped_ptr
<SpdyHeaderBlock
>(
1078 spdy_util_
.ConstructGetHeaderBlock(url
.spec())),
1079 NO_MORE_DATA_TO_SEND
);
1082 EXPECT_EQ(kLastStreamId
- 2u, stream1
->stream_id());
1083 EXPECT_EQ(1u, session
->num_active_streams());
1084 EXPECT_EQ(2u, session
->num_created_streams());
1085 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1087 // Activate stream 2. ID space is exhausted.
1088 stream2
->SendRequestHeaders(
1089 scoped_ptr
<SpdyHeaderBlock
>(
1090 spdy_util_
.ConstructGetHeaderBlock(url
.spec())),
1091 NO_MORE_DATA_TO_SEND
);
1094 // Active streams remain active.
1095 EXPECT_EQ(kLastStreamId
, stream2
->stream_id());
1096 EXPECT_EQ(2u, session
->num_active_streams());
1098 // Session is going away. Created and stalled streams were aborted.
1099 EXPECT_EQ(SpdySession::STATE_GOING_AWAY
, session
->availability_state_
);
1100 EXPECT_EQ(ERR_ABORTED
, delegate3
.WaitForClose());
1101 EXPECT_EQ(ERR_ABORTED
, callback4
.WaitForResult());
1102 EXPECT_EQ(0u, session
->num_created_streams());
1103 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1105 // Read responses on remaining active streams.
1107 EXPECT_EQ(OK
, delegate1
.WaitForClose());
1108 EXPECT_EQ(kUploadData
, delegate1
.TakeReceivedData());
1109 EXPECT_EQ(OK
, delegate2
.WaitForClose());
1110 EXPECT_EQ(kUploadData
, delegate2
.TakeReceivedData());
1112 // Session was destroyed.
1113 base::MessageLoop::current()->RunUntilIdle();
1114 EXPECT_FALSE(session
.get());
1117 // Verifies that an unstalled pending stream creation racing with a new stream
1118 // creation doesn't violate the maximum stream concurrency. Regression test for
1119 // crbug.com/373858.
1120 TEST_P(SpdySessionTest
, UnstallRacesWithStreamCreation
) {
1121 session_deps_
.host_resolver
->set_synchronous_mode(true);
1123 MockRead reads
[] = {
1124 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1127 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1129 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1130 data
.set_connect_data(connect_data
);
1131 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1133 CreateNetworkSession();
1134 base::WeakPtr
<SpdySession
> session
=
1135 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1137 // Fix max_concurrent_streams to allow for one open stream.
1138 session
->max_concurrent_streams_
= 1;
1140 // Create two streams: one synchronously, and one which stalls.
1141 GURL
url(kDefaultURL
);
1142 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
1143 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1145 SpdyStreamRequest request2
;
1146 TestCompletionCallback callback2
;
1147 EXPECT_EQ(ERR_IO_PENDING
,
1148 request2
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
,
1153 callback2
.callback()));
1155 EXPECT_EQ(1u, session
->num_created_streams());
1156 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1158 // Cancel the first stream. A callback to unstall the second stream was
1159 // posted. Don't run it yet.
1162 EXPECT_EQ(0u, session
->num_created_streams());
1163 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1165 // Create a third stream prior to the second stream's callback.
1166 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
1167 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1169 EXPECT_EQ(1u, session
->num_created_streams());
1170 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1172 // NOW run the message loop. The unstalled stream will re-stall itself.
1173 base::MessageLoop::current()->RunUntilIdle();
1174 EXPECT_EQ(1u, session
->num_created_streams());
1175 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1177 // Cancel the third stream and run the message loop. Verify that the second
1178 // stream creation now completes.
1180 base::MessageLoop::current()->RunUntilIdle();
1182 EXPECT_EQ(1u, session
->num_created_streams());
1183 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1184 EXPECT_EQ(OK
, callback2
.WaitForResult());
1187 TEST_P(SpdySessionTest
, DeleteExpiredPushStreams
) {
1188 session_deps_
.host_resolver
->set_synchronous_mode(true);
1189 session_deps_
.time_func
= TheNearFuture
;
1191 scoped_ptr
<SpdyFrame
> req(
1192 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
1193 scoped_ptr
<SpdyFrame
> rst(
1194 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
1196 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
1197 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
1198 scoped_ptr
<SpdyFrame
> push_a_body(
1199 spdy_util_
.ConstructSpdyBodyFrame(2, false));
1200 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
1201 NULL
, 0, 4, 1, "http://www.google.com/b.dat"));
1202 MockWrite writes
[] = {CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 4)};
1203 MockRead reads
[] = {
1204 CreateMockRead(*push_a
, 1), CreateMockRead(*push_a_body
, 2),
1205 CreateMockRead(*push_b
, 3), MockRead(ASYNC
, 0, 5), // EOF
1207 DeterministicSocketData
data(
1208 reads
, arraysize(reads
), writes
, arraysize(writes
));
1210 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1211 data
.set_connect_data(connect_data
);
1212 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1214 CreateDeterministicNetworkSession();
1215 base::WeakPtr
<SpdySession
> session
=
1216 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1218 // Process the principal request, and the first push stream request & body.
1219 GURL
url(kDefaultURL
);
1220 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
1221 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1222 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1223 spdy_stream
->SetDelegate(&delegate
);
1225 scoped_ptr
<SpdyHeaderBlock
> headers(
1226 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1227 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1231 // Verify that there is one unclaimed push stream.
1232 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
1233 SpdySession::PushedStreamMap::iterator iter
=
1234 session
->unclaimed_pushed_streams_
.find(
1235 GURL("http://www.google.com/a.dat"));
1236 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
1238 if (session
->flow_control_state_
==
1239 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1240 // Unclaimed push body consumed bytes from the session window.
1241 EXPECT_EQ(kSpdySessionInitialWindowSize
- kUploadDataSize
,
1242 session
->session_recv_window_size_
);
1243 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
1246 // Shift time to expire the push stream. Read the second SYN_STREAM,
1247 // and verify a RST_STREAM was written.
1248 g_time_delta
= base::TimeDelta::FromSeconds(301);
1251 // Verify that the second pushed stream evicted the first pushed stream.
1252 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
1253 iter
= session
->unclaimed_pushed_streams_
.find(
1254 GURL("http://www.google.com/b.dat"));
1255 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
1257 if (session
->flow_control_state_
==
1258 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
1259 // Verify that the session window reclaimed the evicted stream body.
1260 EXPECT_EQ(kSpdySessionInitialWindowSize
,
1261 session
->session_recv_window_size_
);
1262 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
1265 // Read and process EOF.
1267 base::MessageLoop::current()->RunUntilIdle();
1268 EXPECT_TRUE(session
== NULL
);
1271 TEST_P(SpdySessionTest
, FailedPing
) {
1272 session_deps_
.host_resolver
->set_synchronous_mode(true);
1274 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1275 MockRead reads
[] = {
1276 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1278 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
1279 scoped_ptr
<SpdyFrame
> goaway(
1280 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Failed ping."));
1281 MockWrite writes
[] = {CreateMockWrite(*write_ping
), CreateMockWrite(*goaway
)};
1282 StaticSocketDataProvider
data(
1283 reads
, arraysize(reads
), writes
, arraysize(writes
));
1284 data
.set_connect_data(connect_data
);
1285 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1287 CreateNetworkSession();
1289 base::WeakPtr
<SpdySession
> session
=
1290 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1292 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1293 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1294 session
, test_url_
, MEDIUM
, BoundNetLog());
1295 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1296 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
1297 spdy_stream1
->SetDelegate(&delegate
);
1299 session
->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1300 session
->set_hung_interval(base::TimeDelta::FromSeconds(0));
1302 // Send a PING frame.
1303 session
->WritePingFrame(1, false);
1304 EXPECT_LT(0, session
->pings_in_flight());
1305 EXPECT_GE(session
->next_ping_id(), static_cast<uint32
>(1));
1306 EXPECT_TRUE(session
->check_ping_status_pending());
1308 // Assert session is not closed.
1309 EXPECT_TRUE(session
->IsAvailable());
1310 EXPECT_LT(0u, session
->num_active_streams() + session
->num_created_streams());
1311 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1313 // We set last time we have received any data in 1 sec less than now.
1314 // CheckPingStatus will trigger timeout because hung interval is zero.
1315 base::TimeTicks now
= base::TimeTicks::Now();
1316 session
->last_activity_time_
= now
- base::TimeDelta::FromSeconds(1);
1317 session
->CheckPingStatus(now
);
1318 base::MessageLoop::current()->RunUntilIdle();
1320 EXPECT_TRUE(session
== NULL
);
1321 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1322 EXPECT_EQ(NULL
, spdy_stream1
.get());
1325 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1326 // settings frame increasing the max concurrent streams by 1. Make
1327 // sure nothing blows up. This is a regression test for
1328 // http://crbug.com/57331 .
1329 TEST_P(SpdySessionTest
, OnSettings
) {
1330 session_deps_
.host_resolver
->set_synchronous_mode(true);
1332 const SpdySettingsIds kSpdySettingsIds
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1334 SettingsMap new_settings
;
1335 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1336 new_settings
[kSpdySettingsIds
] =
1337 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1338 scoped_ptr
<SpdyFrame
> settings_frame(
1339 spdy_util_
.ConstructSpdySettings(new_settings
));
1340 MockRead reads
[] = {
1341 CreateMockRead(*settings_frame
, 0),
1342 MockRead(ASYNC
, 0, 1),
1345 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
1346 MockWrite writes
[] = {
1347 CreateMockWrite(*settings_ack
, 2),
1350 DeterministicSocketData
data(reads
, arraysize(reads
),
1351 writes
, arraysize(writes
));
1352 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1353 data
.set_connect_data(connect_data
);
1354 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1356 CreateDeterministicNetworkSession();
1358 base::WeakPtr
<SpdySession
> session
=
1359 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1361 // Create the maximum number of concurrent streams.
1362 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1363 base::WeakPtr
<SpdyStream
> spdy_stream
=
1364 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1365 session
, test_url_
, MEDIUM
, BoundNetLog());
1366 ASSERT_TRUE(spdy_stream
!= NULL
);
1369 StreamReleaserCallback stream_releaser
;
1370 SpdyStreamRequest request
;
1371 ASSERT_EQ(ERR_IO_PENDING
,
1372 request
.StartRequest(
1373 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1375 stream_releaser
.MakeCallback(&request
)));
1379 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1382 if (spdy_util_
.spdy_version() >= SPDY4
) {
1383 // Allow the SETTINGS+ACK to write, so the session finishes draining.
1386 base::MessageLoop::current()->RunUntilIdle();
1387 EXPECT_TRUE(session
== NULL
);
1390 // Start with a persisted value for max concurrent streams. Receive a
1391 // settings frame increasing the max concurrent streams by 1 and which
1392 // also clears the persisted data. Verify that persisted data is
1394 TEST_P(SpdySessionTest
, ClearSettings
) {
1395 if (spdy_util_
.spdy_version() >= SPDY4
) {
1396 // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1397 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4.
1400 session_deps_
.host_resolver
->set_synchronous_mode(true);
1402 SettingsMap new_settings
;
1403 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1404 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1405 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1406 scoped_ptr
<SpdyFrame
> settings_frame(
1407 spdy_util_
.ConstructSpdySettings(new_settings
));
1408 uint8 flags
= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
1409 test::SetFrameFlags(settings_frame
.get(), flags
, spdy_util_
.spdy_version());
1410 MockRead reads
[] = {
1411 CreateMockRead(*settings_frame
, 0),
1412 MockRead(ASYNC
, 0, 1),
1415 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
1416 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1417 data
.set_connect_data(connect_data
);
1418 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1420 CreateDeterministicNetworkSession();
1422 // Initialize the SpdySetting with the default.
1423 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1424 test_host_port_pair_
,
1425 SETTINGS_MAX_CONCURRENT_STREAMS
,
1426 SETTINGS_FLAG_PLEASE_PERSIST
,
1427 kInitialMaxConcurrentStreams
);
1430 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1431 test_host_port_pair_
).empty());
1433 base::WeakPtr
<SpdySession
> session
=
1434 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1436 // Create the maximum number of concurrent streams.
1437 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1438 base::WeakPtr
<SpdyStream
> spdy_stream
=
1439 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1440 session
, test_url_
, MEDIUM
, BoundNetLog());
1441 ASSERT_TRUE(spdy_stream
!= NULL
);
1444 StreamReleaserCallback stream_releaser
;
1446 SpdyStreamRequest request
;
1447 ASSERT_EQ(ERR_IO_PENDING
,
1448 request
.StartRequest(
1449 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1451 stream_releaser
.MakeCallback(&request
)));
1455 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1457 // Make sure that persisted data is cleared.
1459 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1460 test_host_port_pair_
).empty());
1462 // Make sure session's max_concurrent_streams is correct.
1463 EXPECT_EQ(kInitialMaxConcurrentStreams
+ 1,
1464 session
->max_concurrent_streams());
1467 EXPECT_TRUE(session
== NULL
);
1470 // Start with max concurrent streams set to 1. Request two streams.
1471 // When the first completes, have the callback close its stream, which
1472 // should trigger the second stream creation. Then cancel that one
1473 // immediately. Don't crash. This is a regression test for
1474 // http://crbug.com/63532 .
1475 TEST_P(SpdySessionTest
, CancelPendingCreateStream
) {
1476 session_deps_
.host_resolver
->set_synchronous_mode(true);
1478 MockRead reads
[] = {
1479 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1482 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1483 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1485 data
.set_connect_data(connect_data
);
1486 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1488 CreateNetworkSession();
1490 // Initialize the SpdySetting with 1 max concurrent streams.
1491 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1492 test_host_port_pair_
,
1493 SETTINGS_MAX_CONCURRENT_STREAMS
,
1494 SETTINGS_FLAG_PLEASE_PERSIST
,
1497 base::WeakPtr
<SpdySession
> session
=
1498 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1500 // Leave room for only one more stream to be created.
1501 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
1502 base::WeakPtr
<SpdyStream
> spdy_stream
=
1503 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1504 session
, test_url_
, MEDIUM
, BoundNetLog());
1505 ASSERT_TRUE(spdy_stream
!= NULL
);
1508 // Create 2 more streams. First will succeed. Second will be pending.
1509 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1510 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1511 session
, test_url_
, MEDIUM
, BoundNetLog());
1512 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1514 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1515 // a valgrind error if the callback is invoked when it's not supposed to be.
1516 scoped_ptr
<TestCompletionCallback
> callback(new TestCompletionCallback
);
1518 SpdyStreamRequest request
;
1519 ASSERT_EQ(ERR_IO_PENDING
,
1520 request
.StartRequest(
1521 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1523 callback
->callback()));
1525 // Release the first one, this will allow the second to be created.
1526 spdy_stream1
->Cancel();
1527 EXPECT_EQ(NULL
, spdy_stream1
.get());
1529 request
.CancelRequest();
1532 // Should not crash when running the pending callback.
1533 base::MessageLoop::current()->RunUntilIdle();
1536 TEST_P(SpdySessionTest
, SendInitialDataOnNewSession
) {
1537 session_deps_
.host_resolver
->set_synchronous_mode(true);
1539 MockRead reads
[] = {
1540 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1543 SettingsMap settings
;
1544 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1545 const SpdySettingsIds kSpdySettingsIds2
= SETTINGS_INITIAL_WINDOW_SIZE
;
1546 const uint32 kInitialRecvWindowSize
= 10 * 1024 * 1024;
1547 settings
[kSpdySettingsIds1
] =
1548 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
1549 if (spdy_util_
.spdy_version() >= SPDY3
) {
1550 settings
[kSpdySettingsIds2
] =
1551 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kInitialRecvWindowSize
);
1553 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1554 scoped_ptr
<SpdyFrame
> settings_frame(
1555 spdy_util_
.ConstructSpdySettings(settings
));
1556 scoped_ptr
<SpdyFrame
> initial_window_update(
1557 spdy_util_
.ConstructSpdyWindowUpdate(
1558 kSessionFlowControlStreamId
,
1559 kDefaultInitialRecvWindowSize
- kSpdySessionInitialWindowSize
));
1560 std::vector
<MockWrite
> writes
;
1561 if (GetParam() == kProtoSPDY4
) {
1564 kHttp2ConnectionHeaderPrefix
,
1565 kHttp2ConnectionHeaderPrefixSize
));
1567 writes
.push_back(CreateMockWrite(*settings_frame
));
1568 if (GetParam() >= kProtoSPDY31
) {
1569 writes
.push_back(CreateMockWrite(*initial_window_update
));
1572 SettingsMap server_settings
;
1573 const uint32 initial_max_concurrent_streams
= 1;
1574 server_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1575 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED
,
1576 initial_max_concurrent_streams
);
1577 scoped_ptr
<SpdyFrame
> server_settings_frame(
1578 spdy_util_
.ConstructSpdySettings(server_settings
));
1579 writes
.push_back(CreateMockWrite(*server_settings_frame
));
1581 session_deps_
.stream_initial_recv_window_size
= kInitialRecvWindowSize
;
1583 StaticSocketDataProvider
data(reads
, arraysize(reads
),
1584 vector_as_array(&writes
), writes
.size());
1585 data
.set_connect_data(connect_data
);
1586 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1588 CreateNetworkSession();
1590 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1591 test_host_port_pair_
,
1592 SETTINGS_MAX_CONCURRENT_STREAMS
,
1593 SETTINGS_FLAG_PLEASE_PERSIST
,
1594 initial_max_concurrent_streams
);
1596 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
1597 pool_peer
.SetEnableSendingInitialData(true);
1599 base::WeakPtr
<SpdySession
> session
=
1600 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1602 base::MessageLoop::current()->RunUntilIdle();
1603 EXPECT_TRUE(data
.at_write_eof());
1606 TEST_P(SpdySessionTest
, ClearSettingsStorageOnIPAddressChanged
) {
1607 CreateNetworkSession();
1609 base::WeakPtr
<HttpServerProperties
> test_http_server_properties
=
1610 spdy_session_pool_
->http_server_properties();
1611 SettingsFlagsAndValue
flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST
, 2);
1612 test_http_server_properties
->SetSpdySetting(
1613 test_host_port_pair_
,
1614 SETTINGS_MAX_CONCURRENT_STREAMS
,
1615 SETTINGS_FLAG_PLEASE_PERSIST
,
1617 EXPECT_NE(0u, test_http_server_properties
->GetSpdySettings(
1618 test_host_port_pair_
).size());
1619 spdy_session_pool_
->OnIPAddressChanged();
1620 EXPECT_EQ(0u, test_http_server_properties
->GetSpdySettings(
1621 test_host_port_pair_
).size());
1624 TEST_P(SpdySessionTest
, Initialize
) {
1625 CapturingBoundNetLog log
;
1626 session_deps_
.net_log
= log
.bound().net_log();
1627 session_deps_
.host_resolver
->set_synchronous_mode(true);
1629 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1630 MockRead reads
[] = {
1631 MockRead(ASYNC
, 0, 0) // EOF
1634 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1635 data
.set_connect_data(connect_data
);
1636 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1638 CreateNetworkSession();
1640 base::WeakPtr
<SpdySession
> session
=
1641 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1642 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1644 // Flush the read completion task.
1645 base::MessageLoop::current()->RunUntilIdle();
1647 net::CapturingNetLog::CapturedEntryList entries
;
1648 log
.GetEntries(&entries
);
1649 EXPECT_LT(0u, entries
.size());
1651 // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly.
1652 int pos
= net::ExpectLogContainsSomewhere(
1654 net::NetLog::TYPE_SPDY_SESSION_INITIALIZED
,
1655 net::NetLog::PHASE_NONE
);
1658 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1659 NetLog::Source socket_source
;
1660 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry
.params
.get(),
1662 EXPECT_TRUE(socket_source
.IsValid());
1663 EXPECT_NE(log
.bound().source().id
, socket_source
.id
);
1666 TEST_P(SpdySessionTest
, NetLogOnSessionGoaway
) {
1667 session_deps_
.host_resolver
->set_synchronous_mode(true);
1669 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1670 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
1671 MockRead reads
[] = {
1672 CreateMockRead(*goaway
),
1673 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1676 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1677 data
.set_connect_data(connect_data
);
1678 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1680 CreateNetworkSession();
1682 CapturingBoundNetLog log
;
1683 base::WeakPtr
<SpdySession
> session
=
1684 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1685 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1687 // Flush the read completion task.
1688 base::MessageLoop::current()->RunUntilIdle();
1690 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1691 EXPECT_TRUE(session
== NULL
);
1693 // Check that the NetLog was filled reasonably.
1694 net::CapturingNetLog::CapturedEntryList entries
;
1695 log
.GetEntries(&entries
);
1696 EXPECT_LT(0u, entries
.size());
1698 // Check that we logged SPDY_SESSION_CLOSE correctly.
1699 int pos
= net::ExpectLogContainsSomewhere(
1701 net::NetLog::TYPE_SPDY_SESSION_CLOSE
,
1702 net::NetLog::PHASE_NONE
);
1704 if (pos
< static_cast<int>(entries
.size())) {
1705 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1707 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1708 EXPECT_EQ(OK
, error_code
);
1714 TEST_P(SpdySessionTest
, NetLogOnSessionEOF
) {
1715 session_deps_
.host_resolver
->set_synchronous_mode(true);
1717 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1718 MockRead reads
[] = {
1719 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1722 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1723 data
.set_connect_data(connect_data
);
1724 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1726 CreateNetworkSession();
1728 CapturingBoundNetLog log
;
1729 base::WeakPtr
<SpdySession
> session
=
1730 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1731 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1733 // Flush the read completion task.
1734 base::MessageLoop::current()->RunUntilIdle();
1736 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1737 EXPECT_TRUE(session
== NULL
);
1739 // Check that the NetLog was filled reasonably.
1740 net::CapturingNetLog::CapturedEntryList entries
;
1741 log
.GetEntries(&entries
);
1742 EXPECT_LT(0u, entries
.size());
1744 // Check that we logged SPDY_SESSION_CLOSE correctly.
1746 net::ExpectLogContainsSomewhere(entries
,
1748 net::NetLog::TYPE_SPDY_SESSION_CLOSE
,
1749 net::NetLog::PHASE_NONE
);
1751 if (pos
< static_cast<int>(entries
.size())) {
1752 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1754 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1755 EXPECT_EQ(ERR_CONNECTION_CLOSED
, error_code
);
1761 TEST_P(SpdySessionTest
, SynCompressionHistograms
) {
1762 session_deps_
.enable_compression
= true;
1764 scoped_ptr
<SpdyFrame
> req(
1765 spdy_util_
.ConstructSpdyGet(NULL
, 0, true, 1, MEDIUM
, true));
1766 MockWrite writes
[] = {
1767 CreateMockWrite(*req
, 0),
1769 MockRead reads
[] = {
1770 MockRead(ASYNC
, 0, 1) // EOF
1772 DeterministicSocketData
data(reads
, arraysize(reads
),
1773 writes
, arraysize(writes
));
1774 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1775 data
.set_connect_data(connect_data
);
1776 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1778 CreateDeterministicNetworkSession();
1779 base::WeakPtr
<SpdySession
> session
=
1780 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1782 GURL
url(kDefaultURL
);
1783 base::WeakPtr
<SpdyStream
> spdy_stream
=
1784 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1785 session
, url
, MEDIUM
, BoundNetLog());
1786 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1787 spdy_stream
->SetDelegate(&delegate
);
1789 scoped_ptr
<SpdyHeaderBlock
> headers(
1790 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1791 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1792 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
1794 // Write request headers & capture resulting histogram update.
1795 base::HistogramTester histogram_tester
;
1798 // Regression test of compression performance under the request fixture.
1799 switch (spdy_util_
.spdy_version()) {
1801 histogram_tester
.ExpectBucketCount(
1802 "Net.SpdySynStreamCompressionPercentage", 0, 1);
1805 histogram_tester
.ExpectBucketCount(
1806 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1809 histogram_tester
.ExpectBucketCount(
1810 "Net.SpdySynStreamCompressionPercentage", 82, 1);
1813 histogram_tester
.ExpectBucketCount(
1814 "Net.SpdySynStreamCompressionPercentage", 82, 1);
1820 // Read and process EOF.
1822 base::MessageLoop::current()->RunUntilIdle();
1823 EXPECT_TRUE(session
== NULL
);
1826 // Queue up a low-priority SYN_STREAM followed by a high-priority
1827 // one. The high priority one should still send first and receive
1829 TEST_P(SpdySessionTest
, OutOfOrderSynStreams
) {
1830 // Construct the request.
1831 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1832 scoped_ptr
<SpdyFrame
> req_highest(
1833 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, HIGHEST
, true));
1834 scoped_ptr
<SpdyFrame
> req_lowest(
1835 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1836 MockWrite writes
[] = {
1837 CreateMockWrite(*req_highest
, 0),
1838 CreateMockWrite(*req_lowest
, 1),
1841 scoped_ptr
<SpdyFrame
> resp_highest(
1842 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1843 scoped_ptr
<SpdyFrame
> body_highest(
1844 spdy_util_
.ConstructSpdyBodyFrame(1, true));
1845 scoped_ptr
<SpdyFrame
> resp_lowest(
1846 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1847 scoped_ptr
<SpdyFrame
> body_lowest(
1848 spdy_util_
.ConstructSpdyBodyFrame(3, true));
1849 MockRead reads
[] = {
1850 CreateMockRead(*resp_highest
, 2),
1851 CreateMockRead(*body_highest
, 3),
1852 CreateMockRead(*resp_lowest
, 4),
1853 CreateMockRead(*body_lowest
, 5),
1854 MockRead(ASYNC
, 0, 6) // EOF
1857 session_deps_
.host_resolver
->set_synchronous_mode(true);
1859 DeterministicSocketData
data(reads
, arraysize(reads
),
1860 writes
, arraysize(writes
));
1861 data
.set_connect_data(connect_data
);
1862 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1864 CreateDeterministicNetworkSession();
1866 base::WeakPtr
<SpdySession
> session
=
1867 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1869 GURL
url(kDefaultURL
);
1871 base::WeakPtr
<SpdyStream
> spdy_stream_lowest
=
1872 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1873 session
, url
, LOWEST
, BoundNetLog());
1874 ASSERT_TRUE(spdy_stream_lowest
);
1875 EXPECT_EQ(0u, spdy_stream_lowest
->stream_id());
1876 test::StreamDelegateDoNothing
delegate_lowest(spdy_stream_lowest
);
1877 spdy_stream_lowest
->SetDelegate(&delegate_lowest
);
1879 base::WeakPtr
<SpdyStream
> spdy_stream_highest
=
1880 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1881 session
, url
, HIGHEST
, BoundNetLog());
1882 ASSERT_TRUE(spdy_stream_highest
);
1883 EXPECT_EQ(0u, spdy_stream_highest
->stream_id());
1884 test::StreamDelegateDoNothing
delegate_highest(spdy_stream_highest
);
1885 spdy_stream_highest
->SetDelegate(&delegate_highest
);
1887 // Queue the lower priority one first.
1889 scoped_ptr
<SpdyHeaderBlock
> headers_lowest(
1890 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1891 spdy_stream_lowest
->SendRequestHeaders(
1892 headers_lowest
.Pass(), NO_MORE_DATA_TO_SEND
);
1893 EXPECT_TRUE(spdy_stream_lowest
->HasUrlFromHeaders());
1895 scoped_ptr
<SpdyHeaderBlock
> headers_highest(
1896 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1897 spdy_stream_highest
->SendRequestHeaders(
1898 headers_highest
.Pass(), NO_MORE_DATA_TO_SEND
);
1899 EXPECT_TRUE(spdy_stream_highest
->HasUrlFromHeaders());
1903 EXPECT_FALSE(spdy_stream_lowest
);
1904 EXPECT_FALSE(spdy_stream_highest
);
1905 EXPECT_EQ(3u, delegate_lowest
.stream_id());
1906 EXPECT_EQ(1u, delegate_highest
.stream_id());
1909 TEST_P(SpdySessionTest
, CancelStream
) {
1910 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1911 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1912 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1913 scoped_ptr
<SpdyFrame
> req2(
1914 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1915 MockWrite writes
[] = {
1916 CreateMockWrite(*req2
, 0),
1919 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1920 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1921 MockRead reads
[] = {
1922 CreateMockRead(*resp2
, 1),
1923 CreateMockRead(*body2
, 2),
1924 MockRead(ASYNC
, 0, 3) // EOF
1927 session_deps_
.host_resolver
->set_synchronous_mode(true);
1929 DeterministicSocketData
data(reads
, arraysize(reads
),
1930 writes
, arraysize(writes
));
1931 data
.set_connect_data(connect_data
);
1932 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1934 CreateDeterministicNetworkSession();
1936 base::WeakPtr
<SpdySession
> session
=
1937 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1939 GURL
url1(kDefaultURL
);
1940 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1941 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1942 session
, url1
, HIGHEST
, BoundNetLog());
1943 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1944 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1945 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
1946 spdy_stream1
->SetDelegate(&delegate1
);
1948 GURL
url2(kDefaultURL
);
1949 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1950 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1951 session
, url2
, LOWEST
, BoundNetLog());
1952 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1953 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1954 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
1955 spdy_stream2
->SetDelegate(&delegate2
);
1957 scoped_ptr
<SpdyHeaderBlock
> headers(
1958 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1959 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1960 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1962 scoped_ptr
<SpdyHeaderBlock
> headers2(
1963 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1964 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1965 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1967 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1969 spdy_stream1
->Cancel();
1970 EXPECT_EQ(NULL
, spdy_stream1
.get());
1972 EXPECT_EQ(0u, delegate1
.stream_id());
1976 EXPECT_EQ(0u, delegate1
.stream_id());
1977 EXPECT_EQ(1u, delegate2
.stream_id());
1979 spdy_stream2
->Cancel();
1980 EXPECT_EQ(NULL
, spdy_stream2
.get());
1983 // Create two streams that are set to re-close themselves on close,
1984 // and then close the session. Nothing should blow up. Also a
1985 // regression test for http://crbug.com/139518 .
1986 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedSelfClosingStreams
) {
1987 session_deps_
.host_resolver
->set_synchronous_mode(true);
1989 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1991 // No actual data will be sent.
1992 MockWrite writes
[] = {
1993 MockWrite(ASYNC
, 0, 1) // EOF
1996 MockRead reads
[] = {
1997 MockRead(ASYNC
, 0, 0) // EOF
1999 DeterministicSocketData
data(reads
, arraysize(reads
),
2000 writes
, arraysize(writes
));
2001 data
.set_connect_data(connect_data
);
2002 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2004 CreateDeterministicNetworkSession();
2006 base::WeakPtr
<SpdySession
> session
=
2007 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2009 GURL
url1(kDefaultURL
);
2010 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2011 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2012 session
, url1
, HIGHEST
, BoundNetLog());
2013 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2014 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2016 GURL
url2(kDefaultURL
);
2017 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2018 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2019 session
, url2
, LOWEST
, BoundNetLog());
2020 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2021 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2023 test::ClosingDelegate
delegate1(spdy_stream1
);
2024 spdy_stream1
->SetDelegate(&delegate1
);
2026 test::ClosingDelegate
delegate2(spdy_stream2
);
2027 spdy_stream2
->SetDelegate(&delegate2
);
2029 scoped_ptr
<SpdyHeaderBlock
> headers(
2030 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2031 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2032 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2034 scoped_ptr
<SpdyHeaderBlock
> headers2(
2035 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2036 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2037 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2039 // Ensure that the streams have not yet been activated and assigned an id.
2040 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2041 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2043 // Ensure we don't crash while closing the session.
2044 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2046 EXPECT_EQ(NULL
, spdy_stream1
.get());
2047 EXPECT_EQ(NULL
, spdy_stream2
.get());
2049 EXPECT_TRUE(delegate1
.StreamIsClosed());
2050 EXPECT_TRUE(delegate2
.StreamIsClosed());
2052 base::MessageLoop::current()->RunUntilIdle();
2053 EXPECT_TRUE(session
== NULL
);
2056 // Create two streams that are set to close each other on close, and
2057 // then close the session. Nothing should blow up.
2058 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedMutuallyClosingStreams
) {
2059 session_deps_
.host_resolver
->set_synchronous_mode(true);
2061 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2063 // No actual data will be sent.
2064 MockWrite writes
[] = {
2065 MockWrite(ASYNC
, 0, 1) // EOF
2068 MockRead reads
[] = {
2069 MockRead(ASYNC
, 0, 0) // EOF
2071 DeterministicSocketData
data(reads
, arraysize(reads
),
2072 writes
, arraysize(writes
));
2073 data
.set_connect_data(connect_data
);
2074 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2076 CreateDeterministicNetworkSession();
2078 base::WeakPtr
<SpdySession
> session
=
2079 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2081 GURL
url1(kDefaultURL
);
2082 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2083 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2084 session
, url1
, HIGHEST
, BoundNetLog());
2085 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2086 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2088 GURL
url2(kDefaultURL
);
2089 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2090 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2091 session
, url2
, LOWEST
, BoundNetLog());
2092 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2093 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2095 // Make |spdy_stream1| close |spdy_stream2|.
2096 test::ClosingDelegate
delegate1(spdy_stream2
);
2097 spdy_stream1
->SetDelegate(&delegate1
);
2099 // Make |spdy_stream2| close |spdy_stream1|.
2100 test::ClosingDelegate
delegate2(spdy_stream1
);
2101 spdy_stream2
->SetDelegate(&delegate2
);
2103 scoped_ptr
<SpdyHeaderBlock
> headers(
2104 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2105 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2106 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2108 scoped_ptr
<SpdyHeaderBlock
> headers2(
2109 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2110 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2111 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2113 // Ensure that the streams have not yet been activated and assigned an id.
2114 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2115 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2117 // Ensure we don't crash while closing the session.
2118 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2120 EXPECT_EQ(NULL
, spdy_stream1
.get());
2121 EXPECT_EQ(NULL
, spdy_stream2
.get());
2123 EXPECT_TRUE(delegate1
.StreamIsClosed());
2124 EXPECT_TRUE(delegate2
.StreamIsClosed());
2126 base::MessageLoop::current()->RunUntilIdle();
2127 EXPECT_TRUE(session
== NULL
);
2130 // Create two streams that are set to re-close themselves on close,
2131 // activate them, and then close the session. Nothing should blow up.
2132 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedSelfClosingStreams
) {
2133 session_deps_
.host_resolver
->set_synchronous_mode(true);
2135 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2137 scoped_ptr
<SpdyFrame
> req1(
2138 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2139 scoped_ptr
<SpdyFrame
> req2(
2140 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
2141 MockWrite writes
[] = {
2142 CreateMockWrite(*req1
, 0),
2143 CreateMockWrite(*req2
, 1),
2146 MockRead reads
[] = {
2147 MockRead(ASYNC
, 0, 2) // EOF
2150 DeterministicSocketData
data(reads
, arraysize(reads
),
2151 writes
, arraysize(writes
));
2152 data
.set_connect_data(connect_data
);
2153 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2155 CreateDeterministicNetworkSession();
2157 base::WeakPtr
<SpdySession
> session
=
2158 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2160 GURL
url1(kDefaultURL
);
2161 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2162 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2163 session
, url1
, MEDIUM
, BoundNetLog());
2164 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2165 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2167 GURL
url2(kDefaultURL
);
2168 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2169 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2170 session
, url2
, MEDIUM
, BoundNetLog());
2171 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2172 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2174 test::ClosingDelegate
delegate1(spdy_stream1
);
2175 spdy_stream1
->SetDelegate(&delegate1
);
2177 test::ClosingDelegate
delegate2(spdy_stream2
);
2178 spdy_stream2
->SetDelegate(&delegate2
);
2180 scoped_ptr
<SpdyHeaderBlock
> headers(
2181 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2182 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2183 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2185 scoped_ptr
<SpdyHeaderBlock
> headers2(
2186 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2187 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2188 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2190 // Ensure that the streams have not yet been activated and assigned an id.
2191 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2192 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2196 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2197 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2199 // Ensure we don't crash while closing the session.
2200 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2202 EXPECT_EQ(NULL
, spdy_stream1
.get());
2203 EXPECT_EQ(NULL
, spdy_stream2
.get());
2205 EXPECT_TRUE(delegate1
.StreamIsClosed());
2206 EXPECT_TRUE(delegate2
.StreamIsClosed());
2208 base::MessageLoop::current()->RunUntilIdle();
2209 EXPECT_TRUE(session
== NULL
);
2212 // Create two streams that are set to close each other on close,
2213 // activate them, and then close the session. Nothing should blow up.
2214 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedMutuallyClosingStreams
) {
2215 session_deps_
.host_resolver
->set_synchronous_mode(true);
2217 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2219 scoped_ptr
<SpdyFrame
> req1(
2220 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2221 scoped_ptr
<SpdyFrame
> req2(
2222 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
2223 MockWrite writes
[] = {
2224 CreateMockWrite(*req1
, 0),
2225 CreateMockWrite(*req2
, 1),
2228 MockRead reads
[] = {
2229 MockRead(ASYNC
, 0, 2) // EOF
2232 DeterministicSocketData
data(reads
, arraysize(reads
),
2233 writes
, arraysize(writes
));
2234 data
.set_connect_data(connect_data
);
2235 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2237 CreateDeterministicNetworkSession();
2239 base::WeakPtr
<SpdySession
> session
=
2240 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2242 GURL
url1(kDefaultURL
);
2243 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2244 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2245 session
, url1
, MEDIUM
, BoundNetLog());
2246 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2247 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2249 GURL
url2(kDefaultURL
);
2250 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2251 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2252 session
, url2
, MEDIUM
, BoundNetLog());
2253 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2254 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2256 // Make |spdy_stream1| close |spdy_stream2|.
2257 test::ClosingDelegate
delegate1(spdy_stream2
);
2258 spdy_stream1
->SetDelegate(&delegate1
);
2260 // Make |spdy_stream2| close |spdy_stream1|.
2261 test::ClosingDelegate
delegate2(spdy_stream1
);
2262 spdy_stream2
->SetDelegate(&delegate2
);
2264 scoped_ptr
<SpdyHeaderBlock
> headers(
2265 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2266 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2267 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2269 scoped_ptr
<SpdyHeaderBlock
> headers2(
2270 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2271 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2272 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2274 // Ensure that the streams have not yet been activated and assigned an id.
2275 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2276 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2280 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2281 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2283 // Ensure we don't crash while closing the session.
2284 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2286 EXPECT_EQ(NULL
, spdy_stream1
.get());
2287 EXPECT_EQ(NULL
, spdy_stream2
.get());
2289 EXPECT_TRUE(delegate1
.StreamIsClosed());
2290 EXPECT_TRUE(delegate2
.StreamIsClosed());
2292 base::MessageLoop::current()->RunUntilIdle();
2293 EXPECT_TRUE(session
== NULL
);
2296 // Delegate that closes a given session when the stream is closed.
2297 class SessionClosingDelegate
: public test::StreamDelegateDoNothing
{
2299 SessionClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
2300 const base::WeakPtr
<SpdySession
>& session_to_close
)
2301 : StreamDelegateDoNothing(stream
),
2302 session_to_close_(session_to_close
) {}
2304 virtual ~SessionClosingDelegate() {}
2306 virtual void OnClose(int status
) OVERRIDE
{
2307 session_to_close_
->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR
, "Error");
2311 base::WeakPtr
<SpdySession
> session_to_close_
;
2314 // Close an activated stream that closes its session. Nothing should
2315 // blow up. This is a regression test for http://crbug.com/263691 .
2316 TEST_P(SpdySessionTest
, CloseActivatedStreamThatClosesSession
) {
2317 session_deps_
.host_resolver
->set_synchronous_mode(true);
2319 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2321 scoped_ptr
<SpdyFrame
> req(
2322 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2323 scoped_ptr
<SpdyFrame
> rst(
2324 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2325 scoped_ptr
<SpdyFrame
> goaway(
2326 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Error"));
2327 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2328 // despite being queued second.
2329 MockWrite writes
[] = {
2330 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 1),
2331 CreateMockWrite(*rst
, 2),
2334 MockRead reads
[] = {
2335 MockRead(ASYNC
, 0, 3) // EOF
2337 DeterministicSocketData
data(reads
, arraysize(reads
),
2338 writes
, arraysize(writes
));
2339 data
.set_connect_data(connect_data
);
2340 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2342 CreateDeterministicNetworkSession();
2344 base::WeakPtr
<SpdySession
> session
=
2345 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2347 GURL
url(kDefaultURL
);
2348 base::WeakPtr
<SpdyStream
> spdy_stream
=
2349 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2350 session
, url
, MEDIUM
, BoundNetLog());
2351 ASSERT_TRUE(spdy_stream
.get() != NULL
);
2352 EXPECT_EQ(0u, spdy_stream
->stream_id());
2354 SessionClosingDelegate
delegate(spdy_stream
, session
);
2355 spdy_stream
->SetDelegate(&delegate
);
2357 scoped_ptr
<SpdyHeaderBlock
> headers(
2358 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
2359 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2360 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
2362 EXPECT_EQ(0u, spdy_stream
->stream_id());
2366 EXPECT_EQ(1u, spdy_stream
->stream_id());
2368 // Ensure we don't crash while closing the stream (which closes the
2370 spdy_stream
->Cancel();
2372 EXPECT_EQ(NULL
, spdy_stream
.get());
2373 EXPECT_TRUE(delegate
.StreamIsClosed());
2375 data
.RunFor(2); // Write the RST_STREAM & GOAWAY.
2376 base::MessageLoop::current()->RunUntilIdle();
2377 EXPECT_TRUE(session
== NULL
);
2380 TEST_P(SpdySessionTest
, VerifyDomainAuthentication
) {
2381 session_deps_
.host_resolver
->set_synchronous_mode(true);
2383 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2385 // No actual data will be sent.
2386 MockWrite writes
[] = {
2387 MockWrite(ASYNC
, 0, 1) // EOF
2390 MockRead reads
[] = {
2391 MockRead(ASYNC
, 0, 0) // EOF
2393 DeterministicSocketData
data(reads
, arraysize(reads
),
2394 writes
, arraysize(writes
));
2395 data
.set_connect_data(connect_data
);
2396 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2398 // Load a cert that is valid for:
2402 base::FilePath certs_dir
= GetTestCertsDirectory();
2403 scoped_refptr
<X509Certificate
> test_cert(
2404 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2405 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
.get());
2407 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2408 ssl
.cert
= test_cert
;
2409 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2411 CreateDeterministicNetworkSession();
2413 base::WeakPtr
<SpdySession
> session
=
2414 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2416 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2417 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2418 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.com"));
2419 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2422 TEST_P(SpdySessionTest
, ConnectionPooledWithTlsChannelId
) {
2423 session_deps_
.host_resolver
->set_synchronous_mode(true);
2425 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2427 // No actual data will be sent.
2428 MockWrite writes
[] = {
2429 MockWrite(ASYNC
, 0, 1) // EOF
2432 MockRead reads
[] = {
2433 MockRead(ASYNC
, 0, 0) // EOF
2435 DeterministicSocketData
data(reads
, arraysize(reads
),
2436 writes
, arraysize(writes
));
2437 data
.set_connect_data(connect_data
);
2438 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2440 // Load a cert that is valid for:
2444 base::FilePath certs_dir
= GetTestCertsDirectory();
2445 scoped_refptr
<X509Certificate
> test_cert(
2446 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2447 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
.get());
2449 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2450 ssl
.channel_id_sent
= true;
2451 ssl
.cert
= test_cert
;
2452 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2454 CreateDeterministicNetworkSession();
2456 base::WeakPtr
<SpdySession
> session
=
2457 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2459 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2460 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2461 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.example.com"));
2462 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2465 TEST_P(SpdySessionTest
, CloseTwoStalledCreateStream
) {
2466 // TODO(rtenneti): Define a helper class/methods and move the common code in
2468 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2470 SettingsMap new_settings
;
2471 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
2472 const uint32 max_concurrent_streams
= 1;
2473 new_settings
[kSpdySettingsIds1
] =
2474 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
2476 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
2477 scoped_ptr
<SpdyFrame
> req1(
2478 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2479 scoped_ptr
<SpdyFrame
> req2(
2480 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
2481 scoped_ptr
<SpdyFrame
> req3(
2482 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
2483 MockWrite writes
[] = {
2484 CreateMockWrite(*settings_ack
, 1),
2485 CreateMockWrite(*req1
, 2),
2486 CreateMockWrite(*req2
, 5),
2487 CreateMockWrite(*req3
, 8),
2490 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2492 scoped_ptr
<SpdyFrame
> settings_frame(
2493 spdy_util_
.ConstructSpdySettings(new_settings
));
2495 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2496 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2498 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
2499 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
2501 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
2502 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
2504 MockRead reads
[] = {
2505 CreateMockRead(*settings_frame
),
2506 CreateMockRead(*resp1
, 3),
2507 CreateMockRead(*body1
, 4),
2508 CreateMockRead(*resp2
, 6),
2509 CreateMockRead(*body2
, 7),
2510 CreateMockRead(*resp3
, 9),
2511 CreateMockRead(*body3
, 10),
2512 MockRead(ASYNC
, 0, 11) // EOF
2515 DeterministicSocketData
data(reads
, arraysize(reads
),
2516 writes
, arraysize(writes
));
2517 data
.set_connect_data(connect_data
);
2518 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2520 CreateDeterministicNetworkSession();
2522 base::WeakPtr
<SpdySession
> session
=
2523 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2525 // Read the settings frame.
2528 GURL
url1(kDefaultURL
);
2529 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2530 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2531 session
, url1
, LOWEST
, BoundNetLog());
2532 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2533 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2534 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2535 spdy_stream1
->SetDelegate(&delegate1
);
2537 TestCompletionCallback callback2
;
2538 GURL
url2(kDefaultURL
);
2539 SpdyStreamRequest request2
;
2540 ASSERT_EQ(ERR_IO_PENDING
,
2541 request2
.StartRequest(
2542 SPDY_REQUEST_RESPONSE_STREAM
,
2543 session
, url2
, LOWEST
, BoundNetLog(), callback2
.callback()));
2545 TestCompletionCallback callback3
;
2546 GURL
url3(kDefaultURL
);
2547 SpdyStreamRequest request3
;
2548 ASSERT_EQ(ERR_IO_PENDING
,
2549 request3
.StartRequest(
2550 SPDY_REQUEST_RESPONSE_STREAM
,
2551 session
, url3
, LOWEST
, BoundNetLog(), callback3
.callback()));
2553 EXPECT_EQ(0u, session
->num_active_streams());
2554 EXPECT_EQ(1u, session
->num_created_streams());
2555 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2557 scoped_ptr
<SpdyHeaderBlock
> headers(
2558 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2559 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2560 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2562 // Run until 1st stream is activated and then closed.
2563 EXPECT_EQ(0u, delegate1
.stream_id());
2565 EXPECT_EQ(NULL
, spdy_stream1
.get());
2566 EXPECT_EQ(1u, delegate1
.stream_id());
2568 EXPECT_EQ(0u, session
->num_active_streams());
2569 EXPECT_EQ(0u, session
->num_created_streams());
2570 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2572 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2573 // create the 2nd stream.
2574 base::MessageLoop::current()->RunUntilIdle();
2576 EXPECT_EQ(0u, session
->num_active_streams());
2577 EXPECT_EQ(1u, session
->num_created_streams());
2578 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2580 base::WeakPtr
<SpdyStream
> stream2
= request2
.ReleaseStream();
2581 test::StreamDelegateDoNothing
delegate2(stream2
);
2582 stream2
->SetDelegate(&delegate2
);
2583 scoped_ptr
<SpdyHeaderBlock
> headers2(
2584 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2585 stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2586 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
2588 // Run until 2nd stream is activated and then closed.
2589 EXPECT_EQ(0u, delegate2
.stream_id());
2591 EXPECT_EQ(NULL
, stream2
.get());
2592 EXPECT_EQ(3u, delegate2
.stream_id());
2594 EXPECT_EQ(0u, session
->num_active_streams());
2595 EXPECT_EQ(0u, session
->num_created_streams());
2596 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2598 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2599 // create the 3rd stream.
2600 base::MessageLoop::current()->RunUntilIdle();
2602 EXPECT_EQ(0u, session
->num_active_streams());
2603 EXPECT_EQ(1u, session
->num_created_streams());
2604 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2606 base::WeakPtr
<SpdyStream
> stream3
= request3
.ReleaseStream();
2607 test::StreamDelegateDoNothing
delegate3(stream3
);
2608 stream3
->SetDelegate(&delegate3
);
2609 scoped_ptr
<SpdyHeaderBlock
> headers3(
2610 spdy_util_
.ConstructGetHeaderBlock(url3
.spec()));
2611 stream3
->SendRequestHeaders(headers3
.Pass(), NO_MORE_DATA_TO_SEND
);
2612 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
2614 // Run until 2nd stream is activated and then closed.
2615 EXPECT_EQ(0u, delegate3
.stream_id());
2617 EXPECT_EQ(NULL
, stream3
.get());
2618 EXPECT_EQ(5u, delegate3
.stream_id());
2620 EXPECT_EQ(0u, session
->num_active_streams());
2621 EXPECT_EQ(0u, session
->num_created_streams());
2622 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2627 TEST_P(SpdySessionTest
, CancelTwoStalledCreateStream
) {
2628 session_deps_
.host_resolver
->set_synchronous_mode(true);
2630 MockRead reads
[] = {
2631 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2634 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
2635 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2637 data
.set_connect_data(connect_data
);
2638 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2640 CreateNetworkSession();
2642 base::WeakPtr
<SpdySession
> session
=
2643 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2645 // Leave room for only one more stream to be created.
2646 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
2647 base::WeakPtr
<SpdyStream
> spdy_stream
=
2648 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2649 session
, test_url_
, MEDIUM
, BoundNetLog());
2650 ASSERT_TRUE(spdy_stream
!= NULL
);
2653 GURL
url1(kDefaultURL
);
2654 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2655 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2656 session
, url1
, LOWEST
, BoundNetLog());
2657 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2658 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2660 TestCompletionCallback callback2
;
2661 GURL
url2(kDefaultURL
);
2662 SpdyStreamRequest request2
;
2663 ASSERT_EQ(ERR_IO_PENDING
,
2664 request2
.StartRequest(
2665 SPDY_BIDIRECTIONAL_STREAM
, session
, url2
, LOWEST
, BoundNetLog(),
2666 callback2
.callback()));
2668 TestCompletionCallback callback3
;
2669 GURL
url3(kDefaultURL
);
2670 SpdyStreamRequest request3
;
2671 ASSERT_EQ(ERR_IO_PENDING
,
2672 request3
.StartRequest(
2673 SPDY_BIDIRECTIONAL_STREAM
, session
, url3
, LOWEST
, BoundNetLog(),
2674 callback3
.callback()));
2676 EXPECT_EQ(0u, session
->num_active_streams());
2677 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2678 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2680 // Cancel the first stream; this will allow the second stream to be created.
2681 EXPECT_TRUE(spdy_stream1
.get() != NULL
);
2682 spdy_stream1
->Cancel();
2683 EXPECT_EQ(NULL
, spdy_stream1
.get());
2685 EXPECT_EQ(OK
, callback2
.WaitForResult());
2686 EXPECT_EQ(0u, session
->num_active_streams());
2687 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2688 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2690 // Cancel the second stream; this will allow the third stream to be created.
2691 base::WeakPtr
<SpdyStream
> spdy_stream2
= request2
.ReleaseStream();
2692 spdy_stream2
->Cancel();
2693 EXPECT_EQ(NULL
, spdy_stream2
.get());
2695 EXPECT_EQ(OK
, callback3
.WaitForResult());
2696 EXPECT_EQ(0u, session
->num_active_streams());
2697 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2698 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2700 // Cancel the third stream.
2701 base::WeakPtr
<SpdyStream
> spdy_stream3
= request3
.ReleaseStream();
2702 spdy_stream3
->Cancel();
2703 EXPECT_EQ(NULL
, spdy_stream3
.get());
2704 EXPECT_EQ(0u, session
->num_active_streams());
2705 EXPECT_EQ(kInitialMaxConcurrentStreams
- 1, session
->num_created_streams());
2706 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2709 // Test that SpdySession::DoReadLoop reads data from the socket
2710 // without yielding. This test makes 32k - 1 bytes of data available
2711 // on the socket for reading. It then verifies that it has read all
2712 // the available data without yielding.
2713 TEST_P(SpdySessionTest
, ReadDataWithoutYielding
) {
2714 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2715 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2717 scoped_ptr
<SpdyFrame
> req1(
2718 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2719 MockWrite writes
[] = {
2720 CreateMockWrite(*req1
, 0),
2723 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2724 // (-spdy_data_frame_size).
2725 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2726 const int kPayloadSize
=
2727 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2728 TestDataStream test_stream
;
2729 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
2730 char* payload_data
= payload
->data();
2731 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2733 scoped_ptr
<SpdyFrame
> partial_data_frame(
2734 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2735 scoped_ptr
<SpdyFrame
> finish_data_frame(
2736 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
- 1, DATA_FLAG_FIN
));
2738 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2740 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2742 MockRead reads
[] = {
2743 CreateMockRead(*resp1
, 1),
2744 CreateMockRead(*partial_data_frame
, 2),
2745 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2746 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2747 CreateMockRead(*finish_data_frame
, 5, SYNCHRONOUS
),
2748 MockRead(ASYNC
, 0, 6) // EOF
2751 // Create SpdySession and SpdyStream and send the request.
2752 DeterministicSocketData
data(reads
, arraysize(reads
),
2753 writes
, arraysize(writes
));
2754 data
.set_connect_data(connect_data
);
2755 session_deps_
.host_resolver
->set_synchronous_mode(true);
2756 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2758 CreateDeterministicNetworkSession();
2760 base::WeakPtr
<SpdySession
> session
=
2761 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2763 GURL
url1(kDefaultURL
);
2764 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2765 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2766 session
, url1
, MEDIUM
, BoundNetLog());
2767 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2768 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2769 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2770 spdy_stream1
->SetDelegate(&delegate1
);
2772 scoped_ptr
<SpdyHeaderBlock
> headers1(
2773 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2774 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2775 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2777 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2779 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2781 // Run until 1st read.
2782 EXPECT_EQ(0u, delegate1
.stream_id());
2784 EXPECT_EQ(1u, delegate1
.stream_id());
2785 EXPECT_EQ(0u, observer
.executed_count());
2787 // Read all the data and verify SpdySession::DoReadLoop has not
2790 EXPECT_EQ(NULL
, spdy_stream1
.get());
2792 // Verify task observer's executed_count is zero, which indicates DoRead read
2793 // all the available data.
2794 EXPECT_EQ(0u, observer
.executed_count());
2795 EXPECT_TRUE(data
.at_write_eof());
2796 EXPECT_TRUE(data
.at_read_eof());
2799 // Test that SpdySession::DoReadLoop yields while reading the
2800 // data. This test makes 32k + 1 bytes of data available on the socket
2801 // for reading. It then verifies that DoRead has yielded even though
2802 // there is data available for it to read (i.e, socket()->Read didn't
2803 // return ERR_IO_PENDING during socket reads).
2804 TEST_P(SpdySessionTest
, TestYieldingDuringReadData
) {
2805 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2806 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2808 scoped_ptr
<SpdyFrame
> req1(
2809 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2810 MockWrite writes
[] = {
2811 CreateMockWrite(*req1
, 0),
2814 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2815 // (-spdy_data_frame_size).
2816 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2817 const int kPayloadSize
=
2818 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2819 TestDataStream test_stream
;
2820 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
2821 char* payload_data
= payload
->data();
2822 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2824 scoped_ptr
<SpdyFrame
> partial_data_frame(
2825 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2826 scoped_ptr
<SpdyFrame
> finish_data_frame(
2827 framer
.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN
));
2829 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2831 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2832 MockRead reads
[] = {
2833 CreateMockRead(*resp1
, 1),
2834 CreateMockRead(*partial_data_frame
, 2),
2835 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2836 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2837 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2838 CreateMockRead(*finish_data_frame
, 6, SYNCHRONOUS
),
2839 MockRead(ASYNC
, 0, 7) // EOF
2842 // Create SpdySession and SpdyStream and send the request.
2843 DeterministicSocketData
data(reads
, arraysize(reads
),
2844 writes
, arraysize(writes
));
2845 data
.set_connect_data(connect_data
);
2846 session_deps_
.host_resolver
->set_synchronous_mode(true);
2847 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2849 CreateDeterministicNetworkSession();
2851 base::WeakPtr
<SpdySession
> session
=
2852 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2854 GURL
url1(kDefaultURL
);
2855 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2856 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2857 session
, url1
, MEDIUM
, BoundNetLog());
2858 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2859 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2860 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2861 spdy_stream1
->SetDelegate(&delegate1
);
2863 scoped_ptr
<SpdyHeaderBlock
> headers1(
2864 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2865 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2866 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2868 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2870 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2872 // Run until 1st read.
2873 EXPECT_EQ(0u, delegate1
.stream_id());
2875 EXPECT_EQ(1u, delegate1
.stream_id());
2876 EXPECT_EQ(0u, observer
.executed_count());
2878 // Read all the data and verify SpdySession::DoReadLoop has posted a
2881 EXPECT_EQ(NULL
, spdy_stream1
.get());
2883 // Verify task observer's executed_count is 1, which indicates DoRead has
2884 // posted only one task and thus yielded though there is data available for it
2886 EXPECT_EQ(1u, observer
.executed_count());
2887 EXPECT_TRUE(data
.at_write_eof());
2888 EXPECT_TRUE(data
.at_read_eof());
2891 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2892 // + async, by doing the following MockReads.
2894 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2895 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2897 // The above reads 26K synchronously. Since that is less that 32K, we
2898 // will attempt to read again. However, that DoRead() will return
2899 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2900 // yield. When we come back, DoRead() will read the results from the
2901 // async read, and rest of the data synchronously.
2902 TEST_P(SpdySessionTest
, TestYieldingDuringAsyncReadData
) {
2903 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2904 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2906 scoped_ptr
<SpdyFrame
> req1(
2907 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2908 MockWrite writes
[] = {
2909 CreateMockWrite(*req1
, 0),
2912 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2913 // (-spdy_data_frame_size).
2914 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2915 TestDataStream test_stream
;
2916 const int kEightKPayloadSize
=
2917 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2918 scoped_refptr
<net::IOBuffer
> eightk_payload(
2919 new net::IOBuffer(kEightKPayloadSize
));
2920 char* eightk_payload_data
= eightk_payload
->data();
2921 test_stream
.GetBytes(eightk_payload_data
, kEightKPayloadSize
);
2923 // Build buffer of 2k size.
2924 TestDataStream test_stream2
;
2925 const int kTwoKPayloadSize
= kEightKPayloadSize
- 6 * 1024;
2926 scoped_refptr
<net::IOBuffer
> twok_payload(
2927 new net::IOBuffer(kTwoKPayloadSize
));
2928 char* twok_payload_data
= twok_payload
->data();
2929 test_stream2
.GetBytes(twok_payload_data
, kTwoKPayloadSize
);
2931 scoped_ptr
<SpdyFrame
> eightk_data_frame(framer
.CreateDataFrame(
2932 1, eightk_payload_data
, kEightKPayloadSize
, DATA_FLAG_NONE
));
2933 scoped_ptr
<SpdyFrame
> twok_data_frame(framer
.CreateDataFrame(
2934 1, twok_payload_data
, kTwoKPayloadSize
, DATA_FLAG_NONE
));
2935 scoped_ptr
<SpdyFrame
> finish_data_frame(framer
.CreateDataFrame(
2936 1, "h", 1, DATA_FLAG_FIN
));
2938 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2940 MockRead reads
[] = {
2941 CreateMockRead(*resp1
, 1),
2942 CreateMockRead(*eightk_data_frame
, 2),
2943 CreateMockRead(*eightk_data_frame
, 3, SYNCHRONOUS
),
2944 CreateMockRead(*eightk_data_frame
, 4, SYNCHRONOUS
),
2945 CreateMockRead(*twok_data_frame
, 5, SYNCHRONOUS
),
2946 CreateMockRead(*eightk_data_frame
, 6, ASYNC
),
2947 CreateMockRead(*eightk_data_frame
, 7, SYNCHRONOUS
),
2948 CreateMockRead(*eightk_data_frame
, 8, SYNCHRONOUS
),
2949 CreateMockRead(*eightk_data_frame
, 9, SYNCHRONOUS
),
2950 CreateMockRead(*twok_data_frame
, 10, SYNCHRONOUS
),
2951 CreateMockRead(*finish_data_frame
, 11, SYNCHRONOUS
),
2952 MockRead(ASYNC
, 0, 12) // EOF
2955 // Create SpdySession and SpdyStream and send the request.
2956 DeterministicSocketData
data(reads
, arraysize(reads
),
2957 writes
, arraysize(writes
));
2958 data
.set_connect_data(connect_data
);
2959 session_deps_
.host_resolver
->set_synchronous_mode(true);
2960 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2962 CreateDeterministicNetworkSession();
2964 base::WeakPtr
<SpdySession
> session
=
2965 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2967 GURL
url1(kDefaultURL
);
2968 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2969 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2970 session
, url1
, MEDIUM
, BoundNetLog());
2971 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2972 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2973 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2974 spdy_stream1
->SetDelegate(&delegate1
);
2976 scoped_ptr
<SpdyHeaderBlock
> headers1(
2977 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2978 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2979 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2981 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2982 // posting of tasks.
2983 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2985 // Run until 1st read.
2986 EXPECT_EQ(0u, delegate1
.stream_id());
2988 EXPECT_EQ(1u, delegate1
.stream_id());
2989 EXPECT_EQ(0u, observer
.executed_count());
2991 // Read all the data and verify SpdySession::DoReadLoop has posted a
2994 EXPECT_EQ(NULL
, spdy_stream1
.get());
2996 // Verify task observer's executed_count is 1, which indicates DoRead has
2997 // posted only one task and thus yielded though there is data available for
2999 EXPECT_EQ(1u, observer
.executed_count());
3000 EXPECT_TRUE(data
.at_write_eof());
3001 EXPECT_TRUE(data
.at_read_eof());
3004 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
3005 // nothing blows up.
3006 TEST_P(SpdySessionTest
, GoAwayWhileInDoReadLoop
) {
3007 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3008 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3010 scoped_ptr
<SpdyFrame
> req1(
3011 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
3012 MockWrite writes
[] = {
3013 CreateMockWrite(*req1
, 0),
3016 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3017 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3018 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
3020 MockRead reads
[] = {
3021 CreateMockRead(*resp1
, 1),
3022 CreateMockRead(*body1
, 2),
3023 CreateMockRead(*goaway
, 3),
3026 // Create SpdySession and SpdyStream and send the request.
3027 DeterministicSocketData
data(reads
, arraysize(reads
),
3028 writes
, arraysize(writes
));
3029 data
.set_connect_data(connect_data
);
3030 session_deps_
.host_resolver
->set_synchronous_mode(true);
3031 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3033 CreateDeterministicNetworkSession();
3035 base::WeakPtr
<SpdySession
> session
=
3036 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3038 GURL
url1(kDefaultURL
);
3039 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3040 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3041 session
, url1
, MEDIUM
, BoundNetLog());
3042 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3043 spdy_stream1
->SetDelegate(&delegate1
);
3044 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
3045 EXPECT_EQ(0u, spdy_stream1
->stream_id());
3047 scoped_ptr
<SpdyHeaderBlock
> headers1(
3048 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
3049 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
3050 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3052 // Run until 1st read.
3053 EXPECT_EQ(0u, spdy_stream1
->stream_id());
3055 EXPECT_EQ(1u, spdy_stream1
->stream_id());
3057 // Run until GoAway.
3059 EXPECT_EQ(NULL
, spdy_stream1
.get());
3060 EXPECT_TRUE(data
.at_write_eof());
3061 EXPECT_TRUE(data
.at_read_eof());
3062 EXPECT_TRUE(session
== NULL
);
3065 // Within this framework, a SpdySession should be initialized with
3066 // flow control disabled for protocol version 2, with flow control
3067 // enabled only for streams for protocol version 3, and with flow
3068 // control enabled for streams and sessions for higher versions.
3069 TEST_P(SpdySessionTest
, ProtocolNegotiation
) {
3070 session_deps_
.host_resolver
->set_synchronous_mode(true);
3072 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3073 MockRead reads
[] = {
3074 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3076 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3077 data
.set_connect_data(connect_data
);
3078 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3080 CreateNetworkSession();
3081 base::WeakPtr
<SpdySession
> session
=
3082 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3084 EXPECT_EQ(spdy_util_
.spdy_version(),
3085 session
->buffered_spdy_framer_
->protocol_version());
3086 if (GetParam() == kProtoDeprecatedSPDY2
) {
3087 EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE
, session
->flow_control_state());
3088 EXPECT_EQ(0, session
->session_send_window_size_
);
3089 EXPECT_EQ(0, session
->session_recv_window_size_
);
3090 } else if (GetParam() == kProtoSPDY3
) {
3091 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM
, session
->flow_control_state());
3092 EXPECT_EQ(0, session
->session_send_window_size_
);
3093 EXPECT_EQ(0, session
->session_recv_window_size_
);
3095 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3096 session
->flow_control_state());
3097 EXPECT_EQ(kSpdySessionInitialWindowSize
,
3098 session
->session_send_window_size_
);
3099 EXPECT_EQ(kSpdySessionInitialWindowSize
,
3100 session
->session_recv_window_size_
);
3102 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3105 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3106 // pointers to the idle session are currently held.
3107 TEST_P(SpdySessionTest
, CloseOneIdleConnection
) {
3108 ClientSocketPoolManager::set_max_sockets_per_group(
3109 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3110 ClientSocketPoolManager::set_max_sockets_per_pool(
3111 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3113 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3114 MockRead reads
[] = {
3115 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3117 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3118 data
.set_connect_data(connect_data
);
3119 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3120 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3122 CreateNetworkSession();
3124 TransportClientSocketPool
* pool
=
3125 http_session_
->GetTransportSocketPool(
3126 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3128 // Create an idle SPDY session.
3129 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3130 PRIVACY_MODE_DISABLED
);
3131 base::WeakPtr
<SpdySession
> session1
=
3132 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3133 EXPECT_FALSE(pool
->IsStalled());
3135 // Trying to create a new connection should cause the pool to be stalled, and
3136 // post a task asynchronously to try and close the session.
3137 TestCompletionCallback callback2
;
3138 HostPortPair
host_port2("2.com", 80);
3139 scoped_refptr
<TransportSocketParams
> params2(
3140 new TransportSocketParams(host_port2
, false, false,
3141 OnHostResolutionCallback()));
3142 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3143 EXPECT_EQ(ERR_IO_PENDING
,
3144 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3145 callback2
.callback(), pool
, BoundNetLog()));
3146 EXPECT_TRUE(pool
->IsStalled());
3148 // The socket pool should close the connection asynchronously and establish a
3150 EXPECT_EQ(OK
, callback2
.WaitForResult());
3151 EXPECT_FALSE(pool
->IsStalled());
3152 EXPECT_TRUE(session1
== NULL
);
3155 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3156 // pointers to the idle session are currently held, in the case the SPDY session
3158 TEST_P(SpdySessionTest
, CloseOneIdleConnectionWithAlias
) {
3159 ClientSocketPoolManager::set_max_sockets_per_group(
3160 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3161 ClientSocketPoolManager::set_max_sockets_per_pool(
3162 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3164 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3165 MockRead reads
[] = {
3166 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3168 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3169 data
.set_connect_data(connect_data
);
3170 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3171 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3173 session_deps_
.host_resolver
->set_synchronous_mode(true);
3174 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3175 "1.com", "192.168.0.2", std::string());
3176 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3177 "2.com", "192.168.0.2", std::string());
3178 // Not strictly needed.
3179 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3180 "3.com", "192.168.0.3", std::string());
3182 CreateNetworkSession();
3184 TransportClientSocketPool
* pool
=
3185 http_session_
->GetTransportSocketPool(
3186 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3188 // Create an idle SPDY session.
3189 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3190 PRIVACY_MODE_DISABLED
);
3191 base::WeakPtr
<SpdySession
> session1
=
3192 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3193 EXPECT_FALSE(pool
->IsStalled());
3195 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3196 SpdySessionKey
key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3197 PRIVACY_MODE_DISABLED
);
3198 HostResolver::RequestInfo
info(key2
.host_port_pair());
3199 AddressList addresses
;
3200 // Pre-populate the DNS cache, since a synchronous resolution is required in
3201 // order to create the alias.
3202 session_deps_
.host_resolver
->Resolve(info
,
3205 CompletionCallback(),
3208 // Get a session for |key2|, which should return the session created earlier.
3209 base::WeakPtr
<SpdySession
> session2
=
3210 spdy_session_pool_
->FindAvailableSession(key2
, BoundNetLog());
3211 ASSERT_EQ(session1
.get(), session2
.get());
3212 EXPECT_FALSE(pool
->IsStalled());
3214 // Trying to create a new connection should cause the pool to be stalled, and
3215 // post a task asynchronously to try and close the session.
3216 TestCompletionCallback callback3
;
3217 HostPortPair
host_port3("3.com", 80);
3218 scoped_refptr
<TransportSocketParams
> params3(
3219 new TransportSocketParams(host_port3
, false, false,
3220 OnHostResolutionCallback()));
3221 scoped_ptr
<ClientSocketHandle
> connection3(new ClientSocketHandle
);
3222 EXPECT_EQ(ERR_IO_PENDING
,
3223 connection3
->Init(host_port3
.ToString(), params3
, DEFAULT_PRIORITY
,
3224 callback3
.callback(), pool
, BoundNetLog()));
3225 EXPECT_TRUE(pool
->IsStalled());
3227 // The socket pool should close the connection asynchronously and establish a
3229 EXPECT_EQ(OK
, callback3
.WaitForResult());
3230 EXPECT_FALSE(pool
->IsStalled());
3231 EXPECT_TRUE(session1
== NULL
);
3232 EXPECT_TRUE(session2
== NULL
);
3235 // Tests that when a SPDY session becomes idle, it closes itself if there is
3236 // a lower layer pool stalled on the per-pool socket limit.
3237 TEST_P(SpdySessionTest
, CloseSessionOnIdleWhenPoolStalled
) {
3238 ClientSocketPoolManager::set_max_sockets_per_group(
3239 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3240 ClientSocketPoolManager::set_max_sockets_per_pool(
3241 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3243 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3244 MockRead reads
[] = {
3245 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3247 scoped_ptr
<SpdyFrame
> req1(
3248 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3249 scoped_ptr
<SpdyFrame
> cancel1(
3250 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3251 MockWrite writes
[] = {
3252 CreateMockWrite(*req1
, 1),
3253 CreateMockWrite(*cancel1
, 1),
3255 StaticSocketDataProvider
data(reads
, arraysize(reads
),
3256 writes
, arraysize(writes
));
3257 data
.set_connect_data(connect_data
);
3258 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3260 MockRead http_reads
[] = {
3261 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3263 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
3265 http_data
.set_connect_data(connect_data
);
3266 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
3269 CreateNetworkSession();
3271 TransportClientSocketPool
* pool
=
3272 http_session_
->GetTransportSocketPool(
3273 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3275 // Create a SPDY session.
3276 GURL
url1(kDefaultURL
);
3277 SpdySessionKey
key1(HostPortPair(url1
.host(), 80),
3278 ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3279 base::WeakPtr
<SpdySession
> session1
=
3280 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3281 EXPECT_FALSE(pool
->IsStalled());
3283 // Create a stream using the session, and send a request.
3285 TestCompletionCallback callback1
;
3286 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3287 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3288 session1
, url1
, DEFAULT_PRIORITY
,
3290 ASSERT_TRUE(spdy_stream1
.get());
3291 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3292 spdy_stream1
->SetDelegate(&delegate1
);
3294 scoped_ptr
<SpdyHeaderBlock
> headers1(
3295 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
3296 EXPECT_EQ(ERR_IO_PENDING
,
3297 spdy_stream1
->SendRequestHeaders(
3298 headers1
.Pass(), NO_MORE_DATA_TO_SEND
));
3299 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3301 base::MessageLoop::current()->RunUntilIdle();
3303 // Trying to create a new connection should cause the pool to be stalled, and
3304 // post a task asynchronously to try and close the session.
3305 TestCompletionCallback callback2
;
3306 HostPortPair
host_port2("2.com", 80);
3307 scoped_refptr
<TransportSocketParams
> params2(
3308 new TransportSocketParams(host_port2
, false, false,
3309 OnHostResolutionCallback()));
3310 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3311 EXPECT_EQ(ERR_IO_PENDING
,
3312 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3313 callback2
.callback(), pool
, BoundNetLog()));
3314 EXPECT_TRUE(pool
->IsStalled());
3316 // Running the message loop should cause the socket pool to ask the SPDY
3317 // session to close an idle socket, but since the socket is in use, nothing
3319 base::RunLoop().RunUntilIdle();
3320 EXPECT_TRUE(pool
->IsStalled());
3321 EXPECT_FALSE(callback2
.have_result());
3323 // Cancelling the request should result in the session's socket being
3324 // closed, since the pool is stalled.
3325 ASSERT_TRUE(spdy_stream1
.get());
3326 spdy_stream1
->Cancel();
3327 base::RunLoop().RunUntilIdle();
3328 ASSERT_FALSE(pool
->IsStalled());
3329 EXPECT_EQ(OK
, callback2
.WaitForResult());
3332 // Verify that SpdySessionKey and therefore SpdySession is different when
3333 // privacy mode is enabled or disabled.
3334 TEST_P(SpdySessionTest
, SpdySessionKeyPrivacyMode
) {
3335 CreateDeterministicNetworkSession();
3337 HostPortPair
host_port_pair("www.google.com", 443);
3338 SpdySessionKey
key_privacy_enabled(host_port_pair
, ProxyServer::Direct(),
3339 PRIVACY_MODE_ENABLED
);
3340 SpdySessionKey
key_privacy_disabled(host_port_pair
, ProxyServer::Direct(),
3341 PRIVACY_MODE_DISABLED
);
3343 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3344 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3346 // Add SpdySession with PrivacyMode Enabled to the pool.
3347 base::WeakPtr
<SpdySession
> session_privacy_enabled
=
3348 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_enabled
);
3350 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3351 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3353 // Add SpdySession with PrivacyMode Disabled to the pool.
3354 base::WeakPtr
<SpdySession
> session_privacy_disabled
=
3355 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_disabled
);
3357 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3358 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3360 session_privacy_enabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3361 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3362 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3364 session_privacy_disabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3365 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3366 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3369 // Delegate that creates another stream when its stream is closed.
3370 class StreamCreatingDelegate
: public test::StreamDelegateDoNothing
{
3372 StreamCreatingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3373 const base::WeakPtr
<SpdySession
>& session
)
3374 : StreamDelegateDoNothing(stream
),
3375 session_(session
) {}
3377 virtual ~StreamCreatingDelegate() {}
3379 virtual void OnClose(int status
) OVERRIDE
{
3380 GURL
url(kDefaultURL
);
3382 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3383 session_
, url
, MEDIUM
, BoundNetLog()));
3387 const base::WeakPtr
<SpdySession
> session_
;
3390 // Create another stream in response to a stream being reset. Nothing
3391 // should blow up. This is a regression test for
3392 // http://crbug.com/263690 .
3393 TEST_P(SpdySessionTest
, CreateStreamOnStreamReset
) {
3394 session_deps_
.host_resolver
->set_synchronous_mode(true);
3396 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3398 scoped_ptr
<SpdyFrame
> req(
3399 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
3400 MockWrite writes
[] = {
3401 CreateMockWrite(*req
, 0),
3404 scoped_ptr
<SpdyFrame
> rst(
3405 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
3406 MockRead reads
[] = {
3407 CreateMockRead(*rst
, 1),
3408 MockRead(ASYNC
, 0, 2) // EOF
3410 DeterministicSocketData
data(reads
, arraysize(reads
),
3411 writes
, arraysize(writes
));
3412 data
.set_connect_data(connect_data
);
3413 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3415 CreateDeterministicNetworkSession();
3417 base::WeakPtr
<SpdySession
> session
=
3418 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3420 GURL
url(kDefaultURL
);
3421 base::WeakPtr
<SpdyStream
> spdy_stream
=
3422 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3423 session
, url
, MEDIUM
, BoundNetLog());
3424 ASSERT_TRUE(spdy_stream
.get() != NULL
);
3425 EXPECT_EQ(0u, spdy_stream
->stream_id());
3427 StreamCreatingDelegate
delegate(spdy_stream
, session
);
3428 spdy_stream
->SetDelegate(&delegate
);
3430 scoped_ptr
<SpdyHeaderBlock
> headers(
3431 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
3432 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
3433 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
3435 EXPECT_EQ(0u, spdy_stream
->stream_id());
3439 EXPECT_EQ(1u, spdy_stream
->stream_id());
3441 // Cause the stream to be reset, which should cause another stream
3445 EXPECT_EQ(NULL
, spdy_stream
.get());
3446 EXPECT_TRUE(delegate
.StreamIsClosed());
3447 EXPECT_EQ(0u, session
->num_active_streams());
3448 EXPECT_EQ(1u, session
->num_created_streams());
3451 // The tests below are only for SPDY/3 and above.
3453 TEST_P(SpdySessionTest
, UpdateStreamsSendWindowSize
) {
3454 if (GetParam() < kProtoSPDY3
)
3457 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3459 SettingsMap new_settings
;
3460 int32 window_size
= 1;
3461 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
3462 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, window_size
);
3464 // Set up the socket so we read a SETTINGS frame that sets
3465 // INITIAL_WINDOW_SIZE.
3466 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3467 scoped_ptr
<SpdyFrame
> settings_frame(
3468 spdy_util_
.ConstructSpdySettings(new_settings
));
3469 MockRead reads
[] = {
3470 CreateMockRead(*settings_frame
, 0),
3471 MockRead(ASYNC
, 0, 1) // EOF
3474 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
3475 MockWrite writes
[] = {
3476 CreateMockWrite(*settings_ack
, 2),
3479 session_deps_
.host_resolver
->set_synchronous_mode(true);
3481 DeterministicSocketData
data(reads
, arraysize(reads
),
3482 writes
, arraysize(writes
));
3483 data
.set_connect_data(connect_data
);
3484 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3486 CreateDeterministicNetworkSession();
3488 base::WeakPtr
<SpdySession
> session
=
3489 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3490 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3491 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3492 session
, test_url_
, MEDIUM
, BoundNetLog());
3493 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
3494 TestCompletionCallback callback1
;
3495 EXPECT_NE(spdy_stream1
->send_window_size(), window_size
);
3497 data
.RunFor(1); // Process the SETTINGS frame, but not the EOF
3498 base::MessageLoop::current()->RunUntilIdle();
3499 EXPECT_EQ(session
->stream_initial_send_window_size(), window_size
);
3500 EXPECT_EQ(spdy_stream1
->send_window_size(), window_size
);
3502 // Release the first one, this will allow the second to be created.
3503 spdy_stream1
->Cancel();
3504 EXPECT_EQ(NULL
, spdy_stream1
.get());
3506 base::WeakPtr
<SpdyStream
> spdy_stream2
=
3507 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3508 session
, test_url_
, MEDIUM
, BoundNetLog());
3509 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
3510 EXPECT_EQ(spdy_stream2
->send_window_size(), window_size
);
3511 spdy_stream2
->Cancel();
3512 EXPECT_EQ(NULL
, spdy_stream2
.get());
3515 // The tests below are only for SPDY/3.1 and above.
3517 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3518 // adjust the session receive window size for SPDY 3.1 and higher. In
3519 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3520 // sending a WINDOW_UPDATE frame for a large enough delta.
3521 TEST_P(SpdySessionTest
, AdjustRecvWindowSize
) {
3522 if (GetParam() < kProtoSPDY31
)
3525 session_deps_
.host_resolver
->set_synchronous_mode(true);
3527 const int32 delta_window_size
= 100;
3529 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3530 MockRead reads
[] = {
3531 MockRead(ASYNC
, 0, 1) // EOF
3533 scoped_ptr
<SpdyFrame
> window_update(
3534 spdy_util_
.ConstructSpdyWindowUpdate(
3535 kSessionFlowControlStreamId
,
3536 kSpdySessionInitialWindowSize
+ delta_window_size
));
3537 MockWrite writes
[] = {
3538 CreateMockWrite(*window_update
, 0),
3540 DeterministicSocketData
data(reads
, arraysize(reads
),
3541 writes
, arraysize(writes
));
3542 data
.set_connect_data(connect_data
);
3543 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3545 CreateDeterministicNetworkSession();
3546 base::WeakPtr
<SpdySession
> session
=
3547 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3548 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3549 session
->flow_control_state());
3551 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3552 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3554 session
->IncreaseRecvWindowSize(delta_window_size
);
3555 EXPECT_EQ(kSpdySessionInitialWindowSize
+ delta_window_size
,
3556 session
->session_recv_window_size_
);
3557 EXPECT_EQ(delta_window_size
, session
->session_unacked_recv_window_bytes_
);
3559 // Should trigger sending a WINDOW_UPDATE frame.
3560 session
->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize
);
3561 EXPECT_EQ(kSpdySessionInitialWindowSize
+ delta_window_size
+
3562 kSpdySessionInitialWindowSize
,
3563 session
->session_recv_window_size_
);
3564 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3568 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3569 session
->in_io_loop_
= true;
3570 session
->DecreaseRecvWindowSize(
3571 kSpdySessionInitialWindowSize
+ delta_window_size
+
3572 kSpdySessionInitialWindowSize
);
3573 session
->in_io_loop_
= false;
3574 EXPECT_EQ(0, session
->session_recv_window_size_
);
3575 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3578 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3579 // adjust the session send window size when the "enable_spdy_31" flag
3581 TEST_P(SpdySessionTest
, AdjustSendWindowSize
) {
3582 if (GetParam() < kProtoSPDY31
)
3585 session_deps_
.host_resolver
->set_synchronous_mode(true);
3587 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3588 MockRead reads
[] = {
3589 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3591 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3592 data
.set_connect_data(connect_data
);
3593 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3595 CreateNetworkSession();
3596 base::WeakPtr
<SpdySession
> session
=
3597 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3598 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3599 session
->flow_control_state());
3601 const int32 delta_window_size
= 100;
3603 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3605 session
->IncreaseSendWindowSize(delta_window_size
);
3606 EXPECT_EQ(kSpdySessionInitialWindowSize
+ delta_window_size
,
3607 session
->session_send_window_size_
);
3609 session
->DecreaseSendWindowSize(delta_window_size
);
3610 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3613 // Incoming data for an inactive stream should not cause the session
3614 // receive window size to decrease, but it should cause the unacked
3615 // bytes to increase.
3616 TEST_P(SpdySessionTest
, SessionFlowControlInactiveStream
) {
3617 if (GetParam() < kProtoSPDY31
)
3620 session_deps_
.host_resolver
->set_synchronous_mode(true);
3622 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3623 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(1, false));
3624 MockRead reads
[] = {
3625 CreateMockRead(*resp
, 0),
3626 MockRead(ASYNC
, 0, 1) // EOF
3628 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
3629 data
.set_connect_data(connect_data
);
3630 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3632 CreateDeterministicNetworkSession();
3633 base::WeakPtr
<SpdySession
> session
=
3634 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3635 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3636 session
->flow_control_state());
3638 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3639 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3643 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3644 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
3649 // A delegate that drops any received data.
3650 class DropReceivedDataDelegate
: public test::StreamDelegateSendImmediate
{
3652 DropReceivedDataDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3653 base::StringPiece data
)
3654 : StreamDelegateSendImmediate(stream
, data
) {}
3656 virtual ~DropReceivedDataDelegate() {}
3658 // Drop any received data.
3659 virtual void OnDataReceived(scoped_ptr
<SpdyBuffer
> buffer
) OVERRIDE
{}
3662 // Send data back and forth but use a delegate that drops its received
3663 // data. The receive window should still increase to its original
3664 // value, i.e. we shouldn't "leak" receive window bytes.
3665 TEST_P(SpdySessionTest
, SessionFlowControlNoReceiveLeaks
) {
3666 if (GetParam() < kProtoSPDY31
)
3669 const char kStreamUrl
[] = "http://www.google.com/";
3671 const int32 msg_data_size
= 100;
3672 const std::string
msg_data(msg_data_size
, 'a');
3674 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3676 scoped_ptr
<SpdyFrame
> req(
3677 spdy_util_
.ConstructSpdyPost(
3678 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3679 scoped_ptr
<SpdyFrame
> msg(
3680 spdy_util_
.ConstructSpdyBodyFrame(
3681 1, msg_data
.data(), msg_data_size
, false));
3682 MockWrite writes
[] = {
3683 CreateMockWrite(*req
, 0),
3684 CreateMockWrite(*msg
, 2),
3687 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3688 scoped_ptr
<SpdyFrame
> echo(
3689 spdy_util_
.ConstructSpdyBodyFrame(
3690 1, msg_data
.data(), msg_data_size
, false));
3691 scoped_ptr
<SpdyFrame
> window_update(
3692 spdy_util_
.ConstructSpdyWindowUpdate(
3693 kSessionFlowControlStreamId
, msg_data_size
));
3694 MockRead reads
[] = {
3695 CreateMockRead(*resp
, 1),
3696 CreateMockRead(*echo
, 3),
3697 MockRead(ASYNC
, 0, 4) // EOF
3700 // Create SpdySession and SpdyStream and send the request.
3701 DeterministicSocketData
data(reads
, arraysize(reads
),
3702 writes
, arraysize(writes
));
3703 data
.set_connect_data(connect_data
);
3704 session_deps_
.host_resolver
->set_synchronous_mode(true);
3705 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3707 CreateDeterministicNetworkSession();
3709 base::WeakPtr
<SpdySession
> session
=
3710 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3712 GURL
url(kStreamUrl
);
3713 base::WeakPtr
<SpdyStream
> stream
=
3714 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3715 session
, url
, MEDIUM
, BoundNetLog());
3716 ASSERT_TRUE(stream
.get() != NULL
);
3717 EXPECT_EQ(0u, stream
->stream_id());
3719 DropReceivedDataDelegate
delegate(stream
, msg_data
);
3720 stream
->SetDelegate(&delegate
);
3722 scoped_ptr
<SpdyHeaderBlock
> headers(
3723 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3724 EXPECT_EQ(ERR_IO_PENDING
,
3725 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3726 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3728 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3729 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3733 EXPECT_TRUE(data
.at_write_eof());
3734 EXPECT_TRUE(data
.at_read_eof());
3736 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3737 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3740 EXPECT_EQ(NULL
, stream
.get());
3742 EXPECT_EQ(OK
, delegate
.WaitForClose());
3744 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3745 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3748 // Send data back and forth but close the stream before its data frame
3749 // can be written to the socket. The send window should then increase
3750 // to its original value, i.e. we shouldn't "leak" send window bytes.
3751 TEST_P(SpdySessionTest
, SessionFlowControlNoSendLeaks
) {
3752 if (GetParam() < kProtoSPDY31
)
3755 const char kStreamUrl
[] = "http://www.google.com/";
3757 const int32 msg_data_size
= 100;
3758 const std::string
msg_data(msg_data_size
, 'a');
3760 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3762 scoped_ptr
<SpdyFrame
> req(
3763 spdy_util_
.ConstructSpdyPost(
3764 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3765 MockWrite writes
[] = {
3766 CreateMockWrite(*req
, 0),
3769 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3770 MockRead reads
[] = {
3771 CreateMockRead(*resp
, 1),
3772 MockRead(ASYNC
, 0, 2) // EOF
3775 // Create SpdySession and SpdyStream and send the request.
3776 DeterministicSocketData
data(reads
, arraysize(reads
),
3777 writes
, arraysize(writes
));
3778 data
.set_connect_data(connect_data
);
3779 session_deps_
.host_resolver
->set_synchronous_mode(true);
3780 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3782 CreateDeterministicNetworkSession();
3784 base::WeakPtr
<SpdySession
> session
=
3785 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3787 GURL
url(kStreamUrl
);
3788 base::WeakPtr
<SpdyStream
> stream
=
3789 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3790 session
, url
, MEDIUM
, BoundNetLog());
3791 ASSERT_TRUE(stream
.get() != NULL
);
3792 EXPECT_EQ(0u, stream
->stream_id());
3794 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3795 stream
->SetDelegate(&delegate
);
3797 scoped_ptr
<SpdyHeaderBlock
> headers(
3798 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3799 EXPECT_EQ(ERR_IO_PENDING
,
3800 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3801 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3803 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3807 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3811 EXPECT_TRUE(data
.at_write_eof());
3812 EXPECT_TRUE(data
.at_read_eof());
3814 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3815 session
->session_send_window_size_
);
3817 // Closing the stream should increase the session's send window.
3819 EXPECT_EQ(NULL
, stream
.get());
3821 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3823 EXPECT_EQ(OK
, delegate
.WaitForClose());
3826 // Send data back and forth; the send and receive windows should
3827 // change appropriately.
3828 TEST_P(SpdySessionTest
, SessionFlowControlEndToEnd
) {
3829 if (GetParam() < kProtoSPDY31
)
3832 const char kStreamUrl
[] = "http://www.google.com/";
3834 const int32 msg_data_size
= 100;
3835 const std::string
msg_data(msg_data_size
, 'a');
3837 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3839 scoped_ptr
<SpdyFrame
> req(
3840 spdy_util_
.ConstructSpdyPost(
3841 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3842 scoped_ptr
<SpdyFrame
> msg(
3843 spdy_util_
.ConstructSpdyBodyFrame(
3844 1, msg_data
.data(), msg_data_size
, false));
3845 MockWrite writes
[] = {
3846 CreateMockWrite(*req
, 0),
3847 CreateMockWrite(*msg
, 2),
3850 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3851 scoped_ptr
<SpdyFrame
> echo(
3852 spdy_util_
.ConstructSpdyBodyFrame(
3853 1, msg_data
.data(), msg_data_size
, false));
3854 scoped_ptr
<SpdyFrame
> window_update(
3855 spdy_util_
.ConstructSpdyWindowUpdate(
3856 kSessionFlowControlStreamId
, msg_data_size
));
3857 MockRead reads
[] = {
3858 CreateMockRead(*resp
, 1),
3859 CreateMockRead(*echo
, 3),
3860 CreateMockRead(*window_update
, 4),
3861 MockRead(ASYNC
, 0, 5) // EOF
3864 // Create SpdySession and SpdyStream and send the request.
3865 DeterministicSocketData
data(reads
, arraysize(reads
),
3866 writes
, arraysize(writes
));
3867 data
.set_connect_data(connect_data
);
3868 session_deps_
.host_resolver
->set_synchronous_mode(true);
3869 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3871 CreateDeterministicNetworkSession();
3873 base::WeakPtr
<SpdySession
> session
=
3874 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3876 GURL
url(kStreamUrl
);
3877 base::WeakPtr
<SpdyStream
> stream
=
3878 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3879 session
, url
, MEDIUM
, BoundNetLog());
3880 ASSERT_TRUE(stream
.get() != NULL
);
3881 EXPECT_EQ(0u, stream
->stream_id());
3883 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3884 stream
->SetDelegate(&delegate
);
3886 scoped_ptr
<SpdyHeaderBlock
> headers(
3887 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3888 EXPECT_EQ(ERR_IO_PENDING
,
3889 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3890 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3892 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3893 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3894 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3898 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3899 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3900 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3904 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3905 session
->session_send_window_size_
);
3906 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3907 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3911 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3912 session
->session_send_window_size_
);
3913 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3914 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3918 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3919 session
->session_send_window_size_
);
3920 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3921 session
->session_recv_window_size_
);
3922 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3926 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3927 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3928 session
->session_recv_window_size_
);
3929 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3931 EXPECT_TRUE(data
.at_write_eof());
3932 EXPECT_TRUE(data
.at_read_eof());
3934 EXPECT_EQ(msg_data
, delegate
.TakeReceivedData());
3936 // Draining the delegate's read queue should increase the session's
3938 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3939 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3940 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3943 EXPECT_EQ(NULL
, stream
.get());
3945 EXPECT_EQ(OK
, delegate
.WaitForClose());
3947 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3948 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3949 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3952 // Given a stall function and an unstall function, runs a test to make
3953 // sure that a stream resumes after unstall.
3954 void SpdySessionTest::RunResumeAfterUnstallTest(
3955 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
3956 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
3958 const char kStreamUrl
[] = "http://www.google.com/";
3959 GURL
url(kStreamUrl
);
3961 session_deps_
.host_resolver
->set_synchronous_mode(true);
3963 scoped_ptr
<SpdyFrame
> req(
3964 spdy_util_
.ConstructSpdyPost(
3965 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
3966 scoped_ptr
<SpdyFrame
> body(
3967 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
3968 MockWrite writes
[] = {
3969 CreateMockWrite(*req
, 0),
3970 CreateMockWrite(*body
, 1),
3973 scoped_ptr
<SpdyFrame
> resp(
3974 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3975 scoped_ptr
<SpdyFrame
> echo(
3976 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
3977 MockRead reads
[] = {
3978 CreateMockRead(*resp
, 2),
3979 MockRead(ASYNC
, 0, 0, 3), // EOF
3982 DeterministicSocketData
data(reads
, arraysize(reads
),
3983 writes
, arraysize(writes
));
3984 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3985 data
.set_connect_data(connect_data
);
3987 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3989 CreateDeterministicNetworkSession();
3990 base::WeakPtr
<SpdySession
> session
=
3991 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3992 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3993 session
->flow_control_state());
3995 base::WeakPtr
<SpdyStream
> stream
=
3996 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3997 session
, url
, LOWEST
, BoundNetLog());
3998 ASSERT_TRUE(stream
.get() != NULL
);
4000 test::StreamDelegateWithBody
delegate(stream
, kBodyDataStringPiece
);
4001 stream
->SetDelegate(&delegate
);
4003 EXPECT_FALSE(stream
->HasUrlFromHeaders());
4004 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4006 scoped_ptr
<SpdyHeaderBlock
> headers(
4007 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4008 EXPECT_EQ(ERR_IO_PENDING
,
4009 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
4010 EXPECT_TRUE(stream
->HasUrlFromHeaders());
4011 EXPECT_EQ(kStreamUrl
, stream
->GetUrlFromHeaders().spec());
4013 stall_function
.Run(session
.get(), stream
.get());
4017 EXPECT_TRUE(stream
->send_stalled_by_flow_control());
4019 unstall_function
.Run(session
.get(), stream
.get(), kBodyDataSize
);
4021 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4025 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
4027 EXPECT_TRUE(delegate
.send_headers_completed());
4028 EXPECT_EQ("200", delegate
.GetResponseHeaderValue(":status"));
4029 EXPECT_EQ(std::string(), delegate
.TakeReceivedData());
4030 EXPECT_TRUE(data
.at_write_eof());
4033 // Run the resume-after-unstall test with all possible stall and
4034 // unstall sequences.
4036 TEST_P(SpdySessionTest
, ResumeAfterUnstallSession
) {
4037 if (GetParam() < kProtoSPDY31
)
4040 RunResumeAfterUnstallTest(
4041 base::Bind(&SpdySessionTest::StallSessionOnly
,
4042 base::Unretained(this)),
4043 base::Bind(&SpdySessionTest::UnstallSessionOnly
,
4044 base::Unretained(this)));
4048 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4049 TEST_P(SpdySessionTest
, ResumeAfterUnstallStream
) {
4050 if (GetParam() < kProtoSPDY31
)
4053 RunResumeAfterUnstallTest(
4054 base::Bind(&SpdySessionTest::StallStreamOnly
,
4055 base::Unretained(this)),
4056 base::Bind(&SpdySessionTest::UnstallStreamOnly
,
4057 base::Unretained(this)));
4060 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallSessionStream
) {
4061 if (GetParam() < kProtoSPDY31
)
4064 RunResumeAfterUnstallTest(
4065 base::Bind(&SpdySessionTest::StallSessionStream
,
4066 base::Unretained(this)),
4067 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4068 base::Unretained(this)));
4071 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallSessionStream
) {
4072 if (GetParam() < kProtoSPDY31
)
4075 RunResumeAfterUnstallTest(
4076 base::Bind(&SpdySessionTest::StallStreamSession
,
4077 base::Unretained(this)),
4078 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4079 base::Unretained(this)));
4082 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallStreamSession
) {
4083 if (GetParam() < kProtoSPDY31
)
4086 RunResumeAfterUnstallTest(
4087 base::Bind(&SpdySessionTest::StallStreamSession
,
4088 base::Unretained(this)),
4089 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4090 base::Unretained(this)));
4093 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallStreamSession
) {
4094 if (GetParam() < kProtoSPDY31
)
4097 RunResumeAfterUnstallTest(
4098 base::Bind(&SpdySessionTest::StallSessionStream
,
4099 base::Unretained(this)),
4100 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4101 base::Unretained(this)));
4104 // Cause a stall by reducing the flow control send window to 0. The
4105 // streams should resume in priority order when that window is then
4107 TEST_P(SpdySessionTest
, ResumeByPriorityAfterSendWindowSizeIncrease
) {
4108 if (GetParam() < kProtoSPDY31
)
4111 const char kStreamUrl
[] = "http://www.google.com/";
4112 GURL
url(kStreamUrl
);
4114 session_deps_
.host_resolver
->set_synchronous_mode(true);
4116 scoped_ptr
<SpdyFrame
> req1(
4117 spdy_util_
.ConstructSpdyPost(
4118 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4119 scoped_ptr
<SpdyFrame
> req2(
4120 spdy_util_
.ConstructSpdyPost(
4121 kStreamUrl
, 3, kBodyDataSize
, MEDIUM
, NULL
, 0));
4122 scoped_ptr
<SpdyFrame
> body1(
4123 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
4124 scoped_ptr
<SpdyFrame
> body2(
4125 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4126 MockWrite writes
[] = {
4127 CreateMockWrite(*req1
, 0),
4128 CreateMockWrite(*req2
, 1),
4129 CreateMockWrite(*body2
, 2),
4130 CreateMockWrite(*body1
, 3),
4133 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4134 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4135 MockRead reads
[] = {
4136 CreateMockRead(*resp1
, 4),
4137 CreateMockRead(*resp2
, 5),
4138 MockRead(ASYNC
, 0, 0, 6), // EOF
4141 DeterministicSocketData
data(reads
, arraysize(reads
),
4142 writes
, arraysize(writes
));
4143 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4144 data
.set_connect_data(connect_data
);
4146 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4148 CreateDeterministicNetworkSession();
4149 base::WeakPtr
<SpdySession
> session
=
4150 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4151 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4152 session
->flow_control_state());
4154 base::WeakPtr
<SpdyStream
> stream1
=
4155 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4156 session
, url
, LOWEST
, BoundNetLog());
4157 ASSERT_TRUE(stream1
.get() != NULL
);
4159 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4160 stream1
->SetDelegate(&delegate1
);
4162 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4164 base::WeakPtr
<SpdyStream
> stream2
=
4165 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4166 session
, url
, MEDIUM
, BoundNetLog());
4167 ASSERT_TRUE(stream2
.get() != NULL
);
4169 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4170 stream2
->SetDelegate(&delegate2
);
4172 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4174 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4175 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4177 StallSessionSend(session
.get());
4179 scoped_ptr
<SpdyHeaderBlock
> headers1(
4180 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4181 EXPECT_EQ(ERR_IO_PENDING
,
4182 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4183 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4184 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4187 EXPECT_EQ(1u, stream1
->stream_id());
4188 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4190 scoped_ptr
<SpdyHeaderBlock
> headers2(
4191 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4192 EXPECT_EQ(ERR_IO_PENDING
,
4193 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4194 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4195 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4198 EXPECT_EQ(3u, stream2
->stream_id());
4199 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4201 // This should unstall only stream2.
4202 UnstallSessionSend(session
.get(), kBodyDataSize
);
4204 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4205 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4209 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4210 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4212 // This should then unstall stream1.
4213 UnstallSessionSend(session
.get(), kBodyDataSize
);
4215 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4216 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4220 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4221 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4223 EXPECT_TRUE(delegate1
.send_headers_completed());
4224 EXPECT_EQ("200", delegate1
.GetResponseHeaderValue(":status"));
4225 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4227 EXPECT_TRUE(delegate2
.send_headers_completed());
4228 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4229 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4231 EXPECT_TRUE(data
.at_write_eof());
4234 // Delegate that closes a given stream after sending its body.
4235 class StreamClosingDelegate
: public test::StreamDelegateWithBody
{
4237 StreamClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
4238 base::StringPiece data
)
4239 : StreamDelegateWithBody(stream
, data
) {}
4241 virtual ~StreamClosingDelegate() {}
4243 void set_stream_to_close(const base::WeakPtr
<SpdyStream
>& stream_to_close
) {
4244 stream_to_close_
= stream_to_close
;
4247 virtual void OnDataSent() OVERRIDE
{
4248 test::StreamDelegateWithBody::OnDataSent();
4249 if (stream_to_close_
.get()) {
4250 stream_to_close_
->Close();
4251 EXPECT_EQ(NULL
, stream_to_close_
.get());
4256 base::WeakPtr
<SpdyStream
> stream_to_close_
;
4259 // Cause a stall by reducing the flow control send window to
4260 // 0. Unstalling the session should properly handle deleted streams.
4261 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedStreams
) {
4262 if (GetParam() < kProtoSPDY31
)
4265 const char kStreamUrl
[] = "http://www.google.com/";
4266 GURL
url(kStreamUrl
);
4268 session_deps_
.host_resolver
->set_synchronous_mode(true);
4270 scoped_ptr
<SpdyFrame
> req1(
4271 spdy_util_
.ConstructSpdyPost(
4272 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4273 scoped_ptr
<SpdyFrame
> req2(
4274 spdy_util_
.ConstructSpdyPost(
4275 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, NULL
, 0));
4276 scoped_ptr
<SpdyFrame
> req3(
4277 spdy_util_
.ConstructSpdyPost(
4278 kStreamUrl
, 5, kBodyDataSize
, LOWEST
, NULL
, 0));
4279 scoped_ptr
<SpdyFrame
> body2(
4280 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4281 MockWrite writes
[] = {
4282 CreateMockWrite(*req1
, 0),
4283 CreateMockWrite(*req2
, 1),
4284 CreateMockWrite(*req3
, 2),
4285 CreateMockWrite(*body2
, 3),
4288 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4289 MockRead reads
[] = {
4290 CreateMockRead(*resp2
, 4),
4291 MockRead(ASYNC
, 0, 0, 5), // EOF
4294 DeterministicSocketData
data(reads
, arraysize(reads
),
4295 writes
, arraysize(writes
));
4296 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4297 data
.set_connect_data(connect_data
);
4299 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4301 CreateDeterministicNetworkSession();
4302 base::WeakPtr
<SpdySession
> session
=
4303 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4304 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4305 session
->flow_control_state());
4307 base::WeakPtr
<SpdyStream
> stream1
=
4308 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4309 session
, url
, LOWEST
, BoundNetLog());
4310 ASSERT_TRUE(stream1
.get() != NULL
);
4312 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4313 stream1
->SetDelegate(&delegate1
);
4315 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4317 base::WeakPtr
<SpdyStream
> stream2
=
4318 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4319 session
, url
, LOWEST
, BoundNetLog());
4320 ASSERT_TRUE(stream2
.get() != NULL
);
4322 StreamClosingDelegate
delegate2(stream2
, kBodyDataStringPiece
);
4323 stream2
->SetDelegate(&delegate2
);
4325 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4327 base::WeakPtr
<SpdyStream
> stream3
=
4328 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4329 session
, url
, LOWEST
, BoundNetLog());
4330 ASSERT_TRUE(stream3
.get() != NULL
);
4332 test::StreamDelegateWithBody
delegate3(stream3
, kBodyDataStringPiece
);
4333 stream3
->SetDelegate(&delegate3
);
4335 EXPECT_FALSE(stream3
->HasUrlFromHeaders());
4337 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4338 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4339 EXPECT_FALSE(stream3
->send_stalled_by_flow_control());
4341 StallSessionSend(session
.get());
4343 scoped_ptr
<SpdyHeaderBlock
> headers1(
4344 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4345 EXPECT_EQ(ERR_IO_PENDING
,
4346 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4347 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4348 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4351 EXPECT_EQ(1u, stream1
->stream_id());
4352 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4354 scoped_ptr
<SpdyHeaderBlock
> headers2(
4355 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4356 EXPECT_EQ(ERR_IO_PENDING
,
4357 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4358 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4359 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4362 EXPECT_EQ(3u, stream2
->stream_id());
4363 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4365 scoped_ptr
<SpdyHeaderBlock
> headers3(
4366 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4367 EXPECT_EQ(ERR_IO_PENDING
,
4368 stream3
->SendRequestHeaders(headers3
.Pass(), MORE_DATA_TO_SEND
));
4369 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
4370 EXPECT_EQ(kStreamUrl
, stream3
->GetUrlFromHeaders().spec());
4373 EXPECT_EQ(5u, stream3
->stream_id());
4374 EXPECT_TRUE(stream3
->send_stalled_by_flow_control());
4376 SpdyStreamId stream_id1
= stream1
->stream_id();
4377 SpdyStreamId stream_id2
= stream2
->stream_id();
4378 SpdyStreamId stream_id3
= stream3
->stream_id();
4380 // Close stream1 preemptively.
4381 session
->CloseActiveStream(stream_id1
, ERR_CONNECTION_CLOSED
);
4382 EXPECT_EQ(NULL
, stream1
.get());
4384 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4385 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4386 EXPECT_TRUE(session
->IsStreamActive(stream_id3
));
4388 // Unstall stream2, which should then close stream3.
4389 delegate2
.set_stream_to_close(stream3
);
4390 UnstallSessionSend(session
.get(), kBodyDataSize
);
4393 EXPECT_EQ(NULL
, stream3
.get());
4395 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4396 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4397 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4398 EXPECT_FALSE(session
->IsStreamActive(stream_id3
));
4401 EXPECT_EQ(NULL
, stream2
.get());
4403 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4404 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4405 EXPECT_EQ(OK
, delegate3
.WaitForClose());
4407 EXPECT_TRUE(delegate1
.send_headers_completed());
4408 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4410 EXPECT_TRUE(delegate2
.send_headers_completed());
4411 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4412 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4414 EXPECT_TRUE(delegate3
.send_headers_completed());
4415 EXPECT_EQ(std::string(), delegate3
.TakeReceivedData());
4417 EXPECT_TRUE(data
.at_write_eof());
4420 // Cause a stall by reducing the flow control send window to
4421 // 0. Unstalling the session should properly handle the session itself
4423 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedSession
) {
4424 if (GetParam() < kProtoSPDY31
)
4427 const char kStreamUrl
[] = "http://www.google.com/";
4428 GURL
url(kStreamUrl
);
4430 session_deps_
.host_resolver
->set_synchronous_mode(true);
4432 scoped_ptr
<SpdyFrame
> req1(
4433 spdy_util_
.ConstructSpdyPost(
4434 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4435 scoped_ptr
<SpdyFrame
> req2(
4436 spdy_util_
.ConstructSpdyPost(
4437 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, NULL
, 0));
4438 scoped_ptr
<SpdyFrame
> body1(
4439 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4440 MockWrite writes
[] = {
4441 CreateMockWrite(*req1
, 0),
4442 CreateMockWrite(*req2
, 1),
4445 MockRead reads
[] = {
4446 MockRead(ASYNC
, 0, 0, 2), // EOF
4449 DeterministicSocketData
data(reads
, arraysize(reads
),
4450 writes
, arraysize(writes
));
4451 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4452 data
.set_connect_data(connect_data
);
4454 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4456 CreateDeterministicNetworkSession();
4457 base::WeakPtr
<SpdySession
> session
=
4458 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4459 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4460 session
->flow_control_state());
4462 base::WeakPtr
<SpdyStream
> stream1
=
4463 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4464 session
, url
, LOWEST
, BoundNetLog());
4465 ASSERT_TRUE(stream1
.get() != NULL
);
4467 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4468 stream1
->SetDelegate(&delegate1
);
4470 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4472 base::WeakPtr
<SpdyStream
> stream2
=
4473 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4474 session
, url
, LOWEST
, BoundNetLog());
4475 ASSERT_TRUE(stream2
.get() != NULL
);
4477 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4478 stream2
->SetDelegate(&delegate2
);
4480 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4482 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4483 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4485 StallSessionSend(session
.get());
4487 scoped_ptr
<SpdyHeaderBlock
> headers1(
4488 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4489 EXPECT_EQ(ERR_IO_PENDING
,
4490 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4491 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4492 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4495 EXPECT_EQ(1u, stream1
->stream_id());
4496 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4498 scoped_ptr
<SpdyHeaderBlock
> headers2(
4499 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4500 EXPECT_EQ(ERR_IO_PENDING
,
4501 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4502 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4503 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4506 EXPECT_EQ(3u, stream2
->stream_id());
4507 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4509 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
4512 UnstallSessionSend(session
.get(), kBodyDataSize
);
4514 // Close the session (since we can't do it from within the delegate
4515 // method, since it's in the stream's loop).
4516 session
->CloseSessionOnError(ERR_CONNECTION_CLOSED
, "Closing session");
4517 base::RunLoop().RunUntilIdle();
4518 EXPECT_TRUE(session
== NULL
);
4520 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
4522 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4523 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4525 EXPECT_TRUE(delegate1
.send_headers_completed());
4526 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4528 EXPECT_TRUE(delegate2
.send_headers_completed());
4529 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4531 EXPECT_TRUE(data
.at_write_eof());
4534 TEST_P(SpdySessionTest
, GoAwayOnSessionFlowControlError
) {
4535 if (GetParam() < kProtoSPDY31
)
4538 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4540 scoped_ptr
<SpdyFrame
> req(
4541 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4542 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
4544 GOAWAY_FLOW_CONTROL_ERROR
,
4545 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4546 "the receive window size of 1"));
4547 MockWrite writes
[] = {
4548 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 3),
4551 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4552 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4553 MockRead reads
[] = {
4554 CreateMockRead(*resp
, 1), CreateMockRead(*body
, 2),
4557 DeterministicSocketData
data(
4558 reads
, arraysize(reads
), writes
, arraysize(writes
));
4559 data
.set_connect_data(connect_data
);
4560 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4562 CreateDeterministicNetworkSession();
4564 base::WeakPtr
<SpdySession
> session
=
4565 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4567 GURL
url(kDefaultURL
);
4568 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
4569 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, LOWEST
, BoundNetLog());
4570 ASSERT_TRUE(spdy_stream
.get() != NULL
);
4571 test::StreamDelegateDoNothing
delegate(spdy_stream
);
4572 spdy_stream
->SetDelegate(&delegate
);
4574 scoped_ptr
<SpdyHeaderBlock
> headers(
4575 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
4576 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4578 data
.RunFor(1); // Write request.
4580 // Put session on the edge of overflowing it's recv window.
4581 session
->session_recv_window_size_
= 1;
4583 // Read response headers & body. Body overflows the session window, and a
4584 // goaway is written.
4586 base::MessageLoop::current()->RunUntilIdle();
4588 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR
, delegate
.WaitForClose());
4589 EXPECT_TRUE(session
== NULL
);
4592 TEST_P(SpdySessionTest
, SplitHeaders
) {
4593 GURL
kStreamUrl("http://www.google.com/foo.dat");
4594 SpdyHeaderBlock headers
;
4595 spdy_util_
.AddUrlToHeaderBlock(kStreamUrl
.spec(), &headers
);
4596 headers
["alpha"] = "beta";
4598 SpdyHeaderBlock request_headers
;
4599 SpdyHeaderBlock response_headers
;
4601 SplitPushedHeadersToRequestAndResponse(
4602 headers
, spdy_util_
.spdy_version(), &request_headers
, &response_headers
);
4604 SpdyHeaderBlock::const_iterator it
= response_headers
.find("alpha");
4605 std::string alpha_val
=
4606 (it
== response_headers
.end()) ? std::string() : it
->second
;
4607 EXPECT_EQ("beta", alpha_val
);
4610 GetUrlFromHeaderBlock(request_headers
, spdy_util_
.spdy_version(), true);
4611 EXPECT_EQ(kStreamUrl
, request_url
);
4614 // Regression. Sorta. Push streams and client streams were sharing a single
4615 // limit for a long time.
4616 TEST_P(SpdySessionTest
, PushedStreamShouldNotCountToClientConcurrencyLimit
) {
4617 SettingsMap new_settings
;
4618 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4619 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, 2);
4620 scoped_ptr
<SpdyFrame
> settings_frame(
4621 spdy_util_
.ConstructSpdySettings(new_settings
));
4622 scoped_ptr
<SpdyFrame
> pushed(spdy_util_
.ConstructSpdyPush(
4623 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4624 MockRead reads
[] = {
4625 CreateMockRead(*settings_frame
), CreateMockRead(*pushed
, 3),
4626 MockRead(ASYNC
, 0, 4),
4629 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
4630 scoped_ptr
<SpdyFrame
> req(
4631 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4632 MockWrite writes
[] = {
4633 CreateMockWrite(*settings_ack
, 1), CreateMockWrite(*req
, 2),
4636 DeterministicSocketData
data(
4637 reads
, arraysize(reads
), writes
, arraysize(writes
));
4638 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4639 data
.set_connect_data(connect_data
);
4640 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4642 CreateDeterministicNetworkSession();
4644 base::WeakPtr
<SpdySession
> session
=
4645 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4647 // Read the settings frame.
4650 GURL
url1(kDefaultURL
);
4651 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4652 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4653 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4654 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4655 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4656 spdy_stream1
->SetDelegate(&delegate1
);
4658 EXPECT_EQ(0u, session
->num_active_streams());
4659 EXPECT_EQ(1u, session
->num_created_streams());
4660 EXPECT_EQ(0u, session
->num_pushed_streams());
4661 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4663 scoped_ptr
<SpdyHeaderBlock
> headers(
4664 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4665 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4666 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4668 // Run until 1st stream is activated.
4669 EXPECT_EQ(0u, delegate1
.stream_id());
4671 EXPECT_EQ(1u, delegate1
.stream_id());
4672 EXPECT_EQ(1u, session
->num_active_streams());
4673 EXPECT_EQ(0u, session
->num_created_streams());
4674 EXPECT_EQ(0u, session
->num_pushed_streams());
4675 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4677 // Run until pushed stream is created.
4679 EXPECT_EQ(2u, session
->num_active_streams());
4680 EXPECT_EQ(0u, session
->num_created_streams());
4681 EXPECT_EQ(1u, session
->num_pushed_streams());
4682 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4684 // Second stream should not be stalled, although we have 2 active streams, but
4685 // one of them is push stream and should not be taken into account when we
4686 // create streams on the client.
4687 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
4688 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4689 EXPECT_TRUE(spdy_stream2
.get() != NULL
);
4690 EXPECT_EQ(2u, session
->num_active_streams());
4691 EXPECT_EQ(1u, session
->num_created_streams());
4692 EXPECT_EQ(1u, session
->num_pushed_streams());
4693 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4699 TEST_P(SpdySessionTest
, RejectPushedStreamExceedingConcurrencyLimit
) {
4700 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4701 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4702 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
4703 NULL
, 0, 4, 1, "http://www.google.com/b.dat"));
4704 MockRead reads
[] = {
4705 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
4706 MockRead(ASYNC
, 0, 4),
4709 scoped_ptr
<SpdyFrame
> req(
4710 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4711 scoped_ptr
<SpdyFrame
> rst(
4712 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4713 MockWrite writes
[] = {
4714 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 3),
4717 DeterministicSocketData
data(
4718 reads
, arraysize(reads
), writes
, arraysize(writes
));
4719 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4720 data
.set_connect_data(connect_data
);
4721 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4723 CreateDeterministicNetworkSession();
4725 base::WeakPtr
<SpdySession
> session
=
4726 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4727 session
->set_max_concurrent_pushed_streams(1);
4729 GURL
url1(kDefaultURL
);
4730 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4731 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4732 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4733 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4734 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4735 spdy_stream1
->SetDelegate(&delegate1
);
4737 EXPECT_EQ(0u, session
->num_active_streams());
4738 EXPECT_EQ(1u, session
->num_created_streams());
4739 EXPECT_EQ(0u, session
->num_pushed_streams());
4740 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4742 scoped_ptr
<SpdyHeaderBlock
> headers(
4743 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4744 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4745 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4747 // Run until 1st stream is activated.
4748 EXPECT_EQ(0u, delegate1
.stream_id());
4750 EXPECT_EQ(1u, delegate1
.stream_id());
4751 EXPECT_EQ(1u, session
->num_active_streams());
4752 EXPECT_EQ(0u, session
->num_created_streams());
4753 EXPECT_EQ(0u, session
->num_pushed_streams());
4754 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4756 // Run until pushed stream is created.
4758 EXPECT_EQ(2u, session
->num_active_streams());
4759 EXPECT_EQ(0u, session
->num_created_streams());
4760 EXPECT_EQ(1u, session
->num_pushed_streams());
4761 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4763 // Reset incoming pushed stream.
4765 EXPECT_EQ(2u, session
->num_active_streams());
4766 EXPECT_EQ(0u, session
->num_created_streams());
4767 EXPECT_EQ(1u, session
->num_pushed_streams());
4768 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4774 TEST_P(SpdySessionTest
, IgnoreReservedRemoteStreamsCount
) {
4775 // Streams in reserved remote state exist only in SPDY4.
4776 if (spdy_util_
.spdy_version() < SPDY4
)
4779 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4780 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4781 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4782 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/b.dat",
4783 push_headers
.get());
4784 scoped_ptr
<SpdyFrame
> push_b(
4785 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 4, 1));
4786 scoped_ptr
<SpdyFrame
> headers_b(
4787 spdy_util_
.ConstructSpdyPushHeaders(4, NULL
, 0));
4788 MockRead reads
[] = {
4789 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
4790 CreateMockRead(*headers_b
, 3), MockRead(ASYNC
, 0, 5),
4793 scoped_ptr
<SpdyFrame
> req(
4794 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4795 scoped_ptr
<SpdyFrame
> rst(
4796 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4797 MockWrite writes
[] = {
4798 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 4),
4801 DeterministicSocketData
data(
4802 reads
, arraysize(reads
), writes
, arraysize(writes
));
4803 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4804 data
.set_connect_data(connect_data
);
4805 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4807 CreateDeterministicNetworkSession();
4809 base::WeakPtr
<SpdySession
> session
=
4810 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4811 session
->set_max_concurrent_pushed_streams(1);
4813 GURL
url1(kDefaultURL
);
4814 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4815 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4816 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4817 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4818 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4819 spdy_stream1
->SetDelegate(&delegate1
);
4821 EXPECT_EQ(0u, session
->num_active_streams());
4822 EXPECT_EQ(1u, session
->num_created_streams());
4823 EXPECT_EQ(0u, session
->num_pushed_streams());
4824 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4826 scoped_ptr
<SpdyHeaderBlock
> headers(
4827 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4828 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4829 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4831 // Run until 1st stream is activated.
4832 EXPECT_EQ(0u, delegate1
.stream_id());
4834 EXPECT_EQ(1u, delegate1
.stream_id());
4835 EXPECT_EQ(1u, session
->num_active_streams());
4836 EXPECT_EQ(0u, session
->num_created_streams());
4837 EXPECT_EQ(0u, session
->num_pushed_streams());
4838 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4840 // Run until pushed stream is created.
4842 EXPECT_EQ(2u, session
->num_active_streams());
4843 EXPECT_EQ(0u, session
->num_created_streams());
4844 EXPECT_EQ(1u, session
->num_pushed_streams());
4845 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4847 // Accept promised stream. It should not count towards pushed stream limit.
4849 EXPECT_EQ(3u, session
->num_active_streams());
4850 EXPECT_EQ(0u, session
->num_created_streams());
4851 EXPECT_EQ(2u, session
->num_pushed_streams());
4852 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4854 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4855 // while we accept only one.
4857 EXPECT_EQ(2u, session
->num_active_streams());
4858 EXPECT_EQ(0u, session
->num_created_streams());
4859 EXPECT_EQ(1u, session
->num_pushed_streams());
4860 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4866 TEST_P(SpdySessionTest
, CancelReservedStreamOnHeadersReceived
) {
4867 // Streams in reserved remote state exist only in SPDY4.
4868 if (spdy_util_
.spdy_version() < SPDY4
)
4871 const char kPushedUrl
[] = "http://www.google.com/a.dat";
4872 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4873 spdy_util_
.AddUrlToHeaderBlock(kPushedUrl
, push_headers
.get());
4874 scoped_ptr
<SpdyFrame
> push_promise(
4875 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 2, 1));
4876 scoped_ptr
<SpdyFrame
> headers_frame(
4877 spdy_util_
.ConstructSpdyPushHeaders(2, NULL
, 0));
4878 MockRead reads
[] = {
4879 CreateMockRead(*push_promise
, 1), CreateMockRead(*headers_frame
, 2),
4880 MockRead(ASYNC
, 0, 4),
4883 scoped_ptr
<SpdyFrame
> req(
4884 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4885 scoped_ptr
<SpdyFrame
> rst(
4886 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
4887 MockWrite writes
[] = {
4888 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 3),
4891 DeterministicSocketData
data(
4892 reads
, arraysize(reads
), writes
, arraysize(writes
));
4893 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4894 data
.set_connect_data(connect_data
);
4895 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4897 CreateDeterministicNetworkSession();
4899 base::WeakPtr
<SpdySession
> session
=
4900 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4902 GURL
url1(kDefaultURL
);
4903 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4904 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4905 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4906 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4907 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4908 spdy_stream1
->SetDelegate(&delegate1
);
4910 EXPECT_EQ(0u, session
->num_active_streams());
4911 EXPECT_EQ(1u, session
->num_created_streams());
4912 EXPECT_EQ(0u, session
->num_pushed_streams());
4913 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4915 scoped_ptr
<SpdyHeaderBlock
> headers(
4916 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4917 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4918 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4920 // Run until 1st stream is activated.
4921 EXPECT_EQ(0u, delegate1
.stream_id());
4923 EXPECT_EQ(1u, delegate1
.stream_id());
4924 EXPECT_EQ(1u, session
->num_active_streams());
4925 EXPECT_EQ(0u, session
->num_created_streams());
4926 EXPECT_EQ(0u, session
->num_pushed_streams());
4927 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4929 // Run until pushed stream is created.
4931 EXPECT_EQ(2u, session
->num_active_streams());
4932 EXPECT_EQ(0u, session
->num_created_streams());
4933 EXPECT_EQ(1u, session
->num_pushed_streams());
4934 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4936 base::WeakPtr
<SpdyStream
> pushed_stream
;
4938 session
->GetPushStream(GURL(kPushedUrl
), &pushed_stream
, BoundNetLog());
4940 ASSERT_TRUE(pushed_stream
.get() != NULL
);
4941 test::StreamDelegateCloseOnHeaders
delegate2(pushed_stream
);
4942 pushed_stream
->SetDelegate(&delegate2
);
4944 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4945 // that all our counters are in consistent state.
4947 EXPECT_EQ(1u, session
->num_active_streams());
4948 EXPECT_EQ(0u, session
->num_created_streams());
4949 EXPECT_EQ(0u, session
->num_pushed_streams());
4950 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4956 TEST_P(SpdySessionTest
, RejectInvalidUnknownFrames
) {
4957 session_deps_
.host_resolver
->set_synchronous_mode(true);
4959 MockRead reads
[] = {
4960 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
4963 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
4965 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4966 data
.set_connect_data(connect_data
);
4967 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4969 CreateNetworkSession();
4970 base::WeakPtr
<SpdySession
> session
=
4971 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4973 session
->stream_hi_water_mark_
= 5;
4974 // Low client (odd) ids are fine.
4975 EXPECT_TRUE(session
->OnUnknownFrame(3, 0));
4976 // Client id exceeding watermark.
4977 EXPECT_FALSE(session
->OnUnknownFrame(9, 0));
4978 // Currently we do not keep track of server initiated (even) ids.
4979 EXPECT_TRUE(session
->OnUnknownFrame(2, 0));
4980 EXPECT_TRUE(session
->OnUnknownFrame(8, 0));
4983 TEST(MapFramerErrorToProtocolError
, MapsValues
) {
4985 SPDY_ERROR_INVALID_CONTROL_FRAME
,
4986 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4988 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS
,
4989 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
4991 SPDY_ERROR_GOAWAY_FRAME_CORRUPT
,
4992 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT
));
4993 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME
,
4994 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME
));
4997 TEST(MapFramerErrorToNetError
, MapsValue
) {
4998 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR
,
4999 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
5000 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
5001 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE
));
5002 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
5003 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE
));
5005 ERR_SPDY_FRAME_SIZE_ERROR
,
5006 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
));
5009 TEST(MapRstStreamStatusToProtocolError
, MapsValues
) {
5010 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR
,
5011 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR
));
5012 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR
,
5013 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR
));
5014 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM
,
5015 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM
));
5018 TEST(MapNetErrorToGoAwayStatus
, MapsValue
) {
5019 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY
,
5020 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
));
5021 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR
,
5022 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR
));
5023 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
,
5024 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR
));
5025 CHECK_EQ(GOAWAY_COMPRESSION_ERROR
,
5026 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR
));
5027 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR
,
5028 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR
));
5029 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED
));
5032 TEST(CanPoolTest
, CanPool
) {
5033 // Load a cert that is valid for:
5038 TransportSecurityState tss
;
5040 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5041 "spdy_pooling.pem");
5043 EXPECT_TRUE(SpdySession::CanPool(
5044 &tss
, ssl_info
, "www.example.org", "www.example.org"));
5045 EXPECT_TRUE(SpdySession::CanPool(
5046 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5047 EXPECT_TRUE(SpdySession::CanPool(
5048 &tss
, ssl_info
, "www.example.org", "mail.example.com"));
5049 EXPECT_FALSE(SpdySession::CanPool(
5050 &tss
, ssl_info
, "www.example.org", "mail.google.com"));
5053 TEST(CanPoolTest
, CanNotPoolWithCertErrors
) {
5054 // Load a cert that is valid for:
5059 TransportSecurityState tss
;
5061 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5062 "spdy_pooling.pem");
5063 ssl_info
.cert_status
= CERT_STATUS_REVOKED
;
5065 EXPECT_FALSE(SpdySession::CanPool(
5066 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5069 TEST(CanPoolTest
, CanNotPoolWithClientCerts
) {
5070 // Load a cert that is valid for:
5075 TransportSecurityState tss
;
5077 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5078 "spdy_pooling.pem");
5079 ssl_info
.client_cert_sent
= true;
5081 EXPECT_FALSE(SpdySession::CanPool(
5082 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5085 TEST(CanPoolTest
, CanNotPoolAcrossETLDsWithChannelID
) {
5086 // Load a cert that is valid for:
5091 TransportSecurityState tss
;
5093 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5094 "spdy_pooling.pem");
5095 ssl_info
.channel_id_sent
= true;
5097 EXPECT_TRUE(SpdySession::CanPool(
5098 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5099 EXPECT_FALSE(SpdySession::CanPool(
5100 &tss
, ssl_info
, "www.example.org", "www.example.com"));
5103 TEST(CanPoolTest
, CanNotPoolWithBadPins
) {
5104 uint8 primary_pin
= 1;
5105 uint8 backup_pin
= 2;
5107 TransportSecurityState tss
;
5108 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5111 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5112 "spdy_pooling.pem");
5113 ssl_info
.is_issued_by_known_root
= true;
5114 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(bad_pin
));
5116 EXPECT_FALSE(SpdySession::CanPool(
5117 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5120 TEST(CanPoolTest
, CanPoolWithAcceptablePins
) {
5121 uint8 primary_pin
= 1;
5122 uint8 backup_pin
= 2;
5123 TransportSecurityState tss
;
5124 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5127 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5128 "spdy_pooling.pem");
5129 ssl_info
.is_issued_by_known_root
= true;
5130 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(primary_pin
));
5132 EXPECT_TRUE(SpdySession::CanPool(
5133 &tss
, ssl_info
, "www.example.org", "mail.example.org"));