1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/spdy/spdy_session.h"
7 #include "base/base64.h"
9 #include "base/callback.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/test/histogram_tester.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/ip_endpoint.h"
15 #include "net/base/net_log_unittest.h"
16 #include "net/base/request_priority.h"
17 #include "net/base/test_data_directory.h"
18 #include "net/base/test_data_stream.h"
19 #include "net/socket/client_socket_pool_manager.h"
20 #include "net/socket/next_proto.h"
21 #include "net/socket/socket_test_util.h"
22 #include "net/spdy/spdy_http_utils.h"
23 #include "net/spdy/spdy_session_pool.h"
24 #include "net/spdy/spdy_session_test_util.h"
25 #include "net/spdy/spdy_stream.h"
26 #include "net/spdy/spdy_stream_test_util.h"
27 #include "net/spdy/spdy_test_util_common.h"
28 #include "net/spdy/spdy_test_utils.h"
29 #include "net/test/cert_test_util.h"
30 #include "testing/platform_test.h"
36 static const char kTestUrl
[] = "http://www.example.org/";
37 static const char kTestHost
[] = "www.example.org";
38 static const int kTestPort
= 80;
40 const char kBodyData
[] = "Body data";
41 const size_t kBodyDataSize
= arraysize(kBodyData
);
42 const base::StringPiece
kBodyDataStringPiece(kBodyData
, kBodyDataSize
);
44 static base::TimeDelta g_time_delta
;
45 base::TimeTicks
TheNearFuture() {
46 return base::TimeTicks::Now() + g_time_delta
;
51 class SpdySessionTest
: public PlatformTest
,
52 public ::testing::WithParamInterface
<NextProto
> {
54 // Functions used with RunResumeAfterUnstallTest().
56 void StallSessionOnly(SpdySession
* session
, SpdyStream
* stream
) {
57 StallSessionSend(session
);
60 void StallStreamOnly(SpdySession
* session
, SpdyStream
* stream
) {
61 StallStreamSend(stream
);
64 void StallSessionStream(SpdySession
* session
, SpdyStream
* stream
) {
65 StallSessionSend(session
);
66 StallStreamSend(stream
);
69 void StallStreamSession(SpdySession
* session
, SpdyStream
* stream
) {
70 StallStreamSend(stream
);
71 StallSessionSend(session
);
74 void UnstallSessionOnly(SpdySession
* session
,
76 int32 delta_window_size
) {
77 UnstallSessionSend(session
, delta_window_size
);
80 void UnstallStreamOnly(SpdySession
* session
,
82 int32 delta_window_size
) {
83 UnstallStreamSend(stream
, delta_window_size
);
86 void UnstallSessionStream(SpdySession
* session
,
88 int32 delta_window_size
) {
89 UnstallSessionSend(session
, delta_window_size
);
90 UnstallStreamSend(stream
, delta_window_size
);
93 void UnstallStreamSession(SpdySession
* session
,
95 int32 delta_window_size
) {
96 UnstallStreamSend(stream
, delta_window_size
);
97 UnstallSessionSend(session
, delta_window_size
);
102 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
103 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
104 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
105 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
106 spdy_util_(GetParam()),
107 session_deps_(GetParam()),
108 spdy_session_pool_(NULL
),
110 test_host_port_pair_(kTestHost
, kTestPort
),
111 key_(test_host_port_pair_
, ProxyServer::Direct(),
112 PRIVACY_MODE_DISABLED
) {
115 virtual ~SpdySessionTest() {
116 // Important to restore the per-pool limit first, since the pool limit must
117 // always be greater than group limit, and the tests reduce both limits.
118 ClientSocketPoolManager::set_max_sockets_per_pool(
119 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
120 ClientSocketPoolManager::set_max_sockets_per_group(
121 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
124 void SetUp() override
{ g_time_delta
= base::TimeDelta(); }
126 void CreateDeterministicNetworkSession() {
128 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
);
129 spdy_session_pool_
= http_session_
->spdy_session_pool();
132 void CreateNetworkSession() {
134 SpdySessionDependencies::SpdyCreateSession(&session_deps_
);
135 spdy_session_pool_
= http_session_
->spdy_session_pool();
138 void StallSessionSend(SpdySession
* session
) {
139 // Reduce the send window size to 0 to stall.
140 while (session
->session_send_window_size_
> 0) {
141 session
->DecreaseSendWindowSize(
142 std::min(kMaxSpdyFrameChunkSize
, session
->session_send_window_size_
));
146 void UnstallSessionSend(SpdySession
* session
, int32 delta_window_size
) {
147 session
->IncreaseSendWindowSize(delta_window_size
);
150 void StallStreamSend(SpdyStream
* stream
) {
151 // Reduce the send window size to 0 to stall.
152 while (stream
->send_window_size() > 0) {
153 stream
->DecreaseSendWindowSize(
154 std::min(kMaxSpdyFrameChunkSize
, stream
->send_window_size()));
158 void UnstallStreamSend(SpdyStream
* stream
, int32 delta_window_size
) {
159 stream
->IncreaseSendWindowSize(delta_window_size
);
162 void RunResumeAfterUnstallTest(
163 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
164 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
167 // Original socket limits. Some tests set these. Safest to always restore
168 // them once each test has been run.
169 int old_max_group_sockets_
;
170 int old_max_pool_sockets_
;
172 SpdyTestUtil spdy_util_
;
173 SpdySessionDependencies session_deps_
;
174 scoped_refptr
<HttpNetworkSession
> http_session_
;
175 SpdySessionPool
* spdy_session_pool_
;
177 HostPortPair test_host_port_pair_
;
181 INSTANTIATE_TEST_CASE_P(NextProto
,
183 testing::Values(kProtoSPDY31
,
187 // Try to create a SPDY session that will fail during
188 // initialization. Nothing should blow up.
189 TEST_P(SpdySessionTest
, InitialReadError
) {
190 CreateDeterministicNetworkSession();
192 base::WeakPtr
<SpdySession
> session
= TryCreateFakeSpdySessionExpectingFailure(
193 spdy_session_pool_
, key_
, ERR_CONNECTION_CLOSED
);
194 EXPECT_TRUE(session
);
196 base::RunLoop().RunUntilIdle();
197 EXPECT_FALSE(session
);
202 // A helper class that vends a callback that, when fired, destroys a
203 // given SpdyStreamRequest.
204 class StreamRequestDestroyingCallback
: public TestCompletionCallbackBase
{
206 StreamRequestDestroyingCallback() {}
208 ~StreamRequestDestroyingCallback() override
{}
210 void SetRequestToDestroy(scoped_ptr
<SpdyStreamRequest
> request
) {
211 request_
= request
.Pass();
214 CompletionCallback
MakeCallback() {
215 return base::Bind(&StreamRequestDestroyingCallback::OnComplete
,
216 base::Unretained(this));
220 void OnComplete(int result
) {
225 scoped_ptr
<SpdyStreamRequest
> request_
;
230 // Request kInitialMaxConcurrentStreams streams. Request two more
231 // streams, but have the callback for one destroy the second stream
232 // request. Close the session. Nothing should blow up. This is a
233 // regression test for http://crbug.com/250841 .
234 TEST_P(SpdySessionTest
, PendingStreamCancellingAnother
) {
235 session_deps_
.host_resolver
->set_synchronous_mode(true);
237 MockRead reads
[] = {MockRead(ASYNC
, 0, 0), };
239 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
240 MockConnect
connect_data(SYNCHRONOUS
, OK
);
241 data
.set_connect_data(connect_data
);
242 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
244 CreateDeterministicNetworkSession();
246 base::WeakPtr
<SpdySession
> session
=
247 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
249 // Create the maximum number of concurrent streams.
250 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
251 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
252 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
, BoundNetLog());
253 ASSERT_TRUE(spdy_stream
!= NULL
);
256 SpdyStreamRequest request1
;
257 scoped_ptr
<SpdyStreamRequest
> request2(new SpdyStreamRequest
);
259 StreamRequestDestroyingCallback callback1
;
260 ASSERT_EQ(ERR_IO_PENDING
,
261 request1
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
,
266 callback1
.MakeCallback()));
268 // |callback2| is never called.
269 TestCompletionCallback callback2
;
270 ASSERT_EQ(ERR_IO_PENDING
,
271 request2
->StartRequest(SPDY_BIDIRECTIONAL_STREAM
,
276 callback2
.callback()));
278 callback1
.SetRequestToDestroy(request2
.Pass());
280 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
282 EXPECT_EQ(ERR_ABORTED
, callback1
.WaitForResult());
285 // A session receiving a GOAWAY frame with no active streams should close.
286 TEST_P(SpdySessionTest
, GoAwayWithNoActiveStreams
) {
287 session_deps_
.host_resolver
->set_synchronous_mode(true);
289 MockConnect
connect_data(SYNCHRONOUS
, OK
);
290 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
292 CreateMockRead(*goaway
, 0),
294 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
295 data
.set_connect_data(connect_data
);
296 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
298 CreateDeterministicNetworkSession();
300 base::WeakPtr
<SpdySession
> session
=
301 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
303 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
305 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
307 // Read and process the GOAWAY frame.
309 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
310 base::RunLoop().RunUntilIdle();
311 EXPECT_TRUE(session
== NULL
);
314 // A session receiving a GOAWAY frame immediately with no active
315 // streams should then close.
316 TEST_P(SpdySessionTest
, GoAwayImmediatelyWithNoActiveStreams
) {
317 session_deps_
.host_resolver
->set_synchronous_mode(true);
319 MockConnect
connect_data(SYNCHRONOUS
, OK
);
320 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
322 CreateMockRead(*goaway
, 0, SYNCHRONOUS
),
324 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
325 data
.set_connect_data(connect_data
);
326 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
328 CreateDeterministicNetworkSession();
332 base::WeakPtr
<SpdySession
> session
=
333 TryCreateInsecureSpdySessionExpectingFailure(
334 http_session_
, key_
, ERR_CONNECTION_CLOSED
, BoundNetLog());
335 base::RunLoop().RunUntilIdle();
337 EXPECT_FALSE(session
);
338 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
341 // A session receiving a GOAWAY frame with active streams should close
342 // when the last active stream is closed.
343 TEST_P(SpdySessionTest
, GoAwayWithActiveStreams
) {
344 session_deps_
.host_resolver
->set_synchronous_mode(true);
346 MockConnect
connect_data(SYNCHRONOUS
, OK
);
347 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
349 CreateMockRead(*goaway
, 2),
350 MockRead(ASYNC
, 0, 3) // EOF
352 scoped_ptr
<SpdyFrame
> req1(
353 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
354 scoped_ptr
<SpdyFrame
> req2(
355 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
356 MockWrite writes
[] = {
357 CreateMockWrite(*req1
, 0),
358 CreateMockWrite(*req2
, 1),
360 DeterministicSocketData
data(reads
, arraysize(reads
),
361 writes
, arraysize(writes
));
362 data
.set_connect_data(connect_data
);
363 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
365 CreateDeterministicNetworkSession();
367 base::WeakPtr
<SpdySession
> session
=
368 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
370 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
372 GURL
url(kDefaultURL
);
373 base::WeakPtr
<SpdyStream
> spdy_stream1
=
374 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
375 session
, url
, MEDIUM
, BoundNetLog());
376 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
377 spdy_stream1
->SetDelegate(&delegate1
);
379 base::WeakPtr
<SpdyStream
> spdy_stream2
=
380 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
381 session
, url
, MEDIUM
, BoundNetLog());
382 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
383 spdy_stream2
->SetDelegate(&delegate2
);
385 scoped_ptr
<SpdyHeaderBlock
> headers(
386 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
387 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
389 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
390 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
391 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
392 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
396 EXPECT_EQ(1u, spdy_stream1
->stream_id());
397 EXPECT_EQ(3u, spdy_stream2
->stream_id());
399 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
401 // Read and process the GOAWAY frame.
404 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
406 EXPECT_FALSE(session
->IsStreamActive(3));
407 EXPECT_EQ(NULL
, spdy_stream2
.get());
408 EXPECT_TRUE(session
->IsStreamActive(1));
410 EXPECT_TRUE(session
->IsGoingAway());
412 // Should close the session.
413 spdy_stream1
->Close();
414 EXPECT_EQ(NULL
, spdy_stream1
.get());
416 base::MessageLoop::current()->RunUntilIdle();
417 EXPECT_TRUE(session
== NULL
);
420 // Have a session receive two GOAWAY frames, with the last one causing
421 // the last active stream to be closed. The session should then be
422 // closed after the second GOAWAY frame.
423 TEST_P(SpdySessionTest
, GoAwayTwice
) {
424 session_deps_
.host_resolver
->set_synchronous_mode(true);
426 MockConnect
connect_data(SYNCHRONOUS
, OK
);
427 scoped_ptr
<SpdyFrame
> goaway1(spdy_util_
.ConstructSpdyGoAway(1));
428 scoped_ptr
<SpdyFrame
> goaway2(spdy_util_
.ConstructSpdyGoAway(0));
430 CreateMockRead(*goaway1
, 2),
431 CreateMockRead(*goaway2
, 3),
432 MockRead(ASYNC
, 0, 4) // EOF
434 scoped_ptr
<SpdyFrame
> req1(
435 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
436 scoped_ptr
<SpdyFrame
> req2(
437 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
438 MockWrite writes
[] = {
439 CreateMockWrite(*req1
, 0),
440 CreateMockWrite(*req2
, 1),
442 DeterministicSocketData
data(reads
, arraysize(reads
),
443 writes
, arraysize(writes
));
444 data
.set_connect_data(connect_data
);
445 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
447 CreateDeterministicNetworkSession();
449 base::WeakPtr
<SpdySession
> session
=
450 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
452 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
454 GURL
url(kDefaultURL
);
455 base::WeakPtr
<SpdyStream
> spdy_stream1
=
456 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
457 session
, url
, MEDIUM
, BoundNetLog());
458 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
459 spdy_stream1
->SetDelegate(&delegate1
);
461 base::WeakPtr
<SpdyStream
> spdy_stream2
=
462 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
463 session
, url
, MEDIUM
, BoundNetLog());
464 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
465 spdy_stream2
->SetDelegate(&delegate2
);
467 scoped_ptr
<SpdyHeaderBlock
> headers(
468 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
469 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
471 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
472 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
473 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
474 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
478 EXPECT_EQ(1u, spdy_stream1
->stream_id());
479 EXPECT_EQ(3u, spdy_stream2
->stream_id());
481 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
483 // Read and process the first GOAWAY frame.
486 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
488 EXPECT_FALSE(session
->IsStreamActive(3));
489 EXPECT_EQ(NULL
, spdy_stream2
.get());
490 EXPECT_TRUE(session
->IsStreamActive(1));
491 EXPECT_TRUE(session
->IsGoingAway());
493 // Read and process the second GOAWAY frame, which should close the
496 base::MessageLoop::current()->RunUntilIdle();
497 EXPECT_TRUE(session
== NULL
);
500 // Have a session with active streams receive a GOAWAY frame and then
501 // close it. It should handle the close properly (i.e., not try to
502 // make itself unavailable in its pool twice).
503 TEST_P(SpdySessionTest
, GoAwayWithActiveStreamsThenClose
) {
504 session_deps_
.host_resolver
->set_synchronous_mode(true);
506 MockConnect
connect_data(SYNCHRONOUS
, OK
);
507 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
509 CreateMockRead(*goaway
, 2),
510 MockRead(ASYNC
, 0, 3) // EOF
512 scoped_ptr
<SpdyFrame
> req1(
513 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
514 scoped_ptr
<SpdyFrame
> req2(
515 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
516 MockWrite writes
[] = {
517 CreateMockWrite(*req1
, 0),
518 CreateMockWrite(*req2
, 1),
520 DeterministicSocketData
data(reads
, arraysize(reads
),
521 writes
, arraysize(writes
));
522 data
.set_connect_data(connect_data
);
523 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
525 CreateDeterministicNetworkSession();
527 base::WeakPtr
<SpdySession
> session
=
528 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
530 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
532 GURL
url(kDefaultURL
);
533 base::WeakPtr
<SpdyStream
> spdy_stream1
=
534 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
535 session
, url
, MEDIUM
, BoundNetLog());
536 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
537 spdy_stream1
->SetDelegate(&delegate1
);
539 base::WeakPtr
<SpdyStream
> spdy_stream2
=
540 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
541 session
, url
, MEDIUM
, BoundNetLog());
542 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
543 spdy_stream2
->SetDelegate(&delegate2
);
545 scoped_ptr
<SpdyHeaderBlock
> headers(
546 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
547 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
549 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
550 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
551 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
552 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
556 EXPECT_EQ(1u, spdy_stream1
->stream_id());
557 EXPECT_EQ(3u, spdy_stream2
->stream_id());
559 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
561 // Read and process the GOAWAY frame.
564 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
566 EXPECT_FALSE(session
->IsStreamActive(3));
567 EXPECT_EQ(NULL
, spdy_stream2
.get());
568 EXPECT_TRUE(session
->IsStreamActive(1));
569 EXPECT_TRUE(session
->IsGoingAway());
571 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
572 EXPECT_EQ(NULL
, spdy_stream1
.get());
574 base::MessageLoop::current()->RunUntilIdle();
575 EXPECT_TRUE(session
== NULL
);
578 // Process a joint read buffer which causes the session to begin draining, and
579 // then processes a GOAWAY. The session should gracefully drain. Regression test
580 // for crbug.com/379469
581 TEST_P(SpdySessionTest
, GoAwayWhileDraining
) {
582 session_deps_
.host_resolver
->set_synchronous_mode(true);
584 scoped_ptr
<SpdyFrame
> req(
585 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
586 MockWrite writes
[] = {
587 CreateMockWrite(*req
, 0),
590 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
591 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
592 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
593 size_t joint_size
= goaway
->size() * 2 + body
->size();
595 // Compose interleaved |goaway| and |body| frames into a single read.
596 scoped_ptr
<char[]> buffer(new char[joint_size
]);
599 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
600 out
+= goaway
->size();
601 memcpy(&buffer
[out
], body
->data(), body
->size());
603 memcpy(&buffer
[out
], goaway
->data(), goaway
->size());
604 out
+= goaway
->size();
605 ASSERT_EQ(out
, joint_size
);
607 SpdyFrame
joint_frames(buffer
.get(), joint_size
, false);
610 CreateMockRead(*resp
, 1), CreateMockRead(joint_frames
, 2),
611 MockRead(ASYNC
, 0, 3) // EOF
614 MockConnect
connect_data(SYNCHRONOUS
, OK
);
615 DeterministicSocketData
data(
616 reads
, arraysize(reads
), writes
, arraysize(writes
));
617 data
.set_connect_data(connect_data
);
618 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
620 CreateDeterministicNetworkSession();
621 base::WeakPtr
<SpdySession
> session
=
622 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
624 GURL
url(kDefaultURL
);
625 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
626 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
627 test::StreamDelegateDoNothing
delegate(spdy_stream
);
628 spdy_stream
->SetDelegate(&delegate
);
630 scoped_ptr
<SpdyHeaderBlock
> headers(
631 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
632 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
633 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
636 base::MessageLoop::current()->RunUntilIdle();
638 // Stream and session closed gracefully.
639 EXPECT_TRUE(delegate
.StreamIsClosed());
640 EXPECT_EQ(OK
, delegate
.WaitForClose());
641 EXPECT_EQ(kUploadData
, delegate
.TakeReceivedData());
642 EXPECT_TRUE(session
== NULL
);
645 // Try to create a stream after receiving a GOAWAY frame. It should
647 TEST_P(SpdySessionTest
, CreateStreamAfterGoAway
) {
648 session_deps_
.host_resolver
->set_synchronous_mode(true);
650 MockConnect
connect_data(SYNCHRONOUS
, OK
);
651 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
653 CreateMockRead(*goaway
, 1),
654 MockRead(ASYNC
, 0, 2) // EOF
656 scoped_ptr
<SpdyFrame
> req(
657 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
658 MockWrite writes
[] = {
659 CreateMockWrite(*req
, 0),
661 DeterministicSocketData
data(reads
, arraysize(reads
),
662 writes
, arraysize(writes
));
663 data
.set_connect_data(connect_data
);
664 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
666 CreateDeterministicNetworkSession();
668 base::WeakPtr
<SpdySession
> session
=
669 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
671 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
673 GURL
url(kDefaultURL
);
674 base::WeakPtr
<SpdyStream
> spdy_stream
=
675 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
676 session
, url
, MEDIUM
, BoundNetLog());
677 test::StreamDelegateDoNothing
delegate(spdy_stream
);
678 spdy_stream
->SetDelegate(&delegate
);
680 scoped_ptr
<SpdyHeaderBlock
> headers(
681 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
682 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
683 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
687 EXPECT_EQ(1u, spdy_stream
->stream_id());
689 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
691 // Read and process the GOAWAY frame.
694 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
695 EXPECT_TRUE(session
->IsStreamActive(1));
697 SpdyStreamRequest stream_request
;
698 int rv
= stream_request
.StartRequest(
699 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog(),
700 CompletionCallback());
701 EXPECT_EQ(ERR_FAILED
, rv
);
703 // Read and process EOF.
706 EXPECT_TRUE(session
== NULL
);
709 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
710 // the stream being refused.
711 TEST_P(SpdySessionTest
, SynStreamAfterGoAway
) {
712 session_deps_
.host_resolver
->set_synchronous_mode(true);
714 MockConnect
connect_data(SYNCHRONOUS
, OK
);
715 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
716 scoped_ptr
<SpdyFrame
>
717 push(spdy_util_
.ConstructSpdyPush(NULL
, 0, 2, 1, kDefaultURL
));
719 CreateMockRead(*goaway
, 1),
720 CreateMockRead(*push
, 2),
721 MockRead(ASYNC
, 0, 4) // EOF
723 scoped_ptr
<SpdyFrame
> req(
724 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
725 scoped_ptr
<SpdyFrame
> rst(
726 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
727 MockWrite writes
[] = {
728 CreateMockWrite(*req
, 0),
729 CreateMockWrite(*rst
, 3)
731 DeterministicSocketData
data(reads
, arraysize(reads
),
732 writes
, arraysize(writes
));
733 data
.set_connect_data(connect_data
);
734 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
736 CreateDeterministicNetworkSession();
738 base::WeakPtr
<SpdySession
> session
=
739 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
741 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
743 GURL
url(kDefaultURL
);
744 base::WeakPtr
<SpdyStream
> spdy_stream
=
745 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
746 session
, url
, MEDIUM
, BoundNetLog());
747 test::StreamDelegateDoNothing
delegate(spdy_stream
);
748 spdy_stream
->SetDelegate(&delegate
);
750 scoped_ptr
<SpdyHeaderBlock
> headers(
751 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
752 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
753 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
757 EXPECT_EQ(1u, spdy_stream
->stream_id());
759 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
761 // Read and process the GOAWAY frame.
764 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
765 EXPECT_TRUE(session
->IsStreamActive(1));
767 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
770 base::MessageLoop::current()->RunUntilIdle();
771 EXPECT_TRUE(session
== NULL
);
774 // A session observing a network change with active streams should close
775 // when the last active stream is closed.
776 TEST_P(SpdySessionTest
, NetworkChangeWithActiveStreams
) {
777 session_deps_
.host_resolver
->set_synchronous_mode(true);
779 MockConnect
connect_data(SYNCHRONOUS
, OK
);
781 MockRead(ASYNC
, 0, 1) // EOF
783 scoped_ptr
<SpdyFrame
> req1(
784 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
785 MockWrite writes
[] = {
786 CreateMockWrite(*req1
, 0),
788 DeterministicSocketData
data(reads
, arraysize(reads
),
789 writes
, arraysize(writes
));
790 data
.set_connect_data(connect_data
);
791 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
793 CreateDeterministicNetworkSession();
795 base::WeakPtr
<SpdySession
> session
=
796 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
798 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
800 base::WeakPtr
<SpdyStream
> spdy_stream
=
801 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
, session
,
802 GURL(kDefaultURL
), MEDIUM
, BoundNetLog());
803 test::StreamDelegateDoNothing
delegate(spdy_stream
);
804 spdy_stream
->SetDelegate(&delegate
);
806 scoped_ptr
<SpdyHeaderBlock
> headers(
807 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
809 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
810 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
814 EXPECT_EQ(1u, spdy_stream
->stream_id());
816 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
818 spdy_session_pool_
->OnIPAddressChanged();
820 // The SpdySessionPool behavior differs based on how the OSs reacts to
821 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
822 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
823 // For OSs where the TCP connections will close upon relevant network
824 // changes, SpdySessionPool doesn't need to force them to close, so in these
825 // cases verify the session has become unavailable but remains open and the
826 // pre-existing stream is still active.
827 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
829 EXPECT_TRUE(session
->IsGoingAway());
831 EXPECT_TRUE(session
->IsStreamActive(1));
833 // Should close the session.
834 spdy_stream
->Close();
836 EXPECT_EQ(NULL
, spdy_stream
.get());
838 base::MessageLoop::current()->RunUntilIdle();
839 EXPECT_TRUE(session
== NULL
);
842 TEST_P(SpdySessionTest
, ClientPing
) {
843 session_deps_
.enable_ping
= true;
844 session_deps_
.host_resolver
->set_synchronous_mode(true);
846 MockConnect
connect_data(SYNCHRONOUS
, OK
);
847 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(1, true));
849 CreateMockRead(*read_ping
, 1),
850 MockRead(ASYNC
, 0, 0, 2) // EOF
852 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
853 MockWrite writes
[] = {
854 CreateMockWrite(*write_ping
, 0),
856 DeterministicSocketData
data(
857 reads
, arraysize(reads
), writes
, arraysize(writes
));
858 data
.set_connect_data(connect_data
);
859 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
861 CreateDeterministicNetworkSession();
863 base::WeakPtr
<SpdySession
> session
=
864 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
866 base::WeakPtr
<SpdyStream
> spdy_stream1
=
867 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
868 session
, test_url_
, MEDIUM
, BoundNetLog());
869 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
870 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
871 spdy_stream1
->SetDelegate(&delegate
);
873 base::TimeTicks before_ping_time
= base::TimeTicks::Now();
875 session
->set_connection_at_risk_of_loss_time(
876 base::TimeDelta::FromSeconds(-1));
877 session
->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
879 session
->SendPrefacePingIfNoneInFlight();
883 session
->CheckPingStatus(before_ping_time
);
885 EXPECT_EQ(0, session
->pings_in_flight());
886 EXPECT_GE(session
->next_ping_id(), 1U);
887 EXPECT_FALSE(session
->check_ping_status_pending());
888 EXPECT_GE(session
->last_activity_time(), before_ping_time
);
892 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
894 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
895 EXPECT_TRUE(session
== NULL
);
898 TEST_P(SpdySessionTest
, ServerPing
) {
899 session_deps_
.host_resolver
->set_synchronous_mode(true);
901 MockConnect
connect_data(SYNCHRONOUS
, OK
);
902 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(2, false));
904 CreateMockRead(*read_ping
),
905 MockRead(SYNCHRONOUS
, 0, 0) // EOF
907 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(2, true));
908 MockWrite writes
[] = {
909 CreateMockWrite(*write_ping
),
911 StaticSocketDataProvider
data(
912 reads
, arraysize(reads
), writes
, arraysize(writes
));
913 data
.set_connect_data(connect_data
);
914 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
916 CreateNetworkSession();
918 base::WeakPtr
<SpdySession
> session
=
919 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
921 base::WeakPtr
<SpdyStream
> spdy_stream1
=
922 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
923 session
, test_url_
, MEDIUM
, BoundNetLog());
924 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
925 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
926 spdy_stream1
->SetDelegate(&delegate
);
928 // Flush the read completion task.
929 base::MessageLoop::current()->RunUntilIdle();
931 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
933 EXPECT_TRUE(session
== NULL
);
934 EXPECT_EQ(NULL
, spdy_stream1
.get());
937 // Cause a ping to be sent out while producing a write. The write loop
938 // should handle this properly, i.e. another DoWriteLoop task should
939 // not be posted. This is a regression test for
940 // http://crbug.com/261043 .
941 TEST_P(SpdySessionTest
, PingAndWriteLoop
) {
942 session_deps_
.enable_ping
= true;
943 session_deps_
.time_func
= TheNearFuture
;
945 MockConnect
connect_data(SYNCHRONOUS
, OK
);
946 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
947 scoped_ptr
<SpdyFrame
> req(
948 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
949 MockWrite writes
[] = {
950 CreateMockWrite(*req
, 0),
951 CreateMockWrite(*write_ping
, 1),
955 MockRead(ASYNC
, 0, 2) // EOF
958 session_deps_
.host_resolver
->set_synchronous_mode(true);
960 DeterministicSocketData
data(reads
, arraysize(reads
),
961 writes
, arraysize(writes
));
962 data
.set_connect_data(connect_data
);
963 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
965 CreateDeterministicNetworkSession();
967 base::WeakPtr
<SpdySession
> session
=
968 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
970 GURL
url(kDefaultURL
);
971 base::WeakPtr
<SpdyStream
> spdy_stream
=
972 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
973 session
, url
, LOWEST
, BoundNetLog());
974 test::StreamDelegateDoNothing
delegate(spdy_stream
);
975 spdy_stream
->SetDelegate(&delegate
);
977 scoped_ptr
<SpdyHeaderBlock
> headers(
978 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
979 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
981 // Shift time so that a ping will be sent out.
982 g_time_delta
= base::TimeDelta::FromSeconds(11);
986 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting");
989 TEST_P(SpdySessionTest
, StreamIdSpaceExhausted
) {
990 const SpdyStreamId kLastStreamId
= 0x7fffffff;
991 session_deps_
.host_resolver
->set_synchronous_mode(true);
993 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
994 // fixed to allow for two stream ID assignments, and three concurrent
995 // streams. Four streams are started, and two are activated. Verify the
996 // session goes away, and that the created (but not activated) and
997 // stalled streams are aborted. Also verify the activated streams complete,
998 // at which point the session closes.
1000 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyGet(
1001 NULL
, 0, false, kLastStreamId
- 2, MEDIUM
, true));
1002 scoped_ptr
<SpdyFrame
> req2(
1003 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, kLastStreamId
, MEDIUM
, true));
1005 MockWrite writes
[] = {
1006 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
1009 scoped_ptr
<SpdyFrame
> resp1(
1010 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, kLastStreamId
- 2));
1011 scoped_ptr
<SpdyFrame
> resp2(
1012 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, kLastStreamId
));
1014 scoped_ptr
<SpdyFrame
> body1(
1015 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
- 2, true));
1016 scoped_ptr
<SpdyFrame
> body2(
1017 spdy_util_
.ConstructSpdyBodyFrame(kLastStreamId
, true));
1019 MockRead reads
[] = {
1020 CreateMockRead(*resp1
, 2), CreateMockRead(*resp2
, 3),
1021 CreateMockRead(*body1
, 4), CreateMockRead(*body2
, 5),
1022 MockRead(ASYNC
, 0, 6) // EOF
1025 DeterministicSocketData
data(
1026 reads
, arraysize(reads
), writes
, arraysize(writes
));
1028 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1029 data
.set_connect_data(connect_data
);
1030 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1032 CreateDeterministicNetworkSession();
1033 base::WeakPtr
<SpdySession
> session
=
1034 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1036 // Fix stream_hi_water_mark_ to allow for two stream activations.
1037 session
->stream_hi_water_mark_
= kLastStreamId
- 2;
1038 // Fix max_concurrent_streams to allow for three stream creations.
1039 session
->max_concurrent_streams_
= 3;
1041 // Create three streams synchronously, and begin a fourth (which is stalled).
1042 GURL
url(kDefaultURL
);
1043 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
1044 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1045 test::StreamDelegateDoNothing
delegate1(stream1
);
1046 stream1
->SetDelegate(&delegate1
);
1048 base::WeakPtr
<SpdyStream
> stream2
= CreateStreamSynchronously(
1049 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1050 test::StreamDelegateDoNothing
delegate2(stream2
);
1051 stream2
->SetDelegate(&delegate2
);
1053 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
1054 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1055 test::StreamDelegateDoNothing
delegate3(stream3
);
1056 stream3
->SetDelegate(&delegate3
);
1058 SpdyStreamRequest request4
;
1059 TestCompletionCallback callback4
;
1060 EXPECT_EQ(ERR_IO_PENDING
,
1061 request4
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
,
1066 callback4
.callback()));
1068 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1069 EXPECT_EQ(0u, session
->num_active_streams());
1070 EXPECT_EQ(3u, session
->num_created_streams());
1071 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1073 // Activate stream 1. One ID remains available.
1074 stream1
->SendRequestHeaders(
1075 scoped_ptr
<SpdyHeaderBlock
>(
1076 spdy_util_
.ConstructGetHeaderBlock(url
.spec())),
1077 NO_MORE_DATA_TO_SEND
);
1080 EXPECT_EQ(kLastStreamId
- 2u, stream1
->stream_id());
1081 EXPECT_EQ(1u, session
->num_active_streams());
1082 EXPECT_EQ(2u, session
->num_created_streams());
1083 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1085 // Activate stream 2. ID space is exhausted.
1086 stream2
->SendRequestHeaders(
1087 scoped_ptr
<SpdyHeaderBlock
>(
1088 spdy_util_
.ConstructGetHeaderBlock(url
.spec())),
1089 NO_MORE_DATA_TO_SEND
);
1092 // Active streams remain active.
1093 EXPECT_EQ(kLastStreamId
, stream2
->stream_id());
1094 EXPECT_EQ(2u, session
->num_active_streams());
1096 // Session is going away. Created and stalled streams were aborted.
1097 EXPECT_EQ(SpdySession::STATE_GOING_AWAY
, session
->availability_state_
);
1098 EXPECT_EQ(ERR_ABORTED
, delegate3
.WaitForClose());
1099 EXPECT_EQ(ERR_ABORTED
, callback4
.WaitForResult());
1100 EXPECT_EQ(0u, session
->num_created_streams());
1101 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1103 // Read responses on remaining active streams.
1105 EXPECT_EQ(OK
, delegate1
.WaitForClose());
1106 EXPECT_EQ(kUploadData
, delegate1
.TakeReceivedData());
1107 EXPECT_EQ(OK
, delegate2
.WaitForClose());
1108 EXPECT_EQ(kUploadData
, delegate2
.TakeReceivedData());
1110 // Session was destroyed.
1111 base::MessageLoop::current()->RunUntilIdle();
1112 EXPECT_FALSE(session
.get());
1115 // Verifies that an unstalled pending stream creation racing with a new stream
1116 // creation doesn't violate the maximum stream concurrency. Regression test for
1117 // crbug.com/373858.
1118 TEST_P(SpdySessionTest
, UnstallRacesWithStreamCreation
) {
1119 session_deps_
.host_resolver
->set_synchronous_mode(true);
1121 MockRead reads
[] = {
1122 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1125 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1127 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1128 data
.set_connect_data(connect_data
);
1129 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1131 CreateNetworkSession();
1132 base::WeakPtr
<SpdySession
> session
=
1133 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1135 // Fix max_concurrent_streams to allow for one open stream.
1136 session
->max_concurrent_streams_
= 1;
1138 // Create two streams: one synchronously, and one which stalls.
1139 GURL
url(kDefaultURL
);
1140 base::WeakPtr
<SpdyStream
> stream1
= CreateStreamSynchronously(
1141 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1143 SpdyStreamRequest request2
;
1144 TestCompletionCallback callback2
;
1145 EXPECT_EQ(ERR_IO_PENDING
,
1146 request2
.StartRequest(SPDY_REQUEST_RESPONSE_STREAM
,
1151 callback2
.callback()));
1153 EXPECT_EQ(1u, session
->num_created_streams());
1154 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1156 // Cancel the first stream. A callback to unstall the second stream was
1157 // posted. Don't run it yet.
1160 EXPECT_EQ(0u, session
->num_created_streams());
1161 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1163 // Create a third stream prior to the second stream's callback.
1164 base::WeakPtr
<SpdyStream
> stream3
= CreateStreamSynchronously(
1165 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
1167 EXPECT_EQ(1u, session
->num_created_streams());
1168 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1170 // NOW run the message loop. The unstalled stream will re-stall itself.
1171 base::MessageLoop::current()->RunUntilIdle();
1172 EXPECT_EQ(1u, session
->num_created_streams());
1173 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(MEDIUM
));
1175 // Cancel the third stream and run the message loop. Verify that the second
1176 // stream creation now completes.
1178 base::MessageLoop::current()->RunUntilIdle();
1180 EXPECT_EQ(1u, session
->num_created_streams());
1181 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(MEDIUM
));
1182 EXPECT_EQ(OK
, callback2
.WaitForResult());
1185 TEST_P(SpdySessionTest
, DeleteExpiredPushStreams
) {
1186 session_deps_
.host_resolver
->set_synchronous_mode(true);
1187 session_deps_
.time_func
= TheNearFuture
;
1189 scoped_ptr
<SpdyFrame
> req(
1190 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
1191 scoped_ptr
<SpdyFrame
> rst(
1192 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
1194 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
1195 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
1196 scoped_ptr
<SpdyFrame
> push_a_body(
1197 spdy_util_
.ConstructSpdyBodyFrame(2, false));
1198 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1199 // iterators inside. See http://crbug.com/443490
1200 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
1201 NULL
, 0, 4, 1, "http://www.google.com/0.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(SpdySession::GetInitialWindowSize(GetParam()) - 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/0.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(SpdySession::GetInitialWindowSize(GetParam()),
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(), 1U);
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
-
1560 SpdySession::GetInitialWindowSize(GetParam())));
1561 std::vector
<MockWrite
> writes
;
1562 if ((GetParam() >= kProtoSPDY4MinimumVersion
) &&
1563 (GetParam() <= kProtoSPDY4MaximumVersion
)) {
1566 kHttp2ConnectionHeaderPrefix
,
1567 kHttp2ConnectionHeaderPrefixSize
));
1569 writes
.push_back(CreateMockWrite(*settings_frame
));
1570 if (GetParam() >= kProtoSPDY31
) {
1571 writes
.push_back(CreateMockWrite(*initial_window_update
));
1574 SettingsMap server_settings
;
1575 const uint32 initial_max_concurrent_streams
= 1;
1576 server_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1577 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED
,
1578 initial_max_concurrent_streams
);
1579 scoped_ptr
<SpdyFrame
> server_settings_frame(
1580 spdy_util_
.ConstructSpdySettings(server_settings
));
1581 if (GetParam() <= kProtoSPDY31
) {
1582 writes
.push_back(CreateMockWrite(*server_settings_frame
));
1585 session_deps_
.stream_initial_recv_window_size
= kInitialRecvWindowSize
;
1587 StaticSocketDataProvider
data(reads
, arraysize(reads
),
1588 vector_as_array(&writes
), writes
.size());
1589 data
.set_connect_data(connect_data
);
1590 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1592 CreateNetworkSession();
1594 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1595 test_host_port_pair_
,
1596 SETTINGS_MAX_CONCURRENT_STREAMS
,
1597 SETTINGS_FLAG_PLEASE_PERSIST
,
1598 initial_max_concurrent_streams
);
1600 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
1601 pool_peer
.SetEnableSendingInitialData(true);
1603 base::WeakPtr
<SpdySession
> session
=
1604 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1606 base::MessageLoop::current()->RunUntilIdle();
1607 EXPECT_TRUE(data
.at_write_eof());
1610 TEST_P(SpdySessionTest
, ClearSettingsStorageOnIPAddressChanged
) {
1611 CreateNetworkSession();
1613 base::WeakPtr
<HttpServerProperties
> test_http_server_properties
=
1614 spdy_session_pool_
->http_server_properties();
1615 SettingsFlagsAndValue
flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST
, 2);
1616 test_http_server_properties
->SetSpdySetting(
1617 test_host_port_pair_
,
1618 SETTINGS_MAX_CONCURRENT_STREAMS
,
1619 SETTINGS_FLAG_PLEASE_PERSIST
,
1621 EXPECT_NE(0u, test_http_server_properties
->GetSpdySettings(
1622 test_host_port_pair_
).size());
1623 spdy_session_pool_
->OnIPAddressChanged();
1624 EXPECT_EQ(0u, test_http_server_properties
->GetSpdySettings(
1625 test_host_port_pair_
).size());
1628 TEST_P(SpdySessionTest
, Initialize
) {
1629 CapturingBoundNetLog log
;
1630 session_deps_
.net_log
= log
.bound().net_log();
1631 session_deps_
.host_resolver
->set_synchronous_mode(true);
1633 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1634 MockRead reads
[] = {
1635 MockRead(ASYNC
, 0, 0) // EOF
1638 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1639 data
.set_connect_data(connect_data
);
1640 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1642 CreateNetworkSession();
1644 base::WeakPtr
<SpdySession
> session
=
1645 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1646 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1648 // Flush the read completion task.
1649 base::MessageLoop::current()->RunUntilIdle();
1651 net::CapturingNetLog::CapturedEntryList entries
;
1652 log
.GetEntries(&entries
);
1653 EXPECT_LT(0u, entries
.size());
1655 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1656 int pos
= net::ExpectLogContainsSomewhere(
1657 entries
, 0, net::NetLog::TYPE_HTTP2_SESSION_INITIALIZED
,
1658 net::NetLog::PHASE_NONE
);
1661 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1662 NetLog::Source socket_source
;
1663 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry
.params
.get(),
1665 EXPECT_TRUE(socket_source
.IsValid());
1666 EXPECT_NE(log
.bound().source().id
, socket_source
.id
);
1669 TEST_P(SpdySessionTest
, NetLogOnSessionGoaway
) {
1670 session_deps_
.host_resolver
->set_synchronous_mode(true);
1672 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1673 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
1674 MockRead reads
[] = {
1675 CreateMockRead(*goaway
),
1676 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1679 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1680 data
.set_connect_data(connect_data
);
1681 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1683 CreateNetworkSession();
1685 CapturingBoundNetLog log
;
1686 base::WeakPtr
<SpdySession
> session
=
1687 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1688 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1690 // Flush the read completion task.
1691 base::MessageLoop::current()->RunUntilIdle();
1693 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1694 EXPECT_TRUE(session
== NULL
);
1696 // Check that the NetLog was filled reasonably.
1697 net::CapturingNetLog::CapturedEntryList entries
;
1698 log
.GetEntries(&entries
);
1699 EXPECT_LT(0u, entries
.size());
1701 // Check that we logged SPDY_SESSION_CLOSE correctly.
1702 int pos
= net::ExpectLogContainsSomewhere(
1703 entries
, 0, net::NetLog::TYPE_HTTP2_SESSION_CLOSE
,
1704 net::NetLog::PHASE_NONE
);
1706 if (pos
< static_cast<int>(entries
.size())) {
1707 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1709 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1710 EXPECT_EQ(OK
, error_code
);
1716 TEST_P(SpdySessionTest
, NetLogOnSessionEOF
) {
1717 session_deps_
.host_resolver
->set_synchronous_mode(true);
1719 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1720 MockRead reads
[] = {
1721 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1724 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1725 data
.set_connect_data(connect_data
);
1726 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1728 CreateNetworkSession();
1730 CapturingBoundNetLog log
;
1731 base::WeakPtr
<SpdySession
> session
=
1732 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1733 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1735 // Flush the read completion task.
1736 base::MessageLoop::current()->RunUntilIdle();
1738 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1739 EXPECT_TRUE(session
== NULL
);
1741 // Check that the NetLog was filled reasonably.
1742 net::CapturingNetLog::CapturedEntryList entries
;
1743 log
.GetEntries(&entries
);
1744 EXPECT_LT(0u, entries
.size());
1746 // Check that we logged SPDY_SESSION_CLOSE correctly.
1747 int pos
= net::ExpectLogContainsSomewhere(
1748 entries
, 0, net::NetLog::TYPE_HTTP2_SESSION_CLOSE
,
1749 net::NetLog::PHASE_NONE
);
1751 if (pos
< static_cast<int>(entries
.size())) {
1752 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1754 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1755 EXPECT_EQ(ERR_CONNECTION_CLOSED
, error_code
);
1761 TEST_P(SpdySessionTest
, SynCompressionHistograms
) {
1762 session_deps_
.enable_compression
= true;
1764 scoped_ptr
<SpdyFrame
> req(
1765 spdy_util_
.ConstructSpdyGet(NULL
, 0, true, 1, MEDIUM
, true));
1766 MockWrite writes
[] = {
1767 CreateMockWrite(*req
, 0),
1769 MockRead reads
[] = {
1770 MockRead(ASYNC
, 0, 1) // EOF
1772 DeterministicSocketData
data(reads
, arraysize(reads
),
1773 writes
, arraysize(writes
));
1774 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1775 data
.set_connect_data(connect_data
);
1776 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1778 CreateDeterministicNetworkSession();
1779 base::WeakPtr
<SpdySession
> session
=
1780 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1782 GURL
url(kDefaultURL
);
1783 base::WeakPtr
<SpdyStream
> spdy_stream
=
1784 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1785 session
, url
, MEDIUM
, BoundNetLog());
1786 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1787 spdy_stream
->SetDelegate(&delegate
);
1789 scoped_ptr
<SpdyHeaderBlock
> headers(
1790 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1791 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1792 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
1794 // Write request headers & capture resulting histogram update.
1795 base::HistogramTester histogram_tester
;
1798 // Regression test of compression performance under the request fixture.
1799 switch (spdy_util_
.spdy_version()) {
1801 histogram_tester
.ExpectBucketCount(
1802 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1805 histogram_tester
.ExpectBucketCount(
1806 "Net.SpdySynStreamCompressionPercentage", 82, 1);
1812 // Read and process EOF.
1814 base::MessageLoop::current()->RunUntilIdle();
1815 EXPECT_TRUE(session
== NULL
);
1818 // Queue up a low-priority SYN_STREAM followed by a high-priority
1819 // one. The high priority one should still send first and receive
1821 TEST_P(SpdySessionTest
, OutOfOrderSynStreams
) {
1822 // Construct the request.
1823 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1824 scoped_ptr
<SpdyFrame
> req_highest(
1825 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, HIGHEST
, true));
1826 scoped_ptr
<SpdyFrame
> req_lowest(
1827 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1828 MockWrite writes
[] = {
1829 CreateMockWrite(*req_highest
, 0),
1830 CreateMockWrite(*req_lowest
, 1),
1833 scoped_ptr
<SpdyFrame
> resp_highest(
1834 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1835 scoped_ptr
<SpdyFrame
> body_highest(
1836 spdy_util_
.ConstructSpdyBodyFrame(1, true));
1837 scoped_ptr
<SpdyFrame
> resp_lowest(
1838 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1839 scoped_ptr
<SpdyFrame
> body_lowest(
1840 spdy_util_
.ConstructSpdyBodyFrame(3, true));
1841 MockRead reads
[] = {
1842 CreateMockRead(*resp_highest
, 2),
1843 CreateMockRead(*body_highest
, 3),
1844 CreateMockRead(*resp_lowest
, 4),
1845 CreateMockRead(*body_lowest
, 5),
1846 MockRead(ASYNC
, 0, 6) // EOF
1849 session_deps_
.host_resolver
->set_synchronous_mode(true);
1851 DeterministicSocketData
data(reads
, arraysize(reads
),
1852 writes
, arraysize(writes
));
1853 data
.set_connect_data(connect_data
);
1854 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1856 CreateDeterministicNetworkSession();
1858 base::WeakPtr
<SpdySession
> session
=
1859 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1861 GURL
url(kDefaultURL
);
1863 base::WeakPtr
<SpdyStream
> spdy_stream_lowest
=
1864 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1865 session
, url
, LOWEST
, BoundNetLog());
1866 ASSERT_TRUE(spdy_stream_lowest
);
1867 EXPECT_EQ(0u, spdy_stream_lowest
->stream_id());
1868 test::StreamDelegateDoNothing
delegate_lowest(spdy_stream_lowest
);
1869 spdy_stream_lowest
->SetDelegate(&delegate_lowest
);
1871 base::WeakPtr
<SpdyStream
> spdy_stream_highest
=
1872 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1873 session
, url
, HIGHEST
, BoundNetLog());
1874 ASSERT_TRUE(spdy_stream_highest
);
1875 EXPECT_EQ(0u, spdy_stream_highest
->stream_id());
1876 test::StreamDelegateDoNothing
delegate_highest(spdy_stream_highest
);
1877 spdy_stream_highest
->SetDelegate(&delegate_highest
);
1879 // Queue the lower priority one first.
1881 scoped_ptr
<SpdyHeaderBlock
> headers_lowest(
1882 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1883 spdy_stream_lowest
->SendRequestHeaders(
1884 headers_lowest
.Pass(), NO_MORE_DATA_TO_SEND
);
1885 EXPECT_TRUE(spdy_stream_lowest
->HasUrlFromHeaders());
1887 scoped_ptr
<SpdyHeaderBlock
> headers_highest(
1888 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1889 spdy_stream_highest
->SendRequestHeaders(
1890 headers_highest
.Pass(), NO_MORE_DATA_TO_SEND
);
1891 EXPECT_TRUE(spdy_stream_highest
->HasUrlFromHeaders());
1895 EXPECT_FALSE(spdy_stream_lowest
);
1896 EXPECT_FALSE(spdy_stream_highest
);
1897 EXPECT_EQ(3u, delegate_lowest
.stream_id());
1898 EXPECT_EQ(1u, delegate_highest
.stream_id());
1901 TEST_P(SpdySessionTest
, CancelStream
) {
1902 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1903 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1904 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1905 scoped_ptr
<SpdyFrame
> req2(
1906 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1907 MockWrite writes
[] = {
1908 CreateMockWrite(*req2
, 0),
1911 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1912 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1913 MockRead reads
[] = {
1914 CreateMockRead(*resp2
, 1),
1915 CreateMockRead(*body2
, 2),
1916 MockRead(ASYNC
, 0, 3) // EOF
1919 session_deps_
.host_resolver
->set_synchronous_mode(true);
1921 DeterministicSocketData
data(reads
, arraysize(reads
),
1922 writes
, arraysize(writes
));
1923 data
.set_connect_data(connect_data
);
1924 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1926 CreateDeterministicNetworkSession();
1928 base::WeakPtr
<SpdySession
> session
=
1929 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1931 GURL
url1(kDefaultURL
);
1932 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1933 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1934 session
, url1
, HIGHEST
, BoundNetLog());
1935 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1936 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1937 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
1938 spdy_stream1
->SetDelegate(&delegate1
);
1940 GURL
url2(kDefaultURL
);
1941 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1942 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1943 session
, url2
, LOWEST
, BoundNetLog());
1944 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1945 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1946 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
1947 spdy_stream2
->SetDelegate(&delegate2
);
1949 scoped_ptr
<SpdyHeaderBlock
> headers(
1950 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1951 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1952 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1954 scoped_ptr
<SpdyHeaderBlock
> headers2(
1955 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1956 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1957 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1959 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1961 spdy_stream1
->Cancel();
1962 EXPECT_EQ(NULL
, spdy_stream1
.get());
1964 EXPECT_EQ(0u, delegate1
.stream_id());
1968 EXPECT_EQ(0u, delegate1
.stream_id());
1969 EXPECT_EQ(1u, delegate2
.stream_id());
1971 spdy_stream2
->Cancel();
1972 EXPECT_EQ(NULL
, spdy_stream2
.get());
1975 // Create two streams that are set to re-close themselves on close,
1976 // and then close the session. Nothing should blow up. Also a
1977 // regression test for http://crbug.com/139518 .
1978 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedSelfClosingStreams
) {
1979 session_deps_
.host_resolver
->set_synchronous_mode(true);
1981 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1983 // No actual data will be sent.
1984 MockWrite writes
[] = {
1985 MockWrite(ASYNC
, 0, 1) // EOF
1988 MockRead reads
[] = {
1989 MockRead(ASYNC
, 0, 0) // EOF
1991 DeterministicSocketData
data(reads
, arraysize(reads
),
1992 writes
, arraysize(writes
));
1993 data
.set_connect_data(connect_data
);
1994 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1996 CreateDeterministicNetworkSession();
1998 base::WeakPtr
<SpdySession
> session
=
1999 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2001 GURL
url1(kDefaultURL
);
2002 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2003 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2004 session
, url1
, HIGHEST
, BoundNetLog());
2005 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2006 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2008 GURL
url2(kDefaultURL
);
2009 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2010 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2011 session
, url2
, LOWEST
, BoundNetLog());
2012 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2013 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2015 test::ClosingDelegate
delegate1(spdy_stream1
);
2016 spdy_stream1
->SetDelegate(&delegate1
);
2018 test::ClosingDelegate
delegate2(spdy_stream2
);
2019 spdy_stream2
->SetDelegate(&delegate2
);
2021 scoped_ptr
<SpdyHeaderBlock
> headers(
2022 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2023 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2024 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2026 scoped_ptr
<SpdyHeaderBlock
> headers2(
2027 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2028 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2029 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2031 // Ensure that the streams have not yet been activated and assigned an id.
2032 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2033 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2035 // Ensure we don't crash while closing the session.
2036 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2038 EXPECT_EQ(NULL
, spdy_stream1
.get());
2039 EXPECT_EQ(NULL
, spdy_stream2
.get());
2041 EXPECT_TRUE(delegate1
.StreamIsClosed());
2042 EXPECT_TRUE(delegate2
.StreamIsClosed());
2044 base::MessageLoop::current()->RunUntilIdle();
2045 EXPECT_TRUE(session
== NULL
);
2048 // Create two streams that are set to close each other on close, and
2049 // then close the session. Nothing should blow up.
2050 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedMutuallyClosingStreams
) {
2051 session_deps_
.host_resolver
->set_synchronous_mode(true);
2053 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2055 // No actual data will be sent.
2056 MockWrite writes
[] = {
2057 MockWrite(ASYNC
, 0, 1) // EOF
2060 MockRead reads
[] = {
2061 MockRead(ASYNC
, 0, 0) // EOF
2063 DeterministicSocketData
data(reads
, arraysize(reads
),
2064 writes
, arraysize(writes
));
2065 data
.set_connect_data(connect_data
);
2066 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2068 CreateDeterministicNetworkSession();
2070 base::WeakPtr
<SpdySession
> session
=
2071 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2073 GURL
url1(kDefaultURL
);
2074 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2075 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2076 session
, url1
, HIGHEST
, BoundNetLog());
2077 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2078 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2080 GURL
url2(kDefaultURL
);
2081 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2082 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2083 session
, url2
, LOWEST
, BoundNetLog());
2084 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2085 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2087 // Make |spdy_stream1| close |spdy_stream2|.
2088 test::ClosingDelegate
delegate1(spdy_stream2
);
2089 spdy_stream1
->SetDelegate(&delegate1
);
2091 // Make |spdy_stream2| close |spdy_stream1|.
2092 test::ClosingDelegate
delegate2(spdy_stream1
);
2093 spdy_stream2
->SetDelegate(&delegate2
);
2095 scoped_ptr
<SpdyHeaderBlock
> headers(
2096 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2097 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2098 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2100 scoped_ptr
<SpdyHeaderBlock
> headers2(
2101 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2102 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2103 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2105 // Ensure that the streams have not yet been activated and assigned an id.
2106 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2107 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2109 // Ensure we don't crash while closing the session.
2110 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2112 EXPECT_EQ(NULL
, spdy_stream1
.get());
2113 EXPECT_EQ(NULL
, spdy_stream2
.get());
2115 EXPECT_TRUE(delegate1
.StreamIsClosed());
2116 EXPECT_TRUE(delegate2
.StreamIsClosed());
2118 base::MessageLoop::current()->RunUntilIdle();
2119 EXPECT_TRUE(session
== NULL
);
2122 // Create two streams that are set to re-close themselves on close,
2123 // activate them, and then close the session. Nothing should blow up.
2124 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedSelfClosingStreams
) {
2125 session_deps_
.host_resolver
->set_synchronous_mode(true);
2127 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2129 scoped_ptr
<SpdyFrame
> req1(
2130 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2131 scoped_ptr
<SpdyFrame
> req2(
2132 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
2133 MockWrite writes
[] = {
2134 CreateMockWrite(*req1
, 0),
2135 CreateMockWrite(*req2
, 1),
2138 MockRead reads
[] = {
2139 MockRead(ASYNC
, 0, 2) // EOF
2142 DeterministicSocketData
data(reads
, arraysize(reads
),
2143 writes
, arraysize(writes
));
2144 data
.set_connect_data(connect_data
);
2145 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2147 CreateDeterministicNetworkSession();
2149 base::WeakPtr
<SpdySession
> session
=
2150 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2152 GURL
url1(kDefaultURL
);
2153 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2154 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2155 session
, url1
, MEDIUM
, BoundNetLog());
2156 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2157 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2159 GURL
url2(kDefaultURL
);
2160 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2161 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2162 session
, url2
, MEDIUM
, BoundNetLog());
2163 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2164 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2166 test::ClosingDelegate
delegate1(spdy_stream1
);
2167 spdy_stream1
->SetDelegate(&delegate1
);
2169 test::ClosingDelegate
delegate2(spdy_stream2
);
2170 spdy_stream2
->SetDelegate(&delegate2
);
2172 scoped_ptr
<SpdyHeaderBlock
> headers(
2173 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2174 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2175 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2177 scoped_ptr
<SpdyHeaderBlock
> headers2(
2178 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2179 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2180 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2182 // Ensure that the streams have not yet been activated and assigned an id.
2183 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2184 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2188 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2189 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2191 // Ensure we don't crash while closing the session.
2192 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2194 EXPECT_EQ(NULL
, spdy_stream1
.get());
2195 EXPECT_EQ(NULL
, spdy_stream2
.get());
2197 EXPECT_TRUE(delegate1
.StreamIsClosed());
2198 EXPECT_TRUE(delegate2
.StreamIsClosed());
2200 base::MessageLoop::current()->RunUntilIdle();
2201 EXPECT_TRUE(session
== NULL
);
2204 // Create two streams that are set to close each other on close,
2205 // activate them, and then close the session. Nothing should blow up.
2206 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedMutuallyClosingStreams
) {
2207 session_deps_
.host_resolver
->set_synchronous_mode(true);
2209 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2211 scoped_ptr
<SpdyFrame
> req1(
2212 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2213 scoped_ptr
<SpdyFrame
> req2(
2214 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
2215 MockWrite writes
[] = {
2216 CreateMockWrite(*req1
, 0),
2217 CreateMockWrite(*req2
, 1),
2220 MockRead reads
[] = {
2221 MockRead(ASYNC
, 0, 2) // EOF
2224 DeterministicSocketData
data(reads
, arraysize(reads
),
2225 writes
, arraysize(writes
));
2226 data
.set_connect_data(connect_data
);
2227 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2229 CreateDeterministicNetworkSession();
2231 base::WeakPtr
<SpdySession
> session
=
2232 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2234 GURL
url1(kDefaultURL
);
2235 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2236 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2237 session
, url1
, MEDIUM
, BoundNetLog());
2238 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2239 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2241 GURL
url2(kDefaultURL
);
2242 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2243 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2244 session
, url2
, MEDIUM
, BoundNetLog());
2245 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2246 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2248 // Make |spdy_stream1| close |spdy_stream2|.
2249 test::ClosingDelegate
delegate1(spdy_stream2
);
2250 spdy_stream1
->SetDelegate(&delegate1
);
2252 // Make |spdy_stream2| close |spdy_stream1|.
2253 test::ClosingDelegate
delegate2(spdy_stream1
);
2254 spdy_stream2
->SetDelegate(&delegate2
);
2256 scoped_ptr
<SpdyHeaderBlock
> headers(
2257 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2258 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2259 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2261 scoped_ptr
<SpdyHeaderBlock
> headers2(
2262 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2263 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2264 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2266 // Ensure that the streams have not yet been activated and assigned an id.
2267 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2268 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2272 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2273 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2275 // Ensure we don't crash while closing the session.
2276 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2278 EXPECT_EQ(NULL
, spdy_stream1
.get());
2279 EXPECT_EQ(NULL
, spdy_stream2
.get());
2281 EXPECT_TRUE(delegate1
.StreamIsClosed());
2282 EXPECT_TRUE(delegate2
.StreamIsClosed());
2284 base::MessageLoop::current()->RunUntilIdle();
2285 EXPECT_TRUE(session
== NULL
);
2288 // Delegate that closes a given session when the stream is closed.
2289 class SessionClosingDelegate
: public test::StreamDelegateDoNothing
{
2291 SessionClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
2292 const base::WeakPtr
<SpdySession
>& session_to_close
)
2293 : StreamDelegateDoNothing(stream
),
2294 session_to_close_(session_to_close
) {}
2296 ~SessionClosingDelegate() override
{}
2298 void OnClose(int status
) override
{
2299 session_to_close_
->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR
, "Error");
2303 base::WeakPtr
<SpdySession
> session_to_close_
;
2306 // Close an activated stream that closes its session. Nothing should
2307 // blow up. This is a regression test for http://crbug.com/263691 .
2308 TEST_P(SpdySessionTest
, CloseActivatedStreamThatClosesSession
) {
2309 session_deps_
.host_resolver
->set_synchronous_mode(true);
2311 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2313 scoped_ptr
<SpdyFrame
> req(
2314 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2315 scoped_ptr
<SpdyFrame
> rst(
2316 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2317 scoped_ptr
<SpdyFrame
> goaway(
2318 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Error"));
2319 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2320 // despite being queued second.
2321 MockWrite writes
[] = {
2322 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 1),
2323 CreateMockWrite(*rst
, 2),
2326 MockRead reads
[] = {
2327 MockRead(ASYNC
, 0, 3) // EOF
2329 DeterministicSocketData
data(reads
, arraysize(reads
),
2330 writes
, arraysize(writes
));
2331 data
.set_connect_data(connect_data
);
2332 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2334 CreateDeterministicNetworkSession();
2336 base::WeakPtr
<SpdySession
> session
=
2337 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2339 GURL
url(kDefaultURL
);
2340 base::WeakPtr
<SpdyStream
> spdy_stream
=
2341 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2342 session
, url
, MEDIUM
, BoundNetLog());
2343 ASSERT_TRUE(spdy_stream
.get() != NULL
);
2344 EXPECT_EQ(0u, spdy_stream
->stream_id());
2346 SessionClosingDelegate
delegate(spdy_stream
, session
);
2347 spdy_stream
->SetDelegate(&delegate
);
2349 scoped_ptr
<SpdyHeaderBlock
> headers(
2350 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
2351 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2352 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
2354 EXPECT_EQ(0u, spdy_stream
->stream_id());
2358 EXPECT_EQ(1u, spdy_stream
->stream_id());
2360 // Ensure we don't crash while closing the stream (which closes the
2362 spdy_stream
->Cancel();
2364 EXPECT_EQ(NULL
, spdy_stream
.get());
2365 EXPECT_TRUE(delegate
.StreamIsClosed());
2367 data
.RunFor(2); // Write the RST_STREAM & GOAWAY.
2368 base::MessageLoop::current()->RunUntilIdle();
2369 EXPECT_TRUE(session
== NULL
);
2372 TEST_P(SpdySessionTest
, VerifyDomainAuthentication
) {
2373 session_deps_
.host_resolver
->set_synchronous_mode(true);
2375 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2377 // No actual data will be sent.
2378 MockWrite writes
[] = {
2379 MockWrite(ASYNC
, 0, 1) // EOF
2382 MockRead reads
[] = {
2383 MockRead(ASYNC
, 0, 0) // EOF
2385 DeterministicSocketData
data(reads
, arraysize(reads
),
2386 writes
, arraysize(writes
));
2387 data
.set_connect_data(connect_data
);
2388 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2390 // Load a cert that is valid for:
2394 base::FilePath certs_dir
= GetTestCertsDirectory();
2395 scoped_refptr
<X509Certificate
> test_cert(
2396 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2397 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
.get());
2399 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2400 ssl
.cert
= test_cert
;
2401 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2403 CreateDeterministicNetworkSession();
2405 base::WeakPtr
<SpdySession
> session
=
2406 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2408 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2409 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2410 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.com"));
2411 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2414 TEST_P(SpdySessionTest
, ConnectionPooledWithTlsChannelId
) {
2415 session_deps_
.host_resolver
->set_synchronous_mode(true);
2417 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2419 // No actual data will be sent.
2420 MockWrite writes
[] = {
2421 MockWrite(ASYNC
, 0, 1) // EOF
2424 MockRead reads
[] = {
2425 MockRead(ASYNC
, 0, 0) // EOF
2427 DeterministicSocketData
data(reads
, arraysize(reads
),
2428 writes
, arraysize(writes
));
2429 data
.set_connect_data(connect_data
);
2430 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2432 // Load a cert that is valid for:
2436 base::FilePath certs_dir
= GetTestCertsDirectory();
2437 scoped_refptr
<X509Certificate
> test_cert(
2438 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2439 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
.get());
2441 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2442 ssl
.channel_id_sent
= true;
2443 ssl
.cert
= test_cert
;
2444 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2446 CreateDeterministicNetworkSession();
2448 base::WeakPtr
<SpdySession
> session
=
2449 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2451 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2452 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2453 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.example.com"));
2454 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2457 TEST_P(SpdySessionTest
, CloseTwoStalledCreateStream
) {
2458 // TODO(rtenneti): Define a helper class/methods and move the common code in
2460 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2462 SettingsMap new_settings
;
2463 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
2464 const uint32 max_concurrent_streams
= 1;
2465 new_settings
[kSpdySettingsIds1
] =
2466 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
2468 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
2469 scoped_ptr
<SpdyFrame
> req1(
2470 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2471 scoped_ptr
<SpdyFrame
> req2(
2472 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
2473 scoped_ptr
<SpdyFrame
> req3(
2474 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
2475 MockWrite writes
[] = {
2476 CreateMockWrite(*settings_ack
, 1),
2477 CreateMockWrite(*req1
, 2),
2478 CreateMockWrite(*req2
, 5),
2479 CreateMockWrite(*req3
, 8),
2482 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2484 scoped_ptr
<SpdyFrame
> settings_frame(
2485 spdy_util_
.ConstructSpdySettings(new_settings
));
2487 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2488 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2490 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
2491 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
2493 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
2494 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
2496 MockRead reads
[] = {
2497 CreateMockRead(*settings_frame
),
2498 CreateMockRead(*resp1
, 3),
2499 CreateMockRead(*body1
, 4),
2500 CreateMockRead(*resp2
, 6),
2501 CreateMockRead(*body2
, 7),
2502 CreateMockRead(*resp3
, 9),
2503 CreateMockRead(*body3
, 10),
2504 MockRead(ASYNC
, 0, 11) // EOF
2507 DeterministicSocketData
data(reads
, arraysize(reads
),
2508 writes
, arraysize(writes
));
2509 data
.set_connect_data(connect_data
);
2510 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2512 CreateDeterministicNetworkSession();
2514 base::WeakPtr
<SpdySession
> session
=
2515 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2517 // Read the settings frame.
2520 GURL
url1(kDefaultURL
);
2521 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2522 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2523 session
, url1
, LOWEST
, BoundNetLog());
2524 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2525 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2526 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2527 spdy_stream1
->SetDelegate(&delegate1
);
2529 TestCompletionCallback callback2
;
2530 GURL
url2(kDefaultURL
);
2531 SpdyStreamRequest request2
;
2532 ASSERT_EQ(ERR_IO_PENDING
,
2533 request2
.StartRequest(
2534 SPDY_REQUEST_RESPONSE_STREAM
,
2535 session
, url2
, LOWEST
, BoundNetLog(), callback2
.callback()));
2537 TestCompletionCallback callback3
;
2538 GURL
url3(kDefaultURL
);
2539 SpdyStreamRequest request3
;
2540 ASSERT_EQ(ERR_IO_PENDING
,
2541 request3
.StartRequest(
2542 SPDY_REQUEST_RESPONSE_STREAM
,
2543 session
, url3
, LOWEST
, BoundNetLog(), callback3
.callback()));
2545 EXPECT_EQ(0u, session
->num_active_streams());
2546 EXPECT_EQ(1u, session
->num_created_streams());
2547 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2549 scoped_ptr
<SpdyHeaderBlock
> headers(
2550 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2551 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2552 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2554 // Run until 1st stream is activated and then closed.
2555 EXPECT_EQ(0u, delegate1
.stream_id());
2557 EXPECT_EQ(NULL
, spdy_stream1
.get());
2558 EXPECT_EQ(1u, delegate1
.stream_id());
2560 EXPECT_EQ(0u, session
->num_active_streams());
2561 EXPECT_EQ(0u, session
->num_created_streams());
2562 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2564 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2565 // create the 2nd stream.
2566 base::MessageLoop::current()->RunUntilIdle();
2568 EXPECT_EQ(0u, session
->num_active_streams());
2569 EXPECT_EQ(1u, session
->num_created_streams());
2570 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2572 base::WeakPtr
<SpdyStream
> stream2
= request2
.ReleaseStream();
2573 test::StreamDelegateDoNothing
delegate2(stream2
);
2574 stream2
->SetDelegate(&delegate2
);
2575 scoped_ptr
<SpdyHeaderBlock
> headers2(
2576 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2577 stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2578 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
2580 // Run until 2nd stream is activated and then closed.
2581 EXPECT_EQ(0u, delegate2
.stream_id());
2583 EXPECT_EQ(NULL
, stream2
.get());
2584 EXPECT_EQ(3u, delegate2
.stream_id());
2586 EXPECT_EQ(0u, session
->num_active_streams());
2587 EXPECT_EQ(0u, session
->num_created_streams());
2588 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2590 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2591 // create the 3rd stream.
2592 base::MessageLoop::current()->RunUntilIdle();
2594 EXPECT_EQ(0u, session
->num_active_streams());
2595 EXPECT_EQ(1u, session
->num_created_streams());
2596 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2598 base::WeakPtr
<SpdyStream
> stream3
= request3
.ReleaseStream();
2599 test::StreamDelegateDoNothing
delegate3(stream3
);
2600 stream3
->SetDelegate(&delegate3
);
2601 scoped_ptr
<SpdyHeaderBlock
> headers3(
2602 spdy_util_
.ConstructGetHeaderBlock(url3
.spec()));
2603 stream3
->SendRequestHeaders(headers3
.Pass(), NO_MORE_DATA_TO_SEND
);
2604 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
2606 // Run until 2nd stream is activated and then closed.
2607 EXPECT_EQ(0u, delegate3
.stream_id());
2609 EXPECT_EQ(NULL
, stream3
.get());
2610 EXPECT_EQ(5u, delegate3
.stream_id());
2612 EXPECT_EQ(0u, session
->num_active_streams());
2613 EXPECT_EQ(0u, session
->num_created_streams());
2614 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2619 TEST_P(SpdySessionTest
, CancelTwoStalledCreateStream
) {
2620 session_deps_
.host_resolver
->set_synchronous_mode(true);
2622 MockRead reads
[] = {
2623 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2626 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
2627 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2629 data
.set_connect_data(connect_data
);
2630 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2632 CreateNetworkSession();
2634 base::WeakPtr
<SpdySession
> session
=
2635 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2637 // Leave room for only one more stream to be created.
2638 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
2639 base::WeakPtr
<SpdyStream
> spdy_stream
=
2640 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2641 session
, test_url_
, MEDIUM
, BoundNetLog());
2642 ASSERT_TRUE(spdy_stream
!= NULL
);
2645 GURL
url1(kDefaultURL
);
2646 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2647 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2648 session
, url1
, LOWEST
, BoundNetLog());
2649 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2650 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2652 TestCompletionCallback callback2
;
2653 GURL
url2(kDefaultURL
);
2654 SpdyStreamRequest request2
;
2655 ASSERT_EQ(ERR_IO_PENDING
,
2656 request2
.StartRequest(
2657 SPDY_BIDIRECTIONAL_STREAM
, session
, url2
, LOWEST
, BoundNetLog(),
2658 callback2
.callback()));
2660 TestCompletionCallback callback3
;
2661 GURL
url3(kDefaultURL
);
2662 SpdyStreamRequest request3
;
2663 ASSERT_EQ(ERR_IO_PENDING
,
2664 request3
.StartRequest(
2665 SPDY_BIDIRECTIONAL_STREAM
, session
, url3
, LOWEST
, BoundNetLog(),
2666 callback3
.callback()));
2668 EXPECT_EQ(0u, session
->num_active_streams());
2669 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2670 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2672 // Cancel the first stream; this will allow the second stream to be created.
2673 EXPECT_TRUE(spdy_stream1
.get() != NULL
);
2674 spdy_stream1
->Cancel();
2675 EXPECT_EQ(NULL
, spdy_stream1
.get());
2677 EXPECT_EQ(OK
, callback2
.WaitForResult());
2678 EXPECT_EQ(0u, session
->num_active_streams());
2679 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2680 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2682 // Cancel the second stream; this will allow the third stream to be created.
2683 base::WeakPtr
<SpdyStream
> spdy_stream2
= request2
.ReleaseStream();
2684 spdy_stream2
->Cancel();
2685 EXPECT_EQ(NULL
, spdy_stream2
.get());
2687 EXPECT_EQ(OK
, callback3
.WaitForResult());
2688 EXPECT_EQ(0u, session
->num_active_streams());
2689 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2690 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2692 // Cancel the third stream.
2693 base::WeakPtr
<SpdyStream
> spdy_stream3
= request3
.ReleaseStream();
2694 spdy_stream3
->Cancel();
2695 EXPECT_EQ(NULL
, spdy_stream3
.get());
2696 EXPECT_EQ(0u, session
->num_active_streams());
2697 EXPECT_EQ(kInitialMaxConcurrentStreams
- 1, session
->num_created_streams());
2698 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2701 // Test that SpdySession::DoReadLoop reads data from the socket
2702 // without yielding. This test makes 32k - 1 bytes of data available
2703 // on the socket for reading. It then verifies that it has read all
2704 // the available data without yielding.
2705 TEST_P(SpdySessionTest
, ReadDataWithoutYielding
) {
2706 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2707 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2709 scoped_ptr
<SpdyFrame
> req1(
2710 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2711 MockWrite writes
[] = {
2712 CreateMockWrite(*req1
, 0),
2715 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2716 // (-spdy_data_frame_size).
2717 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2718 const int kPayloadSize
=
2719 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2720 TestDataStream test_stream
;
2721 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
2722 char* payload_data
= payload
->data();
2723 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2725 scoped_ptr
<SpdyFrame
> partial_data_frame(
2726 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2727 scoped_ptr
<SpdyFrame
> finish_data_frame(
2728 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
- 1, DATA_FLAG_FIN
));
2730 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2732 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2734 MockRead reads
[] = {
2735 CreateMockRead(*resp1
, 1),
2736 CreateMockRead(*partial_data_frame
, 2),
2737 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2738 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2739 CreateMockRead(*finish_data_frame
, 5, SYNCHRONOUS
),
2740 MockRead(ASYNC
, 0, 6) // EOF
2743 // Create SpdySession and SpdyStream and send the request.
2744 DeterministicSocketData
data(reads
, arraysize(reads
),
2745 writes
, arraysize(writes
));
2746 data
.set_connect_data(connect_data
);
2747 session_deps_
.host_resolver
->set_synchronous_mode(true);
2748 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2750 CreateDeterministicNetworkSession();
2752 base::WeakPtr
<SpdySession
> session
=
2753 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2755 GURL
url1(kDefaultURL
);
2756 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2757 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2758 session
, url1
, MEDIUM
, BoundNetLog());
2759 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2760 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2761 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2762 spdy_stream1
->SetDelegate(&delegate1
);
2764 scoped_ptr
<SpdyHeaderBlock
> headers1(
2765 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2766 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2767 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2769 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2771 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2773 // Run until 1st read.
2774 EXPECT_EQ(0u, delegate1
.stream_id());
2776 EXPECT_EQ(1u, delegate1
.stream_id());
2777 EXPECT_EQ(0u, observer
.executed_count());
2779 // Read all the data and verify SpdySession::DoReadLoop has not
2782 EXPECT_EQ(NULL
, spdy_stream1
.get());
2784 // Verify task observer's executed_count is zero, which indicates DoRead read
2785 // all the available data.
2786 EXPECT_EQ(0u, observer
.executed_count());
2787 EXPECT_TRUE(data
.at_write_eof());
2788 EXPECT_TRUE(data
.at_read_eof());
2791 // Test that SpdySession::DoReadLoop yields while reading the
2792 // data. This test makes 32k + 1 bytes of data available on the socket
2793 // for reading. It then verifies that DoRead has yielded even though
2794 // there is data available for it to read (i.e, socket()->Read didn't
2795 // return ERR_IO_PENDING during socket reads).
2796 TEST_P(SpdySessionTest
, TestYieldingDuringReadData
) {
2797 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2798 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2800 scoped_ptr
<SpdyFrame
> req1(
2801 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2802 MockWrite writes
[] = {
2803 CreateMockWrite(*req1
, 0),
2806 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2807 // (-spdy_data_frame_size).
2808 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2809 const int kPayloadSize
=
2810 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2811 TestDataStream test_stream
;
2812 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
2813 char* payload_data
= payload
->data();
2814 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2816 scoped_ptr
<SpdyFrame
> partial_data_frame(
2817 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2818 scoped_ptr
<SpdyFrame
> finish_data_frame(
2819 framer
.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN
));
2821 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2823 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2824 MockRead reads
[] = {
2825 CreateMockRead(*resp1
, 1),
2826 CreateMockRead(*partial_data_frame
, 2),
2827 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2828 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2829 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2830 CreateMockRead(*finish_data_frame
, 6, SYNCHRONOUS
),
2831 MockRead(ASYNC
, 0, 7) // EOF
2834 // Create SpdySession and SpdyStream and send the request.
2835 DeterministicSocketData
data(reads
, arraysize(reads
),
2836 writes
, arraysize(writes
));
2837 data
.set_connect_data(connect_data
);
2838 session_deps_
.host_resolver
->set_synchronous_mode(true);
2839 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2841 CreateDeterministicNetworkSession();
2843 base::WeakPtr
<SpdySession
> session
=
2844 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2846 GURL
url1(kDefaultURL
);
2847 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2848 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2849 session
, url1
, MEDIUM
, BoundNetLog());
2850 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2851 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2852 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2853 spdy_stream1
->SetDelegate(&delegate1
);
2855 scoped_ptr
<SpdyHeaderBlock
> headers1(
2856 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2857 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2858 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2860 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2862 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2864 // Run until 1st read.
2865 EXPECT_EQ(0u, delegate1
.stream_id());
2867 EXPECT_EQ(1u, delegate1
.stream_id());
2868 EXPECT_EQ(0u, observer
.executed_count());
2870 // Read all the data and verify SpdySession::DoReadLoop has posted a
2873 EXPECT_EQ(NULL
, spdy_stream1
.get());
2875 // Verify task observer's executed_count is 1, which indicates DoRead has
2876 // posted only one task and thus yielded though there is data available for it
2878 EXPECT_EQ(1u, observer
.executed_count());
2879 EXPECT_TRUE(data
.at_write_eof());
2880 EXPECT_TRUE(data
.at_read_eof());
2883 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2884 // + async, by doing the following MockReads.
2886 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2887 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2889 // The above reads 26K synchronously. Since that is less that 32K, we
2890 // will attempt to read again. However, that DoRead() will return
2891 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2892 // yield. When we come back, DoRead() will read the results from the
2893 // async read, and rest of the data synchronously.
2894 TEST_P(SpdySessionTest
, TestYieldingDuringAsyncReadData
) {
2895 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2896 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2898 scoped_ptr
<SpdyFrame
> req1(
2899 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2900 MockWrite writes
[] = {
2901 CreateMockWrite(*req1
, 0),
2904 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2905 // (-spdy_data_frame_size).
2906 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2907 TestDataStream test_stream
;
2908 const int kEightKPayloadSize
=
2909 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2910 scoped_refptr
<net::IOBuffer
> eightk_payload(
2911 new net::IOBuffer(kEightKPayloadSize
));
2912 char* eightk_payload_data
= eightk_payload
->data();
2913 test_stream
.GetBytes(eightk_payload_data
, kEightKPayloadSize
);
2915 // Build buffer of 2k size.
2916 TestDataStream test_stream2
;
2917 const int kTwoKPayloadSize
= kEightKPayloadSize
- 6 * 1024;
2918 scoped_refptr
<net::IOBuffer
> twok_payload(
2919 new net::IOBuffer(kTwoKPayloadSize
));
2920 char* twok_payload_data
= twok_payload
->data();
2921 test_stream2
.GetBytes(twok_payload_data
, kTwoKPayloadSize
);
2923 scoped_ptr
<SpdyFrame
> eightk_data_frame(framer
.CreateDataFrame(
2924 1, eightk_payload_data
, kEightKPayloadSize
, DATA_FLAG_NONE
));
2925 scoped_ptr
<SpdyFrame
> twok_data_frame(framer
.CreateDataFrame(
2926 1, twok_payload_data
, kTwoKPayloadSize
, DATA_FLAG_NONE
));
2927 scoped_ptr
<SpdyFrame
> finish_data_frame(framer
.CreateDataFrame(
2928 1, "h", 1, DATA_FLAG_FIN
));
2930 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2932 MockRead reads
[] = {
2933 CreateMockRead(*resp1
, 1),
2934 CreateMockRead(*eightk_data_frame
, 2),
2935 CreateMockRead(*eightk_data_frame
, 3, SYNCHRONOUS
),
2936 CreateMockRead(*eightk_data_frame
, 4, SYNCHRONOUS
),
2937 CreateMockRead(*twok_data_frame
, 5, SYNCHRONOUS
),
2938 CreateMockRead(*eightk_data_frame
, 6, ASYNC
),
2939 CreateMockRead(*eightk_data_frame
, 7, SYNCHRONOUS
),
2940 CreateMockRead(*eightk_data_frame
, 8, SYNCHRONOUS
),
2941 CreateMockRead(*eightk_data_frame
, 9, SYNCHRONOUS
),
2942 CreateMockRead(*twok_data_frame
, 10, SYNCHRONOUS
),
2943 CreateMockRead(*finish_data_frame
, 11, SYNCHRONOUS
),
2944 MockRead(ASYNC
, 0, 12) // EOF
2947 // Create SpdySession and SpdyStream and send the request.
2948 DeterministicSocketData
data(reads
, arraysize(reads
),
2949 writes
, arraysize(writes
));
2950 data
.set_connect_data(connect_data
);
2951 session_deps_
.host_resolver
->set_synchronous_mode(true);
2952 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2954 CreateDeterministicNetworkSession();
2956 base::WeakPtr
<SpdySession
> session
=
2957 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2959 GURL
url1(kDefaultURL
);
2960 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2961 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2962 session
, url1
, MEDIUM
, BoundNetLog());
2963 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2964 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2965 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2966 spdy_stream1
->SetDelegate(&delegate1
);
2968 scoped_ptr
<SpdyHeaderBlock
> headers1(
2969 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2970 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2971 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2973 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2974 // posting of tasks.
2975 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2977 // Run until 1st read.
2978 EXPECT_EQ(0u, delegate1
.stream_id());
2980 EXPECT_EQ(1u, delegate1
.stream_id());
2981 EXPECT_EQ(0u, observer
.executed_count());
2983 // Read all the data and verify SpdySession::DoReadLoop has posted a
2986 EXPECT_EQ(NULL
, spdy_stream1
.get());
2988 // Verify task observer's executed_count is 1, which indicates DoRead has
2989 // posted only one task and thus yielded though there is data available for
2991 EXPECT_EQ(1u, observer
.executed_count());
2992 EXPECT_TRUE(data
.at_write_eof());
2993 EXPECT_TRUE(data
.at_read_eof());
2996 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2997 // nothing blows up.
2998 TEST_P(SpdySessionTest
, GoAwayWhileInDoReadLoop
) {
2999 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3000 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
3002 scoped_ptr
<SpdyFrame
> req1(
3003 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
3004 MockWrite writes
[] = {
3005 CreateMockWrite(*req1
, 0),
3008 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3009 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3010 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
3012 MockRead reads
[] = {
3013 CreateMockRead(*resp1
, 1),
3014 CreateMockRead(*body1
, 2),
3015 CreateMockRead(*goaway
, 3),
3018 // Create SpdySession and SpdyStream and send the request.
3019 DeterministicSocketData
data(reads
, arraysize(reads
),
3020 writes
, arraysize(writes
));
3021 data
.set_connect_data(connect_data
);
3022 session_deps_
.host_resolver
->set_synchronous_mode(true);
3023 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3025 CreateDeterministicNetworkSession();
3027 base::WeakPtr
<SpdySession
> session
=
3028 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3030 GURL
url1(kDefaultURL
);
3031 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3032 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3033 session
, url1
, MEDIUM
, BoundNetLog());
3034 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3035 spdy_stream1
->SetDelegate(&delegate1
);
3036 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
3037 EXPECT_EQ(0u, spdy_stream1
->stream_id());
3039 scoped_ptr
<SpdyHeaderBlock
> headers1(
3040 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
3041 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
3042 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3044 // Run until 1st read.
3045 EXPECT_EQ(0u, spdy_stream1
->stream_id());
3047 EXPECT_EQ(1u, spdy_stream1
->stream_id());
3049 // Run until GoAway.
3051 EXPECT_EQ(NULL
, spdy_stream1
.get());
3052 EXPECT_TRUE(data
.at_write_eof());
3053 EXPECT_TRUE(data
.at_read_eof());
3054 EXPECT_TRUE(session
== NULL
);
3057 // Within this framework, a SpdySession should be initialized with
3058 // flow control disabled for protocol version 2, with flow control
3059 // enabled only for streams for protocol version 3, and with flow
3060 // control enabled for streams and sessions for higher versions.
3061 TEST_P(SpdySessionTest
, ProtocolNegotiation
) {
3062 session_deps_
.host_resolver
->set_synchronous_mode(true);
3064 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3065 MockRead reads
[] = {
3066 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3068 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3069 data
.set_connect_data(connect_data
);
3070 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3072 CreateNetworkSession();
3073 base::WeakPtr
<SpdySession
> session
=
3074 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3076 EXPECT_EQ(spdy_util_
.spdy_version(),
3077 session
->buffered_spdy_framer_
->protocol_version());
3078 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3079 session
->flow_control_state());
3080 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3081 session
->session_send_window_size_
);
3082 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3083 session
->session_recv_window_size_
);
3084 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3087 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3088 // pointers to the idle session are currently held.
3089 TEST_P(SpdySessionTest
, CloseOneIdleConnection
) {
3090 ClientSocketPoolManager::set_max_sockets_per_group(
3091 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3092 ClientSocketPoolManager::set_max_sockets_per_pool(
3093 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3095 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3096 MockRead reads
[] = {
3097 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3099 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3100 data
.set_connect_data(connect_data
);
3101 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3102 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3104 CreateNetworkSession();
3106 TransportClientSocketPool
* pool
=
3107 http_session_
->GetTransportSocketPool(
3108 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3110 // Create an idle SPDY session.
3111 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3112 PRIVACY_MODE_DISABLED
);
3113 base::WeakPtr
<SpdySession
> session1
=
3114 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3115 EXPECT_FALSE(pool
->IsStalled());
3117 // Trying to create a new connection should cause the pool to be stalled, and
3118 // post a task asynchronously to try and close the session.
3119 TestCompletionCallback callback2
;
3120 HostPortPair
host_port2("2.com", 80);
3121 scoped_refptr
<TransportSocketParams
> params2(
3122 new TransportSocketParams(
3123 host_port2
, false, false, OnHostResolutionCallback(),
3124 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3125 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3126 EXPECT_EQ(ERR_IO_PENDING
,
3127 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3128 callback2
.callback(), pool
, BoundNetLog()));
3129 EXPECT_TRUE(pool
->IsStalled());
3131 // The socket pool should close the connection asynchronously and establish a
3133 EXPECT_EQ(OK
, callback2
.WaitForResult());
3134 EXPECT_FALSE(pool
->IsStalled());
3135 EXPECT_TRUE(session1
== NULL
);
3138 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3139 // pointers to the idle session are currently held, in the case the SPDY session
3141 TEST_P(SpdySessionTest
, CloseOneIdleConnectionWithAlias
) {
3142 ClientSocketPoolManager::set_max_sockets_per_group(
3143 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3144 ClientSocketPoolManager::set_max_sockets_per_pool(
3145 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3147 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3148 MockRead reads
[] = {
3149 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3151 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3152 data
.set_connect_data(connect_data
);
3153 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3154 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3156 session_deps_
.host_resolver
->set_synchronous_mode(true);
3157 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3158 "1.com", "192.168.0.2", std::string());
3159 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3160 "2.com", "192.168.0.2", std::string());
3161 // Not strictly needed.
3162 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3163 "3.com", "192.168.0.3", std::string());
3165 CreateNetworkSession();
3167 TransportClientSocketPool
* pool
=
3168 http_session_
->GetTransportSocketPool(
3169 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3171 // Create an idle SPDY session.
3172 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3173 PRIVACY_MODE_DISABLED
);
3174 base::WeakPtr
<SpdySession
> session1
=
3175 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3176 EXPECT_FALSE(pool
->IsStalled());
3178 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3179 SpdySessionKey
key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3180 PRIVACY_MODE_DISABLED
);
3181 HostResolver::RequestInfo
info(key2
.host_port_pair());
3182 AddressList addresses
;
3183 // Pre-populate the DNS cache, since a synchronous resolution is required in
3184 // order to create the alias.
3185 session_deps_
.host_resolver
->Resolve(info
,
3188 CompletionCallback(),
3191 // Get a session for |key2|, which should return the session created earlier.
3192 base::WeakPtr
<SpdySession
> session2
=
3193 spdy_session_pool_
->FindAvailableSession(key2
, BoundNetLog());
3194 ASSERT_EQ(session1
.get(), session2
.get());
3195 EXPECT_FALSE(pool
->IsStalled());
3197 // Trying to create a new connection should cause the pool to be stalled, and
3198 // post a task asynchronously to try and close the session.
3199 TestCompletionCallback callback3
;
3200 HostPortPair
host_port3("3.com", 80);
3201 scoped_refptr
<TransportSocketParams
> params3(
3202 new TransportSocketParams(
3203 host_port3
, false, false, OnHostResolutionCallback(),
3204 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3205 scoped_ptr
<ClientSocketHandle
> connection3(new ClientSocketHandle
);
3206 EXPECT_EQ(ERR_IO_PENDING
,
3207 connection3
->Init(host_port3
.ToString(), params3
, DEFAULT_PRIORITY
,
3208 callback3
.callback(), pool
, BoundNetLog()));
3209 EXPECT_TRUE(pool
->IsStalled());
3211 // The socket pool should close the connection asynchronously and establish a
3213 EXPECT_EQ(OK
, callback3
.WaitForResult());
3214 EXPECT_FALSE(pool
->IsStalled());
3215 EXPECT_TRUE(session1
== NULL
);
3216 EXPECT_TRUE(session2
== NULL
);
3219 // Tests that when a SPDY session becomes idle, it closes itself if there is
3220 // a lower layer pool stalled on the per-pool socket limit.
3221 TEST_P(SpdySessionTest
, CloseSessionOnIdleWhenPoolStalled
) {
3222 ClientSocketPoolManager::set_max_sockets_per_group(
3223 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3224 ClientSocketPoolManager::set_max_sockets_per_pool(
3225 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3227 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3228 MockRead reads
[] = {
3229 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3231 scoped_ptr
<SpdyFrame
> req1(
3232 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3233 scoped_ptr
<SpdyFrame
> cancel1(
3234 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3235 MockWrite writes
[] = {
3236 CreateMockWrite(*req1
, 1),
3237 CreateMockWrite(*cancel1
, 1),
3239 StaticSocketDataProvider
data(reads
, arraysize(reads
),
3240 writes
, arraysize(writes
));
3241 data
.set_connect_data(connect_data
);
3242 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3244 MockRead http_reads
[] = {
3245 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3247 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
3249 http_data
.set_connect_data(connect_data
);
3250 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
3253 CreateNetworkSession();
3255 TransportClientSocketPool
* pool
=
3256 http_session_
->GetTransportSocketPool(
3257 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3259 // Create a SPDY session.
3260 GURL
url1(kDefaultURL
);
3261 SpdySessionKey
key1(HostPortPair(url1
.host(), 80),
3262 ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3263 base::WeakPtr
<SpdySession
> session1
=
3264 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3265 EXPECT_FALSE(pool
->IsStalled());
3267 // Create a stream using the session, and send a request.
3269 TestCompletionCallback callback1
;
3270 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3271 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3272 session1
, url1
, DEFAULT_PRIORITY
,
3274 ASSERT_TRUE(spdy_stream1
.get());
3275 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3276 spdy_stream1
->SetDelegate(&delegate1
);
3278 scoped_ptr
<SpdyHeaderBlock
> headers1(
3279 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
3280 EXPECT_EQ(ERR_IO_PENDING
,
3281 spdy_stream1
->SendRequestHeaders(
3282 headers1
.Pass(), NO_MORE_DATA_TO_SEND
));
3283 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3285 base::MessageLoop::current()->RunUntilIdle();
3287 // Trying to create a new connection should cause the pool to be stalled, and
3288 // post a task asynchronously to try and close the session.
3289 TestCompletionCallback callback2
;
3290 HostPortPair
host_port2("2.com", 80);
3291 scoped_refptr
<TransportSocketParams
> params2(
3292 new TransportSocketParams(
3293 host_port2
, false, false, OnHostResolutionCallback(),
3294 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3295 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3296 EXPECT_EQ(ERR_IO_PENDING
,
3297 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3298 callback2
.callback(), pool
, BoundNetLog()));
3299 EXPECT_TRUE(pool
->IsStalled());
3301 // Running the message loop should cause the socket pool to ask the SPDY
3302 // session to close an idle socket, but since the socket is in use, nothing
3304 base::RunLoop().RunUntilIdle();
3305 EXPECT_TRUE(pool
->IsStalled());
3306 EXPECT_FALSE(callback2
.have_result());
3308 // Cancelling the request should result in the session's socket being
3309 // closed, since the pool is stalled.
3310 ASSERT_TRUE(spdy_stream1
.get());
3311 spdy_stream1
->Cancel();
3312 base::RunLoop().RunUntilIdle();
3313 ASSERT_FALSE(pool
->IsStalled());
3314 EXPECT_EQ(OK
, callback2
.WaitForResult());
3317 // Verify that SpdySessionKey and therefore SpdySession is different when
3318 // privacy mode is enabled or disabled.
3319 TEST_P(SpdySessionTest
, SpdySessionKeyPrivacyMode
) {
3320 CreateDeterministicNetworkSession();
3322 HostPortPair
host_port_pair("www.google.com", 443);
3323 SpdySessionKey
key_privacy_enabled(host_port_pair
, ProxyServer::Direct(),
3324 PRIVACY_MODE_ENABLED
);
3325 SpdySessionKey
key_privacy_disabled(host_port_pair
, ProxyServer::Direct(),
3326 PRIVACY_MODE_DISABLED
);
3328 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3329 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3331 // Add SpdySession with PrivacyMode Enabled to the pool.
3332 base::WeakPtr
<SpdySession
> session_privacy_enabled
=
3333 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_enabled
);
3335 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3336 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3338 // Add SpdySession with PrivacyMode Disabled to the pool.
3339 base::WeakPtr
<SpdySession
> session_privacy_disabled
=
3340 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_disabled
);
3342 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3343 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3345 session_privacy_enabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3346 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3347 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3349 session_privacy_disabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3350 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3351 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3354 // Delegate that creates another stream when its stream is closed.
3355 class StreamCreatingDelegate
: public test::StreamDelegateDoNothing
{
3357 StreamCreatingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3358 const base::WeakPtr
<SpdySession
>& session
)
3359 : StreamDelegateDoNothing(stream
),
3360 session_(session
) {}
3362 ~StreamCreatingDelegate() override
{}
3364 void OnClose(int status
) override
{
3365 GURL
url(kDefaultURL
);
3367 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3368 session_
, url
, MEDIUM
, BoundNetLog()));
3372 const base::WeakPtr
<SpdySession
> session_
;
3375 // Create another stream in response to a stream being reset. Nothing
3376 // should blow up. This is a regression test for
3377 // http://crbug.com/263690 .
3378 TEST_P(SpdySessionTest
, CreateStreamOnStreamReset
) {
3379 session_deps_
.host_resolver
->set_synchronous_mode(true);
3381 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3383 scoped_ptr
<SpdyFrame
> req(
3384 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
3385 MockWrite writes
[] = {
3386 CreateMockWrite(*req
, 0),
3389 scoped_ptr
<SpdyFrame
> rst(
3390 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
3391 MockRead reads
[] = {
3392 CreateMockRead(*rst
, 1),
3393 MockRead(ASYNC
, 0, 2) // EOF
3395 DeterministicSocketData
data(reads
, arraysize(reads
),
3396 writes
, arraysize(writes
));
3397 data
.set_connect_data(connect_data
);
3398 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3400 CreateDeterministicNetworkSession();
3402 base::WeakPtr
<SpdySession
> session
=
3403 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3405 GURL
url(kDefaultURL
);
3406 base::WeakPtr
<SpdyStream
> spdy_stream
=
3407 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3408 session
, url
, MEDIUM
, BoundNetLog());
3409 ASSERT_TRUE(spdy_stream
.get() != NULL
);
3410 EXPECT_EQ(0u, spdy_stream
->stream_id());
3412 StreamCreatingDelegate
delegate(spdy_stream
, session
);
3413 spdy_stream
->SetDelegate(&delegate
);
3415 scoped_ptr
<SpdyHeaderBlock
> headers(
3416 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
3417 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
3418 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
3420 EXPECT_EQ(0u, spdy_stream
->stream_id());
3424 EXPECT_EQ(1u, spdy_stream
->stream_id());
3426 // Cause the stream to be reset, which should cause another stream
3430 EXPECT_EQ(NULL
, spdy_stream
.get());
3431 EXPECT_TRUE(delegate
.StreamIsClosed());
3432 EXPECT_EQ(0u, session
->num_active_streams());
3433 EXPECT_EQ(1u, session
->num_created_streams());
3436 // The tests below are only for SPDY/3 and above.
3438 TEST_P(SpdySessionTest
, UpdateStreamsSendWindowSize
) {
3439 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3441 SettingsMap new_settings
;
3442 int32 window_size
= 1;
3443 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
3444 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, window_size
);
3446 // Set up the socket so we read a SETTINGS frame that sets
3447 // INITIAL_WINDOW_SIZE.
3448 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3449 scoped_ptr
<SpdyFrame
> settings_frame(
3450 spdy_util_
.ConstructSpdySettings(new_settings
));
3451 MockRead reads
[] = {
3452 CreateMockRead(*settings_frame
, 0),
3453 MockRead(ASYNC
, 0, 1) // EOF
3456 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
3457 MockWrite writes
[] = {
3458 CreateMockWrite(*settings_ack
, 2),
3461 session_deps_
.host_resolver
->set_synchronous_mode(true);
3463 DeterministicSocketData
data(reads
, arraysize(reads
),
3464 writes
, arraysize(writes
));
3465 data
.set_connect_data(connect_data
);
3466 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3468 CreateDeterministicNetworkSession();
3470 base::WeakPtr
<SpdySession
> session
=
3471 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3472 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3473 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3474 session
, test_url_
, MEDIUM
, BoundNetLog());
3475 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
3476 TestCompletionCallback callback1
;
3477 EXPECT_NE(spdy_stream1
->send_window_size(), window_size
);
3479 data
.RunFor(1); // Process the SETTINGS frame, but not the EOF
3480 base::MessageLoop::current()->RunUntilIdle();
3481 EXPECT_EQ(session
->stream_initial_send_window_size(), window_size
);
3482 EXPECT_EQ(spdy_stream1
->send_window_size(), window_size
);
3484 // Release the first one, this will allow the second to be created.
3485 spdy_stream1
->Cancel();
3486 EXPECT_EQ(NULL
, spdy_stream1
.get());
3488 base::WeakPtr
<SpdyStream
> spdy_stream2
=
3489 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3490 session
, test_url_
, MEDIUM
, BoundNetLog());
3491 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
3492 EXPECT_EQ(spdy_stream2
->send_window_size(), window_size
);
3493 spdy_stream2
->Cancel();
3494 EXPECT_EQ(NULL
, spdy_stream2
.get());
3497 // The tests below are only for SPDY/3.1 and above.
3499 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3500 // adjust the session receive window size for SPDY 3.1 and higher. In
3501 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3502 // sending a WINDOW_UPDATE frame for a large enough delta.
3503 TEST_P(SpdySessionTest
, AdjustRecvWindowSize
) {
3504 if (GetParam() < kProtoSPDY31
)
3507 session_deps_
.host_resolver
->set_synchronous_mode(true);
3509 const int32 initial_window_size
=
3510 SpdySession::GetInitialWindowSize(GetParam());
3511 const int32 delta_window_size
= 100;
3513 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3514 MockRead reads
[] = {
3515 MockRead(ASYNC
, 0, 1) // EOF
3517 scoped_ptr
<SpdyFrame
> window_update(spdy_util_
.ConstructSpdyWindowUpdate(
3518 kSessionFlowControlStreamId
, initial_window_size
+ delta_window_size
));
3519 MockWrite writes
[] = {
3520 CreateMockWrite(*window_update
, 0),
3522 DeterministicSocketData
data(reads
, arraysize(reads
),
3523 writes
, arraysize(writes
));
3524 data
.set_connect_data(connect_data
);
3525 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3527 CreateDeterministicNetworkSession();
3528 base::WeakPtr
<SpdySession
> session
=
3529 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3530 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3531 session
->flow_control_state());
3533 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3534 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3536 session
->IncreaseRecvWindowSize(delta_window_size
);
3537 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3538 session
->session_recv_window_size_
);
3539 EXPECT_EQ(delta_window_size
, session
->session_unacked_recv_window_bytes_
);
3541 // Should trigger sending a WINDOW_UPDATE frame.
3542 session
->IncreaseRecvWindowSize(initial_window_size
);
3543 EXPECT_EQ(initial_window_size
+ delta_window_size
+ initial_window_size
,
3544 session
->session_recv_window_size_
);
3545 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3549 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3550 session
->in_io_loop_
= true;
3551 session
->DecreaseRecvWindowSize(initial_window_size
+ delta_window_size
+
3552 initial_window_size
);
3553 session
->in_io_loop_
= false;
3554 EXPECT_EQ(0, session
->session_recv_window_size_
);
3555 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3558 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3559 // adjust the session send window size when the "enable_spdy_31" flag
3561 TEST_P(SpdySessionTest
, AdjustSendWindowSize
) {
3562 if (GetParam() < kProtoSPDY31
)
3565 session_deps_
.host_resolver
->set_synchronous_mode(true);
3567 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3568 MockRead reads
[] = {
3569 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3571 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3572 data
.set_connect_data(connect_data
);
3573 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3575 CreateNetworkSession();
3576 base::WeakPtr
<SpdySession
> session
=
3577 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3578 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3579 session
->flow_control_state());
3581 const int32 initial_window_size
=
3582 SpdySession::GetInitialWindowSize(GetParam());
3583 const int32 delta_window_size
= 100;
3585 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3587 session
->IncreaseSendWindowSize(delta_window_size
);
3588 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3589 session
->session_send_window_size_
);
3591 session
->DecreaseSendWindowSize(delta_window_size
);
3592 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3595 // Incoming data for an inactive stream should not cause the session
3596 // receive window size to decrease, but it should cause the unacked
3597 // bytes to increase.
3598 TEST_P(SpdySessionTest
, SessionFlowControlInactiveStream
) {
3599 if (GetParam() < kProtoSPDY31
)
3602 session_deps_
.host_resolver
->set_synchronous_mode(true);
3604 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3605 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(1, false));
3606 MockRead reads
[] = {
3607 CreateMockRead(*resp
, 0),
3608 MockRead(ASYNC
, 0, 1) // EOF
3610 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
3611 data
.set_connect_data(connect_data
);
3612 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3614 CreateDeterministicNetworkSession();
3615 base::WeakPtr
<SpdySession
> session
=
3616 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3617 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3618 session
->flow_control_state());
3620 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3621 session
->session_recv_window_size_
);
3622 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3626 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3627 session
->session_recv_window_size_
);
3628 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
3633 // The frame header is not included in flow control, but frame payload
3634 // (including optional pad length and padding) is.
3635 TEST_P(SpdySessionTest
, SessionFlowControlPadding
) {
3636 // Padding only exists in HTTP/2.
3637 if (GetParam() < kProtoSPDY4MinimumVersion
)
3640 session_deps_
.host_resolver
->set_synchronous_mode(true);
3642 const int padding_length
= 42;
3643 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3644 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(
3645 1, kUploadData
, kUploadDataSize
, false, padding_length
));
3646 MockRead reads
[] = {
3647 CreateMockRead(*resp
, 0), MockRead(ASYNC
, 0, 1) // EOF
3649 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
3650 data
.set_connect_data(connect_data
);
3651 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3653 CreateDeterministicNetworkSession();
3654 base::WeakPtr
<SpdySession
> session
=
3655 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3656 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3657 session
->flow_control_state());
3659 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3660 session
->session_recv_window_size_
);
3661 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3665 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3666 session
->session_recv_window_size_
);
3667 EXPECT_EQ(kUploadDataSize
+ padding_length
,
3668 session
->session_unacked_recv_window_bytes_
);
3673 // A delegate that drops any received data.
3674 class DropReceivedDataDelegate
: public test::StreamDelegateSendImmediate
{
3676 DropReceivedDataDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3677 base::StringPiece data
)
3678 : StreamDelegateSendImmediate(stream
, data
) {}
3680 ~DropReceivedDataDelegate() override
{}
3682 // Drop any received data.
3683 void OnDataReceived(scoped_ptr
<SpdyBuffer
> buffer
) override
{}
3686 // Send data back and forth but use a delegate that drops its received
3687 // data. The receive window should still increase to its original
3688 // value, i.e. we shouldn't "leak" receive window bytes.
3689 TEST_P(SpdySessionTest
, SessionFlowControlNoReceiveLeaks
) {
3690 if (GetParam() < kProtoSPDY31
)
3693 const char kStreamUrl
[] = "http://www.google.com/";
3695 const int32 msg_data_size
= 100;
3696 const std::string
msg_data(msg_data_size
, 'a');
3698 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3700 scoped_ptr
<SpdyFrame
> req(
3701 spdy_util_
.ConstructSpdyPost(
3702 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3703 scoped_ptr
<SpdyFrame
> msg(
3704 spdy_util_
.ConstructSpdyBodyFrame(
3705 1, msg_data
.data(), msg_data_size
, false));
3706 MockWrite writes
[] = {
3707 CreateMockWrite(*req
, 0),
3708 CreateMockWrite(*msg
, 2),
3711 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3712 scoped_ptr
<SpdyFrame
> echo(
3713 spdy_util_
.ConstructSpdyBodyFrame(
3714 1, msg_data
.data(), msg_data_size
, false));
3715 scoped_ptr
<SpdyFrame
> window_update(
3716 spdy_util_
.ConstructSpdyWindowUpdate(
3717 kSessionFlowControlStreamId
, msg_data_size
));
3718 MockRead reads
[] = {
3719 CreateMockRead(*resp
, 1),
3720 CreateMockRead(*echo
, 3),
3721 MockRead(ASYNC
, 0, 4) // EOF
3724 // Create SpdySession and SpdyStream and send the request.
3725 DeterministicSocketData
data(reads
, arraysize(reads
),
3726 writes
, arraysize(writes
));
3727 data
.set_connect_data(connect_data
);
3728 session_deps_
.host_resolver
->set_synchronous_mode(true);
3729 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3731 CreateDeterministicNetworkSession();
3733 base::WeakPtr
<SpdySession
> session
=
3734 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3736 GURL
url(kStreamUrl
);
3737 base::WeakPtr
<SpdyStream
> stream
=
3738 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3739 session
, url
, MEDIUM
, BoundNetLog());
3740 ASSERT_TRUE(stream
.get() != NULL
);
3741 EXPECT_EQ(0u, stream
->stream_id());
3743 DropReceivedDataDelegate
delegate(stream
, msg_data
);
3744 stream
->SetDelegate(&delegate
);
3746 scoped_ptr
<SpdyHeaderBlock
> headers(
3747 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3748 EXPECT_EQ(ERR_IO_PENDING
,
3749 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3750 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3752 const int32 initial_window_size
=
3753 SpdySession::GetInitialWindowSize(GetParam());
3754 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3755 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3759 EXPECT_TRUE(data
.at_write_eof());
3760 EXPECT_TRUE(data
.at_read_eof());
3762 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3763 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3766 EXPECT_EQ(NULL
, stream
.get());
3768 EXPECT_EQ(OK
, delegate
.WaitForClose());
3770 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3771 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3774 // Send data back and forth but close the stream before its data frame
3775 // can be written to the socket. The send window should then increase
3776 // to its original value, i.e. we shouldn't "leak" send window bytes.
3777 TEST_P(SpdySessionTest
, SessionFlowControlNoSendLeaks
) {
3778 if (GetParam() < kProtoSPDY31
)
3781 const char kStreamUrl
[] = "http://www.google.com/";
3783 const int32 msg_data_size
= 100;
3784 const std::string
msg_data(msg_data_size
, 'a');
3786 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3788 scoped_ptr
<SpdyFrame
> req(
3789 spdy_util_
.ConstructSpdyPost(
3790 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3791 MockWrite writes
[] = {
3792 CreateMockWrite(*req
, 0),
3795 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3796 MockRead reads
[] = {
3797 CreateMockRead(*resp
, 1),
3798 MockRead(ASYNC
, 0, 2) // EOF
3801 // Create SpdySession and SpdyStream and send the request.
3802 DeterministicSocketData
data(reads
, arraysize(reads
),
3803 writes
, arraysize(writes
));
3804 data
.set_connect_data(connect_data
);
3805 session_deps_
.host_resolver
->set_synchronous_mode(true);
3806 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3808 CreateDeterministicNetworkSession();
3810 base::WeakPtr
<SpdySession
> session
=
3811 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3813 GURL
url(kStreamUrl
);
3814 base::WeakPtr
<SpdyStream
> stream
=
3815 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3816 session
, url
, MEDIUM
, BoundNetLog());
3817 ASSERT_TRUE(stream
.get() != NULL
);
3818 EXPECT_EQ(0u, stream
->stream_id());
3820 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3821 stream
->SetDelegate(&delegate
);
3823 scoped_ptr
<SpdyHeaderBlock
> headers(
3824 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3825 EXPECT_EQ(ERR_IO_PENDING
,
3826 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3827 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3829 const int32 initial_window_size
=
3830 SpdySession::GetInitialWindowSize(GetParam());
3831 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3835 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3839 EXPECT_TRUE(data
.at_write_eof());
3840 EXPECT_TRUE(data
.at_read_eof());
3842 EXPECT_EQ(initial_window_size
- msg_data_size
,
3843 session
->session_send_window_size_
);
3845 // Closing the stream should increase the session's send window.
3847 EXPECT_EQ(NULL
, stream
.get());
3849 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3851 EXPECT_EQ(OK
, delegate
.WaitForClose());
3854 // Send data back and forth; the send and receive windows should
3855 // change appropriately.
3856 TEST_P(SpdySessionTest
, SessionFlowControlEndToEnd
) {
3857 if (GetParam() < kProtoSPDY31
)
3860 const char kStreamUrl
[] = "http://www.google.com/";
3862 const int32 msg_data_size
= 100;
3863 const std::string
msg_data(msg_data_size
, 'a');
3865 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3867 scoped_ptr
<SpdyFrame
> req(
3868 spdy_util_
.ConstructSpdyPost(
3869 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3870 scoped_ptr
<SpdyFrame
> msg(
3871 spdy_util_
.ConstructSpdyBodyFrame(
3872 1, msg_data
.data(), msg_data_size
, false));
3873 MockWrite writes
[] = {
3874 CreateMockWrite(*req
, 0),
3875 CreateMockWrite(*msg
, 2),
3878 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3879 scoped_ptr
<SpdyFrame
> echo(
3880 spdy_util_
.ConstructSpdyBodyFrame(
3881 1, msg_data
.data(), msg_data_size
, false));
3882 scoped_ptr
<SpdyFrame
> window_update(
3883 spdy_util_
.ConstructSpdyWindowUpdate(
3884 kSessionFlowControlStreamId
, msg_data_size
));
3885 MockRead reads
[] = {
3886 CreateMockRead(*resp
, 1),
3887 CreateMockRead(*echo
, 3),
3888 CreateMockRead(*window_update
, 4),
3889 MockRead(ASYNC
, 0, 5) // EOF
3892 // Create SpdySession and SpdyStream and send the request.
3893 DeterministicSocketData
data(reads
, arraysize(reads
),
3894 writes
, arraysize(writes
));
3895 data
.set_connect_data(connect_data
);
3896 session_deps_
.host_resolver
->set_synchronous_mode(true);
3897 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3899 CreateDeterministicNetworkSession();
3901 base::WeakPtr
<SpdySession
> session
=
3902 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3904 GURL
url(kStreamUrl
);
3905 base::WeakPtr
<SpdyStream
> stream
=
3906 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3907 session
, url
, MEDIUM
, BoundNetLog());
3908 ASSERT_TRUE(stream
.get() != NULL
);
3909 EXPECT_EQ(0u, stream
->stream_id());
3911 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3912 stream
->SetDelegate(&delegate
);
3914 scoped_ptr
<SpdyHeaderBlock
> headers(
3915 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3916 EXPECT_EQ(ERR_IO_PENDING
,
3917 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3918 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3920 const int32 initial_window_size
=
3921 SpdySession::GetInitialWindowSize(GetParam());
3922 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3923 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3924 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3928 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3929 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3930 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3934 EXPECT_EQ(initial_window_size
- msg_data_size
,
3935 session
->session_send_window_size_
);
3936 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3937 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3941 EXPECT_EQ(initial_window_size
- msg_data_size
,
3942 session
->session_send_window_size_
);
3943 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3944 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3948 EXPECT_EQ(initial_window_size
- msg_data_size
,
3949 session
->session_send_window_size_
);
3950 EXPECT_EQ(initial_window_size
- msg_data_size
,
3951 session
->session_recv_window_size_
);
3952 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3956 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3957 EXPECT_EQ(initial_window_size
- msg_data_size
,
3958 session
->session_recv_window_size_
);
3959 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3961 EXPECT_TRUE(data
.at_write_eof());
3962 EXPECT_TRUE(data
.at_read_eof());
3964 EXPECT_EQ(msg_data
, delegate
.TakeReceivedData());
3966 // Draining the delegate's read queue should increase the session's
3968 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3969 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3970 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3973 EXPECT_EQ(NULL
, stream
.get());
3975 EXPECT_EQ(OK
, delegate
.WaitForClose());
3977 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3978 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3979 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3982 // Given a stall function and an unstall function, runs a test to make
3983 // sure that a stream resumes after unstall.
3984 void SpdySessionTest::RunResumeAfterUnstallTest(
3985 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
3986 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
3988 const char kStreamUrl
[] = "http://www.google.com/";
3989 GURL
url(kStreamUrl
);
3991 session_deps_
.host_resolver
->set_synchronous_mode(true);
3993 scoped_ptr
<SpdyFrame
> req(
3994 spdy_util_
.ConstructSpdyPost(
3995 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
3996 scoped_ptr
<SpdyFrame
> body(
3997 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
3998 MockWrite writes
[] = {
3999 CreateMockWrite(*req
, 0),
4000 CreateMockWrite(*body
, 1),
4003 scoped_ptr
<SpdyFrame
> resp(
4004 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4005 scoped_ptr
<SpdyFrame
> echo(
4006 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4007 MockRead reads
[] = {
4008 CreateMockRead(*resp
, 2),
4009 MockRead(ASYNC
, 0, 0, 3), // EOF
4012 DeterministicSocketData
data(reads
, arraysize(reads
),
4013 writes
, arraysize(writes
));
4014 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4015 data
.set_connect_data(connect_data
);
4017 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4019 CreateDeterministicNetworkSession();
4020 base::WeakPtr
<SpdySession
> session
=
4021 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4022 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4023 session
->flow_control_state());
4025 base::WeakPtr
<SpdyStream
> stream
=
4026 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4027 session
, url
, LOWEST
, BoundNetLog());
4028 ASSERT_TRUE(stream
.get() != NULL
);
4030 test::StreamDelegateWithBody
delegate(stream
, kBodyDataStringPiece
);
4031 stream
->SetDelegate(&delegate
);
4033 EXPECT_FALSE(stream
->HasUrlFromHeaders());
4034 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4036 scoped_ptr
<SpdyHeaderBlock
> headers(
4037 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4038 EXPECT_EQ(ERR_IO_PENDING
,
4039 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
4040 EXPECT_TRUE(stream
->HasUrlFromHeaders());
4041 EXPECT_EQ(kStreamUrl
, stream
->GetUrlFromHeaders().spec());
4043 stall_function
.Run(session
.get(), stream
.get());
4047 EXPECT_TRUE(stream
->send_stalled_by_flow_control());
4049 unstall_function
.Run(session
.get(), stream
.get(), kBodyDataSize
);
4051 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4055 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
4057 EXPECT_TRUE(delegate
.send_headers_completed());
4058 EXPECT_EQ("200", delegate
.GetResponseHeaderValue(":status"));
4059 EXPECT_EQ(std::string(), delegate
.TakeReceivedData());
4060 EXPECT_TRUE(data
.at_write_eof());
4063 // Run the resume-after-unstall test with all possible stall and
4064 // unstall sequences.
4066 TEST_P(SpdySessionTest
, ResumeAfterUnstallSession
) {
4067 if (GetParam() < kProtoSPDY31
)
4070 RunResumeAfterUnstallTest(
4071 base::Bind(&SpdySessionTest::StallSessionOnly
,
4072 base::Unretained(this)),
4073 base::Bind(&SpdySessionTest::UnstallSessionOnly
,
4074 base::Unretained(this)));
4078 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4079 TEST_P(SpdySessionTest
, ResumeAfterUnstallStream
) {
4080 if (GetParam() < kProtoSPDY31
)
4083 RunResumeAfterUnstallTest(
4084 base::Bind(&SpdySessionTest::StallStreamOnly
,
4085 base::Unretained(this)),
4086 base::Bind(&SpdySessionTest::UnstallStreamOnly
,
4087 base::Unretained(this)));
4090 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallSessionStream
) {
4091 if (GetParam() < kProtoSPDY31
)
4094 RunResumeAfterUnstallTest(
4095 base::Bind(&SpdySessionTest::StallSessionStream
,
4096 base::Unretained(this)),
4097 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4098 base::Unretained(this)));
4101 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallSessionStream
) {
4102 if (GetParam() < kProtoSPDY31
)
4105 RunResumeAfterUnstallTest(
4106 base::Bind(&SpdySessionTest::StallStreamSession
,
4107 base::Unretained(this)),
4108 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4109 base::Unretained(this)));
4112 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallStreamSession
) {
4113 if (GetParam() < kProtoSPDY31
)
4116 RunResumeAfterUnstallTest(
4117 base::Bind(&SpdySessionTest::StallStreamSession
,
4118 base::Unretained(this)),
4119 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4120 base::Unretained(this)));
4123 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallStreamSession
) {
4124 if (GetParam() < kProtoSPDY31
)
4127 RunResumeAfterUnstallTest(
4128 base::Bind(&SpdySessionTest::StallSessionStream
,
4129 base::Unretained(this)),
4130 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4131 base::Unretained(this)));
4134 // Cause a stall by reducing the flow control send window to 0. The
4135 // streams should resume in priority order when that window is then
4137 TEST_P(SpdySessionTest
, ResumeByPriorityAfterSendWindowSizeIncrease
) {
4138 if (GetParam() < kProtoSPDY31
)
4141 const char kStreamUrl
[] = "http://www.google.com/";
4142 GURL
url(kStreamUrl
);
4144 session_deps_
.host_resolver
->set_synchronous_mode(true);
4146 scoped_ptr
<SpdyFrame
> req1(
4147 spdy_util_
.ConstructSpdyPost(
4148 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4149 scoped_ptr
<SpdyFrame
> req2(
4150 spdy_util_
.ConstructSpdyPost(
4151 kStreamUrl
, 3, kBodyDataSize
, MEDIUM
, NULL
, 0));
4152 scoped_ptr
<SpdyFrame
> body1(
4153 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
4154 scoped_ptr
<SpdyFrame
> body2(
4155 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4156 MockWrite writes
[] = {
4157 CreateMockWrite(*req1
, 0),
4158 CreateMockWrite(*req2
, 1),
4159 CreateMockWrite(*body2
, 2),
4160 CreateMockWrite(*body1
, 3),
4163 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4164 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4165 MockRead reads
[] = {
4166 CreateMockRead(*resp1
, 4),
4167 CreateMockRead(*resp2
, 5),
4168 MockRead(ASYNC
, 0, 0, 6), // EOF
4171 DeterministicSocketData
data(reads
, arraysize(reads
),
4172 writes
, arraysize(writes
));
4173 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4174 data
.set_connect_data(connect_data
);
4176 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4178 CreateDeterministicNetworkSession();
4179 base::WeakPtr
<SpdySession
> session
=
4180 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4181 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4182 session
->flow_control_state());
4184 base::WeakPtr
<SpdyStream
> stream1
=
4185 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4186 session
, url
, LOWEST
, BoundNetLog());
4187 ASSERT_TRUE(stream1
.get() != NULL
);
4189 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4190 stream1
->SetDelegate(&delegate1
);
4192 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4194 base::WeakPtr
<SpdyStream
> stream2
=
4195 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4196 session
, url
, MEDIUM
, BoundNetLog());
4197 ASSERT_TRUE(stream2
.get() != NULL
);
4199 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4200 stream2
->SetDelegate(&delegate2
);
4202 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4204 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4205 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4207 StallSessionSend(session
.get());
4209 scoped_ptr
<SpdyHeaderBlock
> headers1(
4210 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4211 EXPECT_EQ(ERR_IO_PENDING
,
4212 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4213 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4214 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4217 EXPECT_EQ(1u, stream1
->stream_id());
4218 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4220 scoped_ptr
<SpdyHeaderBlock
> headers2(
4221 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4222 EXPECT_EQ(ERR_IO_PENDING
,
4223 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4224 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4225 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4228 EXPECT_EQ(3u, stream2
->stream_id());
4229 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4231 // This should unstall only stream2.
4232 UnstallSessionSend(session
.get(), kBodyDataSize
);
4234 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4235 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4239 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4240 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4242 // This should then unstall stream1.
4243 UnstallSessionSend(session
.get(), kBodyDataSize
);
4245 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4246 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4250 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4251 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4253 EXPECT_TRUE(delegate1
.send_headers_completed());
4254 EXPECT_EQ("200", delegate1
.GetResponseHeaderValue(":status"));
4255 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4257 EXPECT_TRUE(delegate2
.send_headers_completed());
4258 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4259 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4261 EXPECT_TRUE(data
.at_write_eof());
4264 // Delegate that closes a given stream after sending its body.
4265 class StreamClosingDelegate
: public test::StreamDelegateWithBody
{
4267 StreamClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
4268 base::StringPiece data
)
4269 : StreamDelegateWithBody(stream
, data
) {}
4271 ~StreamClosingDelegate() override
{}
4273 void set_stream_to_close(const base::WeakPtr
<SpdyStream
>& stream_to_close
) {
4274 stream_to_close_
= stream_to_close
;
4277 void OnDataSent() override
{
4278 test::StreamDelegateWithBody::OnDataSent();
4279 if (stream_to_close_
.get()) {
4280 stream_to_close_
->Close();
4281 EXPECT_EQ(NULL
, stream_to_close_
.get());
4286 base::WeakPtr
<SpdyStream
> stream_to_close_
;
4289 // Cause a stall by reducing the flow control send window to
4290 // 0. Unstalling the session should properly handle deleted streams.
4291 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedStreams
) {
4292 if (GetParam() < kProtoSPDY31
)
4295 const char kStreamUrl
[] = "http://www.google.com/";
4296 GURL
url(kStreamUrl
);
4298 session_deps_
.host_resolver
->set_synchronous_mode(true);
4300 scoped_ptr
<SpdyFrame
> req1(
4301 spdy_util_
.ConstructSpdyPost(
4302 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4303 scoped_ptr
<SpdyFrame
> req2(
4304 spdy_util_
.ConstructSpdyPost(
4305 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, NULL
, 0));
4306 scoped_ptr
<SpdyFrame
> req3(
4307 spdy_util_
.ConstructSpdyPost(
4308 kStreamUrl
, 5, kBodyDataSize
, LOWEST
, NULL
, 0));
4309 scoped_ptr
<SpdyFrame
> body2(
4310 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4311 MockWrite writes
[] = {
4312 CreateMockWrite(*req1
, 0),
4313 CreateMockWrite(*req2
, 1),
4314 CreateMockWrite(*req3
, 2),
4315 CreateMockWrite(*body2
, 3),
4318 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4319 MockRead reads
[] = {
4320 CreateMockRead(*resp2
, 4),
4321 MockRead(ASYNC
, 0, 0, 5), // EOF
4324 DeterministicSocketData
data(reads
, arraysize(reads
),
4325 writes
, arraysize(writes
));
4326 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4327 data
.set_connect_data(connect_data
);
4329 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4331 CreateDeterministicNetworkSession();
4332 base::WeakPtr
<SpdySession
> session
=
4333 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4334 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4335 session
->flow_control_state());
4337 base::WeakPtr
<SpdyStream
> stream1
=
4338 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4339 session
, url
, LOWEST
, BoundNetLog());
4340 ASSERT_TRUE(stream1
.get() != NULL
);
4342 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4343 stream1
->SetDelegate(&delegate1
);
4345 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4347 base::WeakPtr
<SpdyStream
> stream2
=
4348 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4349 session
, url
, LOWEST
, BoundNetLog());
4350 ASSERT_TRUE(stream2
.get() != NULL
);
4352 StreamClosingDelegate
delegate2(stream2
, kBodyDataStringPiece
);
4353 stream2
->SetDelegate(&delegate2
);
4355 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4357 base::WeakPtr
<SpdyStream
> stream3
=
4358 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4359 session
, url
, LOWEST
, BoundNetLog());
4360 ASSERT_TRUE(stream3
.get() != NULL
);
4362 test::StreamDelegateWithBody
delegate3(stream3
, kBodyDataStringPiece
);
4363 stream3
->SetDelegate(&delegate3
);
4365 EXPECT_FALSE(stream3
->HasUrlFromHeaders());
4367 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4368 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4369 EXPECT_FALSE(stream3
->send_stalled_by_flow_control());
4371 StallSessionSend(session
.get());
4373 scoped_ptr
<SpdyHeaderBlock
> headers1(
4374 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4375 EXPECT_EQ(ERR_IO_PENDING
,
4376 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4377 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4378 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4381 EXPECT_EQ(1u, stream1
->stream_id());
4382 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4384 scoped_ptr
<SpdyHeaderBlock
> headers2(
4385 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4386 EXPECT_EQ(ERR_IO_PENDING
,
4387 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4388 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4389 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4392 EXPECT_EQ(3u, stream2
->stream_id());
4393 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4395 scoped_ptr
<SpdyHeaderBlock
> headers3(
4396 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4397 EXPECT_EQ(ERR_IO_PENDING
,
4398 stream3
->SendRequestHeaders(headers3
.Pass(), MORE_DATA_TO_SEND
));
4399 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
4400 EXPECT_EQ(kStreamUrl
, stream3
->GetUrlFromHeaders().spec());
4403 EXPECT_EQ(5u, stream3
->stream_id());
4404 EXPECT_TRUE(stream3
->send_stalled_by_flow_control());
4406 SpdyStreamId stream_id1
= stream1
->stream_id();
4407 SpdyStreamId stream_id2
= stream2
->stream_id();
4408 SpdyStreamId stream_id3
= stream3
->stream_id();
4410 // Close stream1 preemptively.
4411 session
->CloseActiveStream(stream_id1
, ERR_CONNECTION_CLOSED
);
4412 EXPECT_EQ(NULL
, stream1
.get());
4414 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4415 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4416 EXPECT_TRUE(session
->IsStreamActive(stream_id3
));
4418 // Unstall stream2, which should then close stream3.
4419 delegate2
.set_stream_to_close(stream3
);
4420 UnstallSessionSend(session
.get(), kBodyDataSize
);
4423 EXPECT_EQ(NULL
, stream3
.get());
4425 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4426 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4427 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4428 EXPECT_FALSE(session
->IsStreamActive(stream_id3
));
4431 EXPECT_EQ(NULL
, stream2
.get());
4433 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4434 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4435 EXPECT_EQ(OK
, delegate3
.WaitForClose());
4437 EXPECT_TRUE(delegate1
.send_headers_completed());
4438 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4440 EXPECT_TRUE(delegate2
.send_headers_completed());
4441 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4442 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4444 EXPECT_TRUE(delegate3
.send_headers_completed());
4445 EXPECT_EQ(std::string(), delegate3
.TakeReceivedData());
4447 EXPECT_TRUE(data
.at_write_eof());
4450 // Cause a stall by reducing the flow control send window to
4451 // 0. Unstalling the session should properly handle the session itself
4453 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedSession
) {
4454 if (GetParam() < kProtoSPDY31
)
4457 const char kStreamUrl
[] = "http://www.google.com/";
4458 GURL
url(kStreamUrl
);
4460 session_deps_
.host_resolver
->set_synchronous_mode(true);
4462 scoped_ptr
<SpdyFrame
> req1(
4463 spdy_util_
.ConstructSpdyPost(
4464 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4465 scoped_ptr
<SpdyFrame
> req2(
4466 spdy_util_
.ConstructSpdyPost(
4467 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, NULL
, 0));
4468 scoped_ptr
<SpdyFrame
> body1(
4469 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4470 MockWrite writes
[] = {
4471 CreateMockWrite(*req1
, 0),
4472 CreateMockWrite(*req2
, 1),
4475 MockRead reads
[] = {
4476 MockRead(ASYNC
, 0, 0, 2), // EOF
4479 DeterministicSocketData
data(reads
, arraysize(reads
),
4480 writes
, arraysize(writes
));
4481 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4482 data
.set_connect_data(connect_data
);
4484 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4486 CreateDeterministicNetworkSession();
4487 base::WeakPtr
<SpdySession
> session
=
4488 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4489 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4490 session
->flow_control_state());
4492 base::WeakPtr
<SpdyStream
> stream1
=
4493 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4494 session
, url
, LOWEST
, BoundNetLog());
4495 ASSERT_TRUE(stream1
.get() != NULL
);
4497 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4498 stream1
->SetDelegate(&delegate1
);
4500 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4502 base::WeakPtr
<SpdyStream
> stream2
=
4503 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4504 session
, url
, LOWEST
, BoundNetLog());
4505 ASSERT_TRUE(stream2
.get() != NULL
);
4507 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4508 stream2
->SetDelegate(&delegate2
);
4510 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4512 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4513 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4515 StallSessionSend(session
.get());
4517 scoped_ptr
<SpdyHeaderBlock
> headers1(
4518 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4519 EXPECT_EQ(ERR_IO_PENDING
,
4520 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4521 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4522 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4525 EXPECT_EQ(1u, stream1
->stream_id());
4526 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4528 scoped_ptr
<SpdyHeaderBlock
> headers2(
4529 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4530 EXPECT_EQ(ERR_IO_PENDING
,
4531 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4532 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4533 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4536 EXPECT_EQ(3u, stream2
->stream_id());
4537 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4539 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
4542 UnstallSessionSend(session
.get(), kBodyDataSize
);
4544 // Close the session (since we can't do it from within the delegate
4545 // method, since it's in the stream's loop).
4546 session
->CloseSessionOnError(ERR_CONNECTION_CLOSED
, "Closing session");
4547 base::RunLoop().RunUntilIdle();
4548 EXPECT_TRUE(session
== NULL
);
4550 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
4552 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4553 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4555 EXPECT_TRUE(delegate1
.send_headers_completed());
4556 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4558 EXPECT_TRUE(delegate2
.send_headers_completed());
4559 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4561 EXPECT_TRUE(data
.at_write_eof());
4564 TEST_P(SpdySessionTest
, GoAwayOnSessionFlowControlError
) {
4565 if (GetParam() < kProtoSPDY31
)
4568 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4570 scoped_ptr
<SpdyFrame
> req(
4571 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4572 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
4574 GOAWAY_FLOW_CONTROL_ERROR
,
4575 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4576 "the receive window size of 1"));
4577 MockWrite writes
[] = {
4578 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 3),
4581 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4582 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4583 MockRead reads
[] = {
4584 CreateMockRead(*resp
, 1), CreateMockRead(*body
, 2),
4587 DeterministicSocketData
data(
4588 reads
, arraysize(reads
), writes
, arraysize(writes
));
4589 data
.set_connect_data(connect_data
);
4590 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4592 CreateDeterministicNetworkSession();
4594 base::WeakPtr
<SpdySession
> session
=
4595 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4597 GURL
url(kDefaultURL
);
4598 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
4599 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, LOWEST
, BoundNetLog());
4600 ASSERT_TRUE(spdy_stream
.get() != NULL
);
4601 test::StreamDelegateDoNothing
delegate(spdy_stream
);
4602 spdy_stream
->SetDelegate(&delegate
);
4604 scoped_ptr
<SpdyHeaderBlock
> headers(
4605 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
4606 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4608 data
.RunFor(1); // Write request.
4610 // Put session on the edge of overflowing it's recv window.
4611 session
->session_recv_window_size_
= 1;
4613 // Read response headers & body. Body overflows the session window, and a
4614 // goaway is written.
4616 base::MessageLoop::current()->RunUntilIdle();
4618 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR
, delegate
.WaitForClose());
4619 EXPECT_TRUE(session
== NULL
);
4622 TEST_P(SpdySessionTest
, SplitHeaders
) {
4623 GURL
kStreamUrl("http://www.google.com/foo.dat");
4624 SpdyHeaderBlock headers
;
4625 spdy_util_
.AddUrlToHeaderBlock(kStreamUrl
.spec(), &headers
);
4626 headers
["alpha"] = "beta";
4628 SpdyHeaderBlock request_headers
;
4629 SpdyHeaderBlock response_headers
;
4631 SplitPushedHeadersToRequestAndResponse(
4632 headers
, spdy_util_
.spdy_version(), &request_headers
, &response_headers
);
4634 SpdyHeaderBlock::const_iterator it
= response_headers
.find("alpha");
4635 std::string alpha_val
=
4636 (it
== response_headers
.end()) ? std::string() : it
->second
;
4637 EXPECT_EQ("beta", alpha_val
);
4640 GetUrlFromHeaderBlock(request_headers
, spdy_util_
.spdy_version(), true);
4641 EXPECT_EQ(kStreamUrl
, request_url
);
4644 // Regression. Sorta. Push streams and client streams were sharing a single
4645 // limit for a long time.
4646 TEST_P(SpdySessionTest
, PushedStreamShouldNotCountToClientConcurrencyLimit
) {
4647 SettingsMap new_settings
;
4648 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4649 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, 2);
4650 scoped_ptr
<SpdyFrame
> settings_frame(
4651 spdy_util_
.ConstructSpdySettings(new_settings
));
4652 scoped_ptr
<SpdyFrame
> pushed(spdy_util_
.ConstructSpdyPush(
4653 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4654 MockRead reads
[] = {
4655 CreateMockRead(*settings_frame
), CreateMockRead(*pushed
, 3),
4656 MockRead(ASYNC
, 0, 4),
4659 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
4660 scoped_ptr
<SpdyFrame
> req(
4661 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4662 MockWrite writes
[] = {
4663 CreateMockWrite(*settings_ack
, 1), CreateMockWrite(*req
, 2),
4666 DeterministicSocketData
data(
4667 reads
, arraysize(reads
), writes
, arraysize(writes
));
4668 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4669 data
.set_connect_data(connect_data
);
4670 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4672 CreateDeterministicNetworkSession();
4674 base::WeakPtr
<SpdySession
> session
=
4675 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4677 // Read the settings frame.
4680 GURL
url1(kDefaultURL
);
4681 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4682 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4683 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4684 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4685 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4686 spdy_stream1
->SetDelegate(&delegate1
);
4688 EXPECT_EQ(0u, session
->num_active_streams());
4689 EXPECT_EQ(1u, session
->num_created_streams());
4690 EXPECT_EQ(0u, session
->num_pushed_streams());
4691 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4693 scoped_ptr
<SpdyHeaderBlock
> headers(
4694 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4695 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4696 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4698 // Run until 1st stream is activated.
4699 EXPECT_EQ(0u, delegate1
.stream_id());
4701 EXPECT_EQ(1u, delegate1
.stream_id());
4702 EXPECT_EQ(1u, session
->num_active_streams());
4703 EXPECT_EQ(0u, session
->num_created_streams());
4704 EXPECT_EQ(0u, session
->num_pushed_streams());
4705 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4707 // Run until pushed stream is created.
4709 EXPECT_EQ(2u, session
->num_active_streams());
4710 EXPECT_EQ(0u, session
->num_created_streams());
4711 EXPECT_EQ(1u, session
->num_pushed_streams());
4712 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4714 // Second stream should not be stalled, although we have 2 active streams, but
4715 // one of them is push stream and should not be taken into account when we
4716 // create streams on the client.
4717 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
4718 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4719 EXPECT_TRUE(spdy_stream2
.get() != NULL
);
4720 EXPECT_EQ(2u, session
->num_active_streams());
4721 EXPECT_EQ(1u, session
->num_created_streams());
4722 EXPECT_EQ(1u, session
->num_pushed_streams());
4723 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4729 TEST_P(SpdySessionTest
, RejectPushedStreamExceedingConcurrencyLimit
) {
4730 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4731 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4732 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
4733 NULL
, 0, 4, 1, "http://www.google.com/b.dat"));
4734 MockRead reads
[] = {
4735 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
4736 MockRead(ASYNC
, 0, 4),
4739 scoped_ptr
<SpdyFrame
> req(
4740 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4741 scoped_ptr
<SpdyFrame
> rst(
4742 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4743 MockWrite writes
[] = {
4744 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 3),
4747 DeterministicSocketData
data(
4748 reads
, arraysize(reads
), writes
, arraysize(writes
));
4749 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4750 data
.set_connect_data(connect_data
);
4751 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4753 CreateDeterministicNetworkSession();
4755 base::WeakPtr
<SpdySession
> session
=
4756 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4757 session
->set_max_concurrent_pushed_streams(1);
4759 GURL
url1(kDefaultURL
);
4760 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4761 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4762 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4763 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4764 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4765 spdy_stream1
->SetDelegate(&delegate1
);
4767 EXPECT_EQ(0u, session
->num_active_streams());
4768 EXPECT_EQ(1u, session
->num_created_streams());
4769 EXPECT_EQ(0u, session
->num_pushed_streams());
4770 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4772 scoped_ptr
<SpdyHeaderBlock
> headers(
4773 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4774 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4775 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4777 // Run until 1st stream is activated.
4778 EXPECT_EQ(0u, delegate1
.stream_id());
4780 EXPECT_EQ(1u, delegate1
.stream_id());
4781 EXPECT_EQ(1u, session
->num_active_streams());
4782 EXPECT_EQ(0u, session
->num_created_streams());
4783 EXPECT_EQ(0u, session
->num_pushed_streams());
4784 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4786 // Run until pushed stream is created.
4788 EXPECT_EQ(2u, session
->num_active_streams());
4789 EXPECT_EQ(0u, session
->num_created_streams());
4790 EXPECT_EQ(1u, session
->num_pushed_streams());
4791 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4793 // Reset incoming pushed stream.
4795 EXPECT_EQ(2u, session
->num_active_streams());
4796 EXPECT_EQ(0u, session
->num_created_streams());
4797 EXPECT_EQ(1u, session
->num_pushed_streams());
4798 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4804 TEST_P(SpdySessionTest
, IgnoreReservedRemoteStreamsCount
) {
4805 // Streams in reserved remote state exist only in SPDY4.
4806 if (spdy_util_
.spdy_version() < SPDY4
)
4809 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4810 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4811 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4812 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/b.dat",
4813 push_headers
.get());
4814 scoped_ptr
<SpdyFrame
> push_b(
4815 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 4, 1));
4816 scoped_ptr
<SpdyFrame
> headers_b(
4817 spdy_util_
.ConstructSpdyPushHeaders(4, NULL
, 0));
4818 MockRead reads
[] = {
4819 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
4820 CreateMockRead(*headers_b
, 3), MockRead(ASYNC
, 0, 5),
4823 scoped_ptr
<SpdyFrame
> req(
4824 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4825 scoped_ptr
<SpdyFrame
> rst(
4826 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4827 MockWrite writes
[] = {
4828 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 4),
4831 DeterministicSocketData
data(
4832 reads
, arraysize(reads
), writes
, arraysize(writes
));
4833 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4834 data
.set_connect_data(connect_data
);
4835 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4837 CreateDeterministicNetworkSession();
4839 base::WeakPtr
<SpdySession
> session
=
4840 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4841 session
->set_max_concurrent_pushed_streams(1);
4843 GURL
url1(kDefaultURL
);
4844 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4845 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4846 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4847 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4848 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4849 spdy_stream1
->SetDelegate(&delegate1
);
4851 EXPECT_EQ(0u, session
->num_active_streams());
4852 EXPECT_EQ(1u, session
->num_created_streams());
4853 EXPECT_EQ(0u, session
->num_pushed_streams());
4854 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4856 scoped_ptr
<SpdyHeaderBlock
> headers(
4857 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4858 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4859 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4861 // Run until 1st stream is activated.
4862 EXPECT_EQ(0u, delegate1
.stream_id());
4864 EXPECT_EQ(1u, delegate1
.stream_id());
4865 EXPECT_EQ(1u, session
->num_active_streams());
4866 EXPECT_EQ(0u, session
->num_created_streams());
4867 EXPECT_EQ(0u, session
->num_pushed_streams());
4868 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4870 // Run until pushed stream is created.
4872 EXPECT_EQ(2u, session
->num_active_streams());
4873 EXPECT_EQ(0u, session
->num_created_streams());
4874 EXPECT_EQ(1u, session
->num_pushed_streams());
4875 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4877 // Accept promised stream. It should not count towards pushed stream limit.
4879 EXPECT_EQ(3u, session
->num_active_streams());
4880 EXPECT_EQ(0u, session
->num_created_streams());
4881 EXPECT_EQ(2u, session
->num_pushed_streams());
4882 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4884 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4885 // while we accept only one.
4887 EXPECT_EQ(2u, session
->num_active_streams());
4888 EXPECT_EQ(0u, session
->num_created_streams());
4889 EXPECT_EQ(1u, session
->num_pushed_streams());
4890 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4896 TEST_P(SpdySessionTest
, CancelReservedStreamOnHeadersReceived
) {
4897 // Streams in reserved remote state exist only in SPDY4.
4898 if (spdy_util_
.spdy_version() < SPDY4
)
4901 const char kPushedUrl
[] = "http://www.google.com/a.dat";
4902 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4903 spdy_util_
.AddUrlToHeaderBlock(kPushedUrl
, push_headers
.get());
4904 scoped_ptr
<SpdyFrame
> push_promise(
4905 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 2, 1));
4906 scoped_ptr
<SpdyFrame
> headers_frame(
4907 spdy_util_
.ConstructSpdyPushHeaders(2, NULL
, 0));
4908 MockRead reads
[] = {
4909 CreateMockRead(*push_promise
, 1), CreateMockRead(*headers_frame
, 2),
4910 MockRead(ASYNC
, 0, 4),
4913 scoped_ptr
<SpdyFrame
> req(
4914 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4915 scoped_ptr
<SpdyFrame
> rst(
4916 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
4917 MockWrite writes
[] = {
4918 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 3),
4921 DeterministicSocketData
data(
4922 reads
, arraysize(reads
), writes
, arraysize(writes
));
4923 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4924 data
.set_connect_data(connect_data
);
4925 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4927 CreateDeterministicNetworkSession();
4929 base::WeakPtr
<SpdySession
> session
=
4930 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4932 GURL
url1(kDefaultURL
);
4933 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4934 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4935 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4936 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4937 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4938 spdy_stream1
->SetDelegate(&delegate1
);
4940 EXPECT_EQ(0u, session
->num_active_streams());
4941 EXPECT_EQ(1u, session
->num_created_streams());
4942 EXPECT_EQ(0u, session
->num_pushed_streams());
4943 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4945 scoped_ptr
<SpdyHeaderBlock
> headers(
4946 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4947 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4948 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4950 // Run until 1st stream is activated.
4951 EXPECT_EQ(0u, delegate1
.stream_id());
4953 EXPECT_EQ(1u, delegate1
.stream_id());
4954 EXPECT_EQ(1u, session
->num_active_streams());
4955 EXPECT_EQ(0u, session
->num_created_streams());
4956 EXPECT_EQ(0u, session
->num_pushed_streams());
4957 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4959 // Run until pushed stream is created.
4961 EXPECT_EQ(2u, session
->num_active_streams());
4962 EXPECT_EQ(0u, session
->num_created_streams());
4963 EXPECT_EQ(1u, session
->num_pushed_streams());
4964 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4966 base::WeakPtr
<SpdyStream
> pushed_stream
;
4968 session
->GetPushStream(GURL(kPushedUrl
), &pushed_stream
, BoundNetLog());
4970 ASSERT_TRUE(pushed_stream
.get() != NULL
);
4971 test::StreamDelegateCloseOnHeaders
delegate2(pushed_stream
);
4972 pushed_stream
->SetDelegate(&delegate2
);
4974 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4975 // that all our counters are in consistent state.
4977 EXPECT_EQ(1u, session
->num_active_streams());
4978 EXPECT_EQ(0u, session
->num_created_streams());
4979 EXPECT_EQ(0u, session
->num_pushed_streams());
4980 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4986 TEST_P(SpdySessionTest
, RejectInvalidUnknownFrames
) {
4987 session_deps_
.host_resolver
->set_synchronous_mode(true);
4989 MockRead reads
[] = {
4990 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
4993 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
4995 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4996 data
.set_connect_data(connect_data
);
4997 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4999 CreateNetworkSession();
5000 base::WeakPtr
<SpdySession
> session
=
5001 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
5003 session
->stream_hi_water_mark_
= 5;
5004 // Low client (odd) ids are fine.
5005 EXPECT_TRUE(session
->OnUnknownFrame(3, 0));
5006 // Client id exceeding watermark.
5007 EXPECT_FALSE(session
->OnUnknownFrame(9, 0));
5009 session
->last_accepted_push_stream_id_
= 6;
5010 // Low server (even) ids are fine.
5011 EXPECT_TRUE(session
->OnUnknownFrame(2, 0));
5012 // Server id exceeding last accepted id.
5013 EXPECT_FALSE(session
->OnUnknownFrame(8, 0));
5016 TEST(MapFramerErrorToProtocolError
, MapsValues
) {
5018 SPDY_ERROR_INVALID_CONTROL_FRAME
,
5019 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
5021 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS
,
5022 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
5024 SPDY_ERROR_GOAWAY_FRAME_CORRUPT
,
5025 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT
));
5026 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME
,
5027 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME
));
5030 TEST(MapFramerErrorToNetError
, MapsValue
) {
5031 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR
,
5032 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
5033 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
5034 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE
));
5035 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
5036 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE
));
5038 ERR_SPDY_FRAME_SIZE_ERROR
,
5039 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
));
5042 TEST(MapRstStreamStatusToProtocolError
, MapsValues
) {
5043 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR
,
5044 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR
));
5045 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR
,
5046 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR
));
5047 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM
,
5048 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM
));
5049 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY
,
5050 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY
));
5051 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED
,
5052 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED
));
5055 TEST(MapNetErrorToGoAwayStatus
, MapsValue
) {
5056 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY
,
5057 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
));
5058 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR
,
5059 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR
));
5060 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
,
5061 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR
));
5062 CHECK_EQ(GOAWAY_COMPRESSION_ERROR
,
5063 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR
));
5064 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR
,
5065 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR
));
5066 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED
));
5069 TEST(CanPoolTest
, CanPool
) {
5070 // Load a cert that is valid for:
5075 TransportSecurityState tss
;
5077 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5078 "spdy_pooling.pem");
5080 EXPECT_TRUE(SpdySession::CanPool(
5081 &tss
, ssl_info
, "www.example.org", "www.example.org"));
5082 EXPECT_TRUE(SpdySession::CanPool(
5083 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5084 EXPECT_TRUE(SpdySession::CanPool(
5085 &tss
, ssl_info
, "www.example.org", "mail.example.com"));
5086 EXPECT_FALSE(SpdySession::CanPool(
5087 &tss
, ssl_info
, "www.example.org", "mail.google.com"));
5090 TEST(CanPoolTest
, CanNotPoolWithCertErrors
) {
5091 // Load a cert that is valid for:
5096 TransportSecurityState tss
;
5098 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5099 "spdy_pooling.pem");
5100 ssl_info
.cert_status
= CERT_STATUS_REVOKED
;
5102 EXPECT_FALSE(SpdySession::CanPool(
5103 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5106 TEST(CanPoolTest
, CanNotPoolWithClientCerts
) {
5107 // Load a cert that is valid for:
5112 TransportSecurityState tss
;
5114 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5115 "spdy_pooling.pem");
5116 ssl_info
.client_cert_sent
= true;
5118 EXPECT_FALSE(SpdySession::CanPool(
5119 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5122 TEST(CanPoolTest
, CanNotPoolAcrossETLDsWithChannelID
) {
5123 // Load a cert that is valid for:
5128 TransportSecurityState tss
;
5130 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5131 "spdy_pooling.pem");
5132 ssl_info
.channel_id_sent
= true;
5134 EXPECT_TRUE(SpdySession::CanPool(
5135 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5136 EXPECT_FALSE(SpdySession::CanPool(
5137 &tss
, ssl_info
, "www.example.org", "www.example.com"));
5140 TEST(CanPoolTest
, CanNotPoolWithBadPins
) {
5141 uint8 primary_pin
= 1;
5142 uint8 backup_pin
= 2;
5144 TransportSecurityState tss
;
5145 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5148 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5149 "spdy_pooling.pem");
5150 ssl_info
.is_issued_by_known_root
= true;
5151 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(bad_pin
));
5153 EXPECT_FALSE(SpdySession::CanPool(
5154 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5157 TEST(CanPoolTest
, CanPoolWithAcceptablePins
) {
5158 uint8 primary_pin
= 1;
5159 uint8 backup_pin
= 2;
5160 TransportSecurityState tss
;
5161 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5164 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5165 "spdy_pooling.pem");
5166 ssl_info
.is_issued_by_known_root
= true;
5167 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(primary_pin
));
5169 EXPECT_TRUE(SpdySession::CanPool(
5170 &tss
, ssl_info
, "www.example.org", "mail.example.org"));