1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/spdy/spdy_session.h"
7 #include "base/base64.h"
9 #include "base/callback.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/test/histogram_tester.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/ip_endpoint.h"
15 #include "net/base/request_priority.h"
16 #include "net/base/test_data_directory.h"
17 #include "net/base/test_data_stream.h"
18 #include "net/log/net_log_unittest.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 settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1545 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
1546 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1547 scoped_ptr
<SpdyFrame
> settings_frame(
1548 spdy_util_
.ConstructSpdySettings(settings
));
1549 std::vector
<MockWrite
> writes
;
1550 if ((GetParam() >= kProtoSPDY4MinimumVersion
) &&
1551 (GetParam() <= kProtoSPDY4MaximumVersion
)) {
1554 kHttp2ConnectionHeaderPrefix
,
1555 kHttp2ConnectionHeaderPrefixSize
));
1557 writes
.push_back(CreateMockWrite(*settings_frame
));
1559 SettingsMap server_settings
;
1560 const uint32 initial_max_concurrent_streams
= 1;
1561 server_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1562 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED
,
1563 initial_max_concurrent_streams
);
1564 scoped_ptr
<SpdyFrame
> server_settings_frame(
1565 spdy_util_
.ConstructSpdySettings(server_settings
));
1566 if (GetParam() <= kProtoSPDY31
) {
1567 writes
.push_back(CreateMockWrite(*server_settings_frame
));
1570 StaticSocketDataProvider
data(reads
, arraysize(reads
),
1571 vector_as_array(&writes
), writes
.size());
1572 data
.set_connect_data(connect_data
);
1573 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1575 CreateNetworkSession();
1577 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1578 test_host_port_pair_
,
1579 SETTINGS_MAX_CONCURRENT_STREAMS
,
1580 SETTINGS_FLAG_PLEASE_PERSIST
,
1581 initial_max_concurrent_streams
);
1583 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
1584 pool_peer
.SetEnableSendingInitialData(true);
1586 base::WeakPtr
<SpdySession
> session
=
1587 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1589 base::MessageLoop::current()->RunUntilIdle();
1590 EXPECT_TRUE(data
.at_write_eof());
1593 TEST_P(SpdySessionTest
, ClearSettingsStorageOnIPAddressChanged
) {
1594 CreateNetworkSession();
1596 base::WeakPtr
<HttpServerProperties
> test_http_server_properties
=
1597 spdy_session_pool_
->http_server_properties();
1598 SettingsFlagsAndValue
flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST
, 2);
1599 test_http_server_properties
->SetSpdySetting(
1600 test_host_port_pair_
,
1601 SETTINGS_MAX_CONCURRENT_STREAMS
,
1602 SETTINGS_FLAG_PLEASE_PERSIST
,
1604 EXPECT_NE(0u, test_http_server_properties
->GetSpdySettings(
1605 test_host_port_pair_
).size());
1606 spdy_session_pool_
->OnIPAddressChanged();
1607 EXPECT_EQ(0u, test_http_server_properties
->GetSpdySettings(
1608 test_host_port_pair_
).size());
1611 TEST_P(SpdySessionTest
, Initialize
) {
1612 CapturingBoundNetLog log
;
1613 session_deps_
.net_log
= log
.bound().net_log();
1614 session_deps_
.host_resolver
->set_synchronous_mode(true);
1616 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1617 MockRead reads
[] = {
1618 MockRead(ASYNC
, 0, 0) // EOF
1621 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1622 data
.set_connect_data(connect_data
);
1623 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1625 CreateNetworkSession();
1627 base::WeakPtr
<SpdySession
> session
=
1628 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1629 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1631 // Flush the read completion task.
1632 base::MessageLoop::current()->RunUntilIdle();
1634 net::CapturingNetLog::CapturedEntryList entries
;
1635 log
.GetEntries(&entries
);
1636 EXPECT_LT(0u, entries
.size());
1638 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1639 int pos
= net::ExpectLogContainsSomewhere(
1640 entries
, 0, net::NetLog::TYPE_HTTP2_SESSION_INITIALIZED
,
1641 net::NetLog::PHASE_NONE
);
1644 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1645 NetLog::Source socket_source
;
1646 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry
.params
.get(),
1648 EXPECT_TRUE(socket_source
.IsValid());
1649 EXPECT_NE(log
.bound().source().id
, socket_source
.id
);
1652 TEST_P(SpdySessionTest
, NetLogOnSessionGoaway
) {
1653 session_deps_
.host_resolver
->set_synchronous_mode(true);
1655 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1656 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
1657 MockRead reads
[] = {
1658 CreateMockRead(*goaway
),
1659 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1662 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1663 data
.set_connect_data(connect_data
);
1664 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1666 CreateNetworkSession();
1668 CapturingBoundNetLog log
;
1669 base::WeakPtr
<SpdySession
> session
=
1670 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1671 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1673 // Flush the read completion task.
1674 base::MessageLoop::current()->RunUntilIdle();
1676 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1677 EXPECT_TRUE(session
== NULL
);
1679 // Check that the NetLog was filled reasonably.
1680 net::CapturingNetLog::CapturedEntryList entries
;
1681 log
.GetEntries(&entries
);
1682 EXPECT_LT(0u, entries
.size());
1684 // Check that we logged SPDY_SESSION_CLOSE correctly.
1685 int pos
= net::ExpectLogContainsSomewhere(
1686 entries
, 0, net::NetLog::TYPE_HTTP2_SESSION_CLOSE
,
1687 net::NetLog::PHASE_NONE
);
1689 if (pos
< static_cast<int>(entries
.size())) {
1690 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1692 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1693 EXPECT_EQ(OK
, error_code
);
1699 TEST_P(SpdySessionTest
, NetLogOnSessionEOF
) {
1700 session_deps_
.host_resolver
->set_synchronous_mode(true);
1702 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1703 MockRead reads
[] = {
1704 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1707 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1708 data
.set_connect_data(connect_data
);
1709 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1711 CreateNetworkSession();
1713 CapturingBoundNetLog log
;
1714 base::WeakPtr
<SpdySession
> session
=
1715 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1716 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1718 // Flush the read completion task.
1719 base::MessageLoop::current()->RunUntilIdle();
1721 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1722 EXPECT_TRUE(session
== NULL
);
1724 // Check that the NetLog was filled reasonably.
1725 net::CapturingNetLog::CapturedEntryList entries
;
1726 log
.GetEntries(&entries
);
1727 EXPECT_LT(0u, entries
.size());
1729 // Check that we logged SPDY_SESSION_CLOSE correctly.
1730 int pos
= net::ExpectLogContainsSomewhere(
1731 entries
, 0, net::NetLog::TYPE_HTTP2_SESSION_CLOSE
,
1732 net::NetLog::PHASE_NONE
);
1734 if (pos
< static_cast<int>(entries
.size())) {
1735 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1737 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1738 EXPECT_EQ(ERR_CONNECTION_CLOSED
, error_code
);
1744 TEST_P(SpdySessionTest
, SynCompressionHistograms
) {
1745 session_deps_
.enable_compression
= true;
1747 scoped_ptr
<SpdyFrame
> req(
1748 spdy_util_
.ConstructSpdyGet(NULL
, 0, true, 1, MEDIUM
, true));
1749 MockWrite writes
[] = {
1750 CreateMockWrite(*req
, 0),
1752 MockRead reads
[] = {
1753 MockRead(ASYNC
, 0, 1) // EOF
1755 DeterministicSocketData
data(reads
, arraysize(reads
),
1756 writes
, arraysize(writes
));
1757 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1758 data
.set_connect_data(connect_data
);
1759 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1761 CreateDeterministicNetworkSession();
1762 base::WeakPtr
<SpdySession
> session
=
1763 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1765 GURL
url(kDefaultURL
);
1766 base::WeakPtr
<SpdyStream
> spdy_stream
=
1767 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1768 session
, url
, MEDIUM
, BoundNetLog());
1769 test::StreamDelegateDoNothing
delegate(spdy_stream
);
1770 spdy_stream
->SetDelegate(&delegate
);
1772 scoped_ptr
<SpdyHeaderBlock
> headers(
1773 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1774 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1775 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
1777 // Write request headers & capture resulting histogram update.
1778 base::HistogramTester histogram_tester
;
1781 // Regression test of compression performance under the request fixture.
1782 switch (spdy_util_
.spdy_version()) {
1784 histogram_tester
.ExpectBucketCount(
1785 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1788 histogram_tester
.ExpectBucketCount(
1789 "Net.SpdySynStreamCompressionPercentage", 82, 1);
1795 // Read and process EOF.
1797 base::MessageLoop::current()->RunUntilIdle();
1798 EXPECT_TRUE(session
== NULL
);
1801 // Queue up a low-priority SYN_STREAM followed by a high-priority
1802 // one. The high priority one should still send first and receive
1804 TEST_P(SpdySessionTest
, OutOfOrderSynStreams
) {
1805 // Construct the request.
1806 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1807 scoped_ptr
<SpdyFrame
> req_highest(
1808 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, HIGHEST
, true));
1809 scoped_ptr
<SpdyFrame
> req_lowest(
1810 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1811 MockWrite writes
[] = {
1812 CreateMockWrite(*req_highest
, 0),
1813 CreateMockWrite(*req_lowest
, 1),
1816 scoped_ptr
<SpdyFrame
> resp_highest(
1817 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1818 scoped_ptr
<SpdyFrame
> body_highest(
1819 spdy_util_
.ConstructSpdyBodyFrame(1, true));
1820 scoped_ptr
<SpdyFrame
> resp_lowest(
1821 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1822 scoped_ptr
<SpdyFrame
> body_lowest(
1823 spdy_util_
.ConstructSpdyBodyFrame(3, true));
1824 MockRead reads
[] = {
1825 CreateMockRead(*resp_highest
, 2),
1826 CreateMockRead(*body_highest
, 3),
1827 CreateMockRead(*resp_lowest
, 4),
1828 CreateMockRead(*body_lowest
, 5),
1829 MockRead(ASYNC
, 0, 6) // EOF
1832 session_deps_
.host_resolver
->set_synchronous_mode(true);
1834 DeterministicSocketData
data(reads
, arraysize(reads
),
1835 writes
, arraysize(writes
));
1836 data
.set_connect_data(connect_data
);
1837 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1839 CreateDeterministicNetworkSession();
1841 base::WeakPtr
<SpdySession
> session
=
1842 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1844 GURL
url(kDefaultURL
);
1846 base::WeakPtr
<SpdyStream
> spdy_stream_lowest
=
1847 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1848 session
, url
, LOWEST
, BoundNetLog());
1849 ASSERT_TRUE(spdy_stream_lowest
);
1850 EXPECT_EQ(0u, spdy_stream_lowest
->stream_id());
1851 test::StreamDelegateDoNothing
delegate_lowest(spdy_stream_lowest
);
1852 spdy_stream_lowest
->SetDelegate(&delegate_lowest
);
1854 base::WeakPtr
<SpdyStream
> spdy_stream_highest
=
1855 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1856 session
, url
, HIGHEST
, BoundNetLog());
1857 ASSERT_TRUE(spdy_stream_highest
);
1858 EXPECT_EQ(0u, spdy_stream_highest
->stream_id());
1859 test::StreamDelegateDoNothing
delegate_highest(spdy_stream_highest
);
1860 spdy_stream_highest
->SetDelegate(&delegate_highest
);
1862 // Queue the lower priority one first.
1864 scoped_ptr
<SpdyHeaderBlock
> headers_lowest(
1865 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1866 spdy_stream_lowest
->SendRequestHeaders(
1867 headers_lowest
.Pass(), NO_MORE_DATA_TO_SEND
);
1868 EXPECT_TRUE(spdy_stream_lowest
->HasUrlFromHeaders());
1870 scoped_ptr
<SpdyHeaderBlock
> headers_highest(
1871 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1872 spdy_stream_highest
->SendRequestHeaders(
1873 headers_highest
.Pass(), NO_MORE_DATA_TO_SEND
);
1874 EXPECT_TRUE(spdy_stream_highest
->HasUrlFromHeaders());
1878 EXPECT_FALSE(spdy_stream_lowest
);
1879 EXPECT_FALSE(spdy_stream_highest
);
1880 EXPECT_EQ(3u, delegate_lowest
.stream_id());
1881 EXPECT_EQ(1u, delegate_highest
.stream_id());
1884 TEST_P(SpdySessionTest
, CancelStream
) {
1885 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1886 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1887 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1888 scoped_ptr
<SpdyFrame
> req2(
1889 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1890 MockWrite writes
[] = {
1891 CreateMockWrite(*req2
, 0),
1894 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1895 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1896 MockRead reads
[] = {
1897 CreateMockRead(*resp2
, 1),
1898 CreateMockRead(*body2
, 2),
1899 MockRead(ASYNC
, 0, 3) // EOF
1902 session_deps_
.host_resolver
->set_synchronous_mode(true);
1904 DeterministicSocketData
data(reads
, arraysize(reads
),
1905 writes
, arraysize(writes
));
1906 data
.set_connect_data(connect_data
);
1907 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1909 CreateDeterministicNetworkSession();
1911 base::WeakPtr
<SpdySession
> session
=
1912 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1914 GURL
url1(kDefaultURL
);
1915 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1916 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1917 session
, url1
, HIGHEST
, BoundNetLog());
1918 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1919 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1920 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
1921 spdy_stream1
->SetDelegate(&delegate1
);
1923 GURL
url2(kDefaultURL
);
1924 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1925 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1926 session
, url2
, LOWEST
, BoundNetLog());
1927 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1928 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1929 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
1930 spdy_stream2
->SetDelegate(&delegate2
);
1932 scoped_ptr
<SpdyHeaderBlock
> headers(
1933 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1934 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1935 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1937 scoped_ptr
<SpdyHeaderBlock
> headers2(
1938 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1939 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1940 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1942 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1944 spdy_stream1
->Cancel();
1945 EXPECT_EQ(NULL
, spdy_stream1
.get());
1947 EXPECT_EQ(0u, delegate1
.stream_id());
1951 EXPECT_EQ(0u, delegate1
.stream_id());
1952 EXPECT_EQ(1u, delegate2
.stream_id());
1954 spdy_stream2
->Cancel();
1955 EXPECT_EQ(NULL
, spdy_stream2
.get());
1958 // Create two streams that are set to re-close themselves on close,
1959 // and then close the session. Nothing should blow up. Also a
1960 // regression test for http://crbug.com/139518 .
1961 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedSelfClosingStreams
) {
1962 session_deps_
.host_resolver
->set_synchronous_mode(true);
1964 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1966 // No actual data will be sent.
1967 MockWrite writes
[] = {
1968 MockWrite(ASYNC
, 0, 1) // EOF
1971 MockRead reads
[] = {
1972 MockRead(ASYNC
, 0, 0) // EOF
1974 DeterministicSocketData
data(reads
, arraysize(reads
),
1975 writes
, arraysize(writes
));
1976 data
.set_connect_data(connect_data
);
1977 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1979 CreateDeterministicNetworkSession();
1981 base::WeakPtr
<SpdySession
> session
=
1982 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1984 GURL
url1(kDefaultURL
);
1985 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1986 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1987 session
, url1
, HIGHEST
, BoundNetLog());
1988 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1989 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1991 GURL
url2(kDefaultURL
);
1992 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1993 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1994 session
, url2
, LOWEST
, BoundNetLog());
1995 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1996 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1998 test::ClosingDelegate
delegate1(spdy_stream1
);
1999 spdy_stream1
->SetDelegate(&delegate1
);
2001 test::ClosingDelegate
delegate2(spdy_stream2
);
2002 spdy_stream2
->SetDelegate(&delegate2
);
2004 scoped_ptr
<SpdyHeaderBlock
> headers(
2005 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2006 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2007 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2009 scoped_ptr
<SpdyHeaderBlock
> headers2(
2010 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2011 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2012 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2014 // Ensure that the streams have not yet been activated and assigned an id.
2015 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2016 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2018 // Ensure we don't crash while closing the session.
2019 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2021 EXPECT_EQ(NULL
, spdy_stream1
.get());
2022 EXPECT_EQ(NULL
, spdy_stream2
.get());
2024 EXPECT_TRUE(delegate1
.StreamIsClosed());
2025 EXPECT_TRUE(delegate2
.StreamIsClosed());
2027 base::MessageLoop::current()->RunUntilIdle();
2028 EXPECT_TRUE(session
== NULL
);
2031 // Create two streams that are set to close each other on close, and
2032 // then close the session. Nothing should blow up.
2033 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedMutuallyClosingStreams
) {
2034 session_deps_
.host_resolver
->set_synchronous_mode(true);
2036 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2038 // No actual data will be sent.
2039 MockWrite writes
[] = {
2040 MockWrite(ASYNC
, 0, 1) // EOF
2043 MockRead reads
[] = {
2044 MockRead(ASYNC
, 0, 0) // EOF
2046 DeterministicSocketData
data(reads
, arraysize(reads
),
2047 writes
, arraysize(writes
));
2048 data
.set_connect_data(connect_data
);
2049 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2051 CreateDeterministicNetworkSession();
2053 base::WeakPtr
<SpdySession
> session
=
2054 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2056 GURL
url1(kDefaultURL
);
2057 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2058 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2059 session
, url1
, HIGHEST
, BoundNetLog());
2060 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2061 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2063 GURL
url2(kDefaultURL
);
2064 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2065 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2066 session
, url2
, LOWEST
, BoundNetLog());
2067 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2068 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2070 // Make |spdy_stream1| close |spdy_stream2|.
2071 test::ClosingDelegate
delegate1(spdy_stream2
);
2072 spdy_stream1
->SetDelegate(&delegate1
);
2074 // Make |spdy_stream2| close |spdy_stream1|.
2075 test::ClosingDelegate
delegate2(spdy_stream1
);
2076 spdy_stream2
->SetDelegate(&delegate2
);
2078 scoped_ptr
<SpdyHeaderBlock
> headers(
2079 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2080 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2081 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2083 scoped_ptr
<SpdyHeaderBlock
> headers2(
2084 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2085 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2086 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2088 // Ensure that the streams have not yet been activated and assigned an id.
2089 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2090 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2092 // Ensure we don't crash while closing the session.
2093 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2095 EXPECT_EQ(NULL
, spdy_stream1
.get());
2096 EXPECT_EQ(NULL
, spdy_stream2
.get());
2098 EXPECT_TRUE(delegate1
.StreamIsClosed());
2099 EXPECT_TRUE(delegate2
.StreamIsClosed());
2101 base::MessageLoop::current()->RunUntilIdle();
2102 EXPECT_TRUE(session
== NULL
);
2105 // Create two streams that are set to re-close themselves on close,
2106 // activate them, and then close the session. Nothing should blow up.
2107 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedSelfClosingStreams
) {
2108 session_deps_
.host_resolver
->set_synchronous_mode(true);
2110 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2112 scoped_ptr
<SpdyFrame
> req1(
2113 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2114 scoped_ptr
<SpdyFrame
> req2(
2115 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
2116 MockWrite writes
[] = {
2117 CreateMockWrite(*req1
, 0),
2118 CreateMockWrite(*req2
, 1),
2121 MockRead reads
[] = {
2122 MockRead(ASYNC
, 0, 2) // EOF
2125 DeterministicSocketData
data(reads
, arraysize(reads
),
2126 writes
, arraysize(writes
));
2127 data
.set_connect_data(connect_data
);
2128 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2130 CreateDeterministicNetworkSession();
2132 base::WeakPtr
<SpdySession
> session
=
2133 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2135 GURL
url1(kDefaultURL
);
2136 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2137 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2138 session
, url1
, MEDIUM
, BoundNetLog());
2139 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2140 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2142 GURL
url2(kDefaultURL
);
2143 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2144 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2145 session
, url2
, MEDIUM
, BoundNetLog());
2146 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2147 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2149 test::ClosingDelegate
delegate1(spdy_stream1
);
2150 spdy_stream1
->SetDelegate(&delegate1
);
2152 test::ClosingDelegate
delegate2(spdy_stream2
);
2153 spdy_stream2
->SetDelegate(&delegate2
);
2155 scoped_ptr
<SpdyHeaderBlock
> headers(
2156 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2157 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2158 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2160 scoped_ptr
<SpdyHeaderBlock
> headers2(
2161 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2162 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2163 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2165 // Ensure that the streams have not yet been activated and assigned an id.
2166 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2167 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2171 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2172 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2174 // Ensure we don't crash while closing the session.
2175 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2177 EXPECT_EQ(NULL
, spdy_stream1
.get());
2178 EXPECT_EQ(NULL
, spdy_stream2
.get());
2180 EXPECT_TRUE(delegate1
.StreamIsClosed());
2181 EXPECT_TRUE(delegate2
.StreamIsClosed());
2183 base::MessageLoop::current()->RunUntilIdle();
2184 EXPECT_TRUE(session
== NULL
);
2187 // Create two streams that are set to close each other on close,
2188 // activate them, and then close the session. Nothing should blow up.
2189 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedMutuallyClosingStreams
) {
2190 session_deps_
.host_resolver
->set_synchronous_mode(true);
2192 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2194 scoped_ptr
<SpdyFrame
> req1(
2195 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2196 scoped_ptr
<SpdyFrame
> req2(
2197 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
2198 MockWrite writes
[] = {
2199 CreateMockWrite(*req1
, 0),
2200 CreateMockWrite(*req2
, 1),
2203 MockRead reads
[] = {
2204 MockRead(ASYNC
, 0, 2) // EOF
2207 DeterministicSocketData
data(reads
, arraysize(reads
),
2208 writes
, arraysize(writes
));
2209 data
.set_connect_data(connect_data
);
2210 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2212 CreateDeterministicNetworkSession();
2214 base::WeakPtr
<SpdySession
> session
=
2215 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2217 GURL
url1(kDefaultURL
);
2218 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2219 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2220 session
, url1
, MEDIUM
, BoundNetLog());
2221 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2222 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2224 GURL
url2(kDefaultURL
);
2225 base::WeakPtr
<SpdyStream
> spdy_stream2
=
2226 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2227 session
, url2
, MEDIUM
, BoundNetLog());
2228 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
2229 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2231 // Make |spdy_stream1| close |spdy_stream2|.
2232 test::ClosingDelegate
delegate1(spdy_stream2
);
2233 spdy_stream1
->SetDelegate(&delegate1
);
2235 // Make |spdy_stream2| close |spdy_stream1|.
2236 test::ClosingDelegate
delegate2(spdy_stream1
);
2237 spdy_stream2
->SetDelegate(&delegate2
);
2239 scoped_ptr
<SpdyHeaderBlock
> headers(
2240 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2241 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2242 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2244 scoped_ptr
<SpdyHeaderBlock
> headers2(
2245 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2246 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2247 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
2249 // Ensure that the streams have not yet been activated and assigned an id.
2250 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2251 EXPECT_EQ(0u, spdy_stream2
->stream_id());
2255 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2256 EXPECT_EQ(3u, spdy_stream2
->stream_id());
2258 // Ensure we don't crash while closing the session.
2259 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
2261 EXPECT_EQ(NULL
, spdy_stream1
.get());
2262 EXPECT_EQ(NULL
, spdy_stream2
.get());
2264 EXPECT_TRUE(delegate1
.StreamIsClosed());
2265 EXPECT_TRUE(delegate2
.StreamIsClosed());
2267 base::MessageLoop::current()->RunUntilIdle();
2268 EXPECT_TRUE(session
== NULL
);
2271 // Delegate that closes a given session when the stream is closed.
2272 class SessionClosingDelegate
: public test::StreamDelegateDoNothing
{
2274 SessionClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
2275 const base::WeakPtr
<SpdySession
>& session_to_close
)
2276 : StreamDelegateDoNothing(stream
),
2277 session_to_close_(session_to_close
) {}
2279 ~SessionClosingDelegate() override
{}
2281 void OnClose(int status
) override
{
2282 session_to_close_
->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR
, "Error");
2286 base::WeakPtr
<SpdySession
> session_to_close_
;
2289 // Close an activated stream that closes its session. Nothing should
2290 // blow up. This is a regression test for http://crbug.com/263691 .
2291 TEST_P(SpdySessionTest
, CloseActivatedStreamThatClosesSession
) {
2292 session_deps_
.host_resolver
->set_synchronous_mode(true);
2294 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2296 scoped_ptr
<SpdyFrame
> req(
2297 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2298 scoped_ptr
<SpdyFrame
> rst(
2299 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2300 scoped_ptr
<SpdyFrame
> goaway(
2301 spdy_util_
.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR
, "Error"));
2302 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2303 // despite being queued second.
2304 MockWrite writes
[] = {
2305 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 1),
2306 CreateMockWrite(*rst
, 2),
2309 MockRead reads
[] = {
2310 MockRead(ASYNC
, 0, 3) // EOF
2312 DeterministicSocketData
data(reads
, arraysize(reads
),
2313 writes
, arraysize(writes
));
2314 data
.set_connect_data(connect_data
);
2315 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2317 CreateDeterministicNetworkSession();
2319 base::WeakPtr
<SpdySession
> session
=
2320 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2322 GURL
url(kDefaultURL
);
2323 base::WeakPtr
<SpdyStream
> spdy_stream
=
2324 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2325 session
, url
, MEDIUM
, BoundNetLog());
2326 ASSERT_TRUE(spdy_stream
.get() != NULL
);
2327 EXPECT_EQ(0u, spdy_stream
->stream_id());
2329 SessionClosingDelegate
delegate(spdy_stream
, session
);
2330 spdy_stream
->SetDelegate(&delegate
);
2332 scoped_ptr
<SpdyHeaderBlock
> headers(
2333 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
2334 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2335 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
2337 EXPECT_EQ(0u, spdy_stream
->stream_id());
2341 EXPECT_EQ(1u, spdy_stream
->stream_id());
2343 // Ensure we don't crash while closing the stream (which closes the
2345 spdy_stream
->Cancel();
2347 EXPECT_EQ(NULL
, spdy_stream
.get());
2348 EXPECT_TRUE(delegate
.StreamIsClosed());
2350 data
.RunFor(2); // Write the RST_STREAM & GOAWAY.
2351 base::MessageLoop::current()->RunUntilIdle();
2352 EXPECT_TRUE(session
== NULL
);
2355 TEST_P(SpdySessionTest
, VerifyDomainAuthentication
) {
2356 session_deps_
.host_resolver
->set_synchronous_mode(true);
2358 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2360 // No actual data will be sent.
2361 MockWrite writes
[] = {
2362 MockWrite(ASYNC
, 0, 1) // EOF
2365 MockRead reads
[] = {
2366 MockRead(ASYNC
, 0, 0) // EOF
2368 DeterministicSocketData
data(reads
, arraysize(reads
),
2369 writes
, arraysize(writes
));
2370 data
.set_connect_data(connect_data
);
2371 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2373 // Load a cert that is valid for:
2377 base::FilePath certs_dir
= GetTestCertsDirectory();
2378 scoped_refptr
<X509Certificate
> test_cert(
2379 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2380 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
.get());
2382 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2383 ssl
.cert
= test_cert
;
2384 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2386 CreateDeterministicNetworkSession();
2388 base::WeakPtr
<SpdySession
> session
=
2389 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2391 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2392 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2393 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.com"));
2394 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2397 TEST_P(SpdySessionTest
, ConnectionPooledWithTlsChannelId
) {
2398 session_deps_
.host_resolver
->set_synchronous_mode(true);
2400 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2402 // No actual data will be sent.
2403 MockWrite writes
[] = {
2404 MockWrite(ASYNC
, 0, 1) // EOF
2407 MockRead reads
[] = {
2408 MockRead(ASYNC
, 0, 0) // EOF
2410 DeterministicSocketData
data(reads
, arraysize(reads
),
2411 writes
, arraysize(writes
));
2412 data
.set_connect_data(connect_data
);
2413 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2415 // Load a cert that is valid for:
2419 base::FilePath certs_dir
= GetTestCertsDirectory();
2420 scoped_refptr
<X509Certificate
> test_cert(
2421 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2422 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
.get());
2424 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2425 ssl
.channel_id_sent
= true;
2426 ssl
.cert
= test_cert
;
2427 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2429 CreateDeterministicNetworkSession();
2431 base::WeakPtr
<SpdySession
> session
=
2432 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2434 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2435 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2436 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.example.com"));
2437 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2440 TEST_P(SpdySessionTest
, CloseTwoStalledCreateStream
) {
2441 // TODO(rtenneti): Define a helper class/methods and move the common code in
2443 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2445 SettingsMap new_settings
;
2446 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
2447 const uint32 max_concurrent_streams
= 1;
2448 new_settings
[kSpdySettingsIds1
] =
2449 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
2451 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
2452 scoped_ptr
<SpdyFrame
> req1(
2453 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2454 scoped_ptr
<SpdyFrame
> req2(
2455 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
2456 scoped_ptr
<SpdyFrame
> req3(
2457 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
2458 MockWrite writes
[] = {
2459 CreateMockWrite(*settings_ack
, 1),
2460 CreateMockWrite(*req1
, 2),
2461 CreateMockWrite(*req2
, 5),
2462 CreateMockWrite(*req3
, 8),
2465 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2467 scoped_ptr
<SpdyFrame
> settings_frame(
2468 spdy_util_
.ConstructSpdySettings(new_settings
));
2470 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2471 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2473 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
2474 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
2476 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
2477 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
2479 MockRead reads
[] = {
2480 CreateMockRead(*settings_frame
),
2481 CreateMockRead(*resp1
, 3),
2482 CreateMockRead(*body1
, 4),
2483 CreateMockRead(*resp2
, 6),
2484 CreateMockRead(*body2
, 7),
2485 CreateMockRead(*resp3
, 9),
2486 CreateMockRead(*body3
, 10),
2487 MockRead(ASYNC
, 0, 11) // EOF
2490 DeterministicSocketData
data(reads
, arraysize(reads
),
2491 writes
, arraysize(writes
));
2492 data
.set_connect_data(connect_data
);
2493 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2495 CreateDeterministicNetworkSession();
2497 base::WeakPtr
<SpdySession
> session
=
2498 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2500 // Read the settings frame.
2503 GURL
url1(kDefaultURL
);
2504 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2505 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2506 session
, url1
, LOWEST
, BoundNetLog());
2507 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2508 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2509 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2510 spdy_stream1
->SetDelegate(&delegate1
);
2512 TestCompletionCallback callback2
;
2513 GURL
url2(kDefaultURL
);
2514 SpdyStreamRequest request2
;
2515 ASSERT_EQ(ERR_IO_PENDING
,
2516 request2
.StartRequest(
2517 SPDY_REQUEST_RESPONSE_STREAM
,
2518 session
, url2
, LOWEST
, BoundNetLog(), callback2
.callback()));
2520 TestCompletionCallback callback3
;
2521 GURL
url3(kDefaultURL
);
2522 SpdyStreamRequest request3
;
2523 ASSERT_EQ(ERR_IO_PENDING
,
2524 request3
.StartRequest(
2525 SPDY_REQUEST_RESPONSE_STREAM
,
2526 session
, url3
, LOWEST
, BoundNetLog(), callback3
.callback()));
2528 EXPECT_EQ(0u, session
->num_active_streams());
2529 EXPECT_EQ(1u, session
->num_created_streams());
2530 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2532 scoped_ptr
<SpdyHeaderBlock
> headers(
2533 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2534 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2535 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2537 // Run until 1st stream is activated and then closed.
2538 EXPECT_EQ(0u, delegate1
.stream_id());
2540 EXPECT_EQ(NULL
, spdy_stream1
.get());
2541 EXPECT_EQ(1u, delegate1
.stream_id());
2543 EXPECT_EQ(0u, session
->num_active_streams());
2544 EXPECT_EQ(0u, session
->num_created_streams());
2545 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2547 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2548 // create the 2nd stream.
2549 base::MessageLoop::current()->RunUntilIdle();
2551 EXPECT_EQ(0u, session
->num_active_streams());
2552 EXPECT_EQ(1u, session
->num_created_streams());
2553 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2555 base::WeakPtr
<SpdyStream
> stream2
= request2
.ReleaseStream();
2556 test::StreamDelegateDoNothing
delegate2(stream2
);
2557 stream2
->SetDelegate(&delegate2
);
2558 scoped_ptr
<SpdyHeaderBlock
> headers2(
2559 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2560 stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2561 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
2563 // Run until 2nd stream is activated and then closed.
2564 EXPECT_EQ(0u, delegate2
.stream_id());
2566 EXPECT_EQ(NULL
, stream2
.get());
2567 EXPECT_EQ(3u, delegate2
.stream_id());
2569 EXPECT_EQ(0u, session
->num_active_streams());
2570 EXPECT_EQ(0u, session
->num_created_streams());
2571 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2573 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2574 // create the 3rd stream.
2575 base::MessageLoop::current()->RunUntilIdle();
2577 EXPECT_EQ(0u, session
->num_active_streams());
2578 EXPECT_EQ(1u, session
->num_created_streams());
2579 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2581 base::WeakPtr
<SpdyStream
> stream3
= request3
.ReleaseStream();
2582 test::StreamDelegateDoNothing
delegate3(stream3
);
2583 stream3
->SetDelegate(&delegate3
);
2584 scoped_ptr
<SpdyHeaderBlock
> headers3(
2585 spdy_util_
.ConstructGetHeaderBlock(url3
.spec()));
2586 stream3
->SendRequestHeaders(headers3
.Pass(), NO_MORE_DATA_TO_SEND
);
2587 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
2589 // Run until 2nd stream is activated and then closed.
2590 EXPECT_EQ(0u, delegate3
.stream_id());
2592 EXPECT_EQ(NULL
, stream3
.get());
2593 EXPECT_EQ(5u, delegate3
.stream_id());
2595 EXPECT_EQ(0u, session
->num_active_streams());
2596 EXPECT_EQ(0u, session
->num_created_streams());
2597 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2602 TEST_P(SpdySessionTest
, CancelTwoStalledCreateStream
) {
2603 session_deps_
.host_resolver
->set_synchronous_mode(true);
2605 MockRead reads
[] = {
2606 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2609 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
2610 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2612 data
.set_connect_data(connect_data
);
2613 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2615 CreateNetworkSession();
2617 base::WeakPtr
<SpdySession
> session
=
2618 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2620 // Leave room for only one more stream to be created.
2621 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
2622 base::WeakPtr
<SpdyStream
> spdy_stream
=
2623 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2624 session
, test_url_
, MEDIUM
, BoundNetLog());
2625 ASSERT_TRUE(spdy_stream
!= NULL
);
2628 GURL
url1(kDefaultURL
);
2629 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2630 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2631 session
, url1
, LOWEST
, BoundNetLog());
2632 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2633 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2635 TestCompletionCallback callback2
;
2636 GURL
url2(kDefaultURL
);
2637 SpdyStreamRequest request2
;
2638 ASSERT_EQ(ERR_IO_PENDING
,
2639 request2
.StartRequest(
2640 SPDY_BIDIRECTIONAL_STREAM
, session
, url2
, LOWEST
, BoundNetLog(),
2641 callback2
.callback()));
2643 TestCompletionCallback callback3
;
2644 GURL
url3(kDefaultURL
);
2645 SpdyStreamRequest request3
;
2646 ASSERT_EQ(ERR_IO_PENDING
,
2647 request3
.StartRequest(
2648 SPDY_BIDIRECTIONAL_STREAM
, session
, url3
, LOWEST
, BoundNetLog(),
2649 callback3
.callback()));
2651 EXPECT_EQ(0u, session
->num_active_streams());
2652 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2653 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2655 // Cancel the first stream; this will allow the second stream to be created.
2656 EXPECT_TRUE(spdy_stream1
.get() != NULL
);
2657 spdy_stream1
->Cancel();
2658 EXPECT_EQ(NULL
, spdy_stream1
.get());
2660 EXPECT_EQ(OK
, callback2
.WaitForResult());
2661 EXPECT_EQ(0u, session
->num_active_streams());
2662 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2663 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2665 // Cancel the second stream; this will allow the third stream to be created.
2666 base::WeakPtr
<SpdyStream
> spdy_stream2
= request2
.ReleaseStream();
2667 spdy_stream2
->Cancel();
2668 EXPECT_EQ(NULL
, spdy_stream2
.get());
2670 EXPECT_EQ(OK
, callback3
.WaitForResult());
2671 EXPECT_EQ(0u, session
->num_active_streams());
2672 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2673 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2675 // Cancel the third stream.
2676 base::WeakPtr
<SpdyStream
> spdy_stream3
= request3
.ReleaseStream();
2677 spdy_stream3
->Cancel();
2678 EXPECT_EQ(NULL
, spdy_stream3
.get());
2679 EXPECT_EQ(0u, session
->num_active_streams());
2680 EXPECT_EQ(kInitialMaxConcurrentStreams
- 1, session
->num_created_streams());
2681 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2684 // Test that SpdySession::DoReadLoop reads data from the socket
2685 // without yielding. This test makes 32k - 1 bytes of data available
2686 // on the socket for reading. It then verifies that it has read all
2687 // the available data without yielding.
2688 TEST_P(SpdySessionTest
, ReadDataWithoutYielding
) {
2689 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2690 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2692 scoped_ptr
<SpdyFrame
> req1(
2693 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2694 MockWrite writes
[] = {
2695 CreateMockWrite(*req1
, 0),
2698 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2699 // (-spdy_data_frame_size).
2700 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2701 const int kPayloadSize
=
2702 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2703 TestDataStream test_stream
;
2704 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
2705 char* payload_data
= payload
->data();
2706 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2708 scoped_ptr
<SpdyFrame
> partial_data_frame(
2709 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2710 scoped_ptr
<SpdyFrame
> finish_data_frame(
2711 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
- 1, DATA_FLAG_FIN
));
2713 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2715 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2717 MockRead reads
[] = {
2718 CreateMockRead(*resp1
, 1),
2719 CreateMockRead(*partial_data_frame
, 2),
2720 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2721 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2722 CreateMockRead(*finish_data_frame
, 5, SYNCHRONOUS
),
2723 MockRead(ASYNC
, 0, 6) // EOF
2726 // Create SpdySession and SpdyStream and send the request.
2727 DeterministicSocketData
data(reads
, arraysize(reads
),
2728 writes
, arraysize(writes
));
2729 data
.set_connect_data(connect_data
);
2730 session_deps_
.host_resolver
->set_synchronous_mode(true);
2731 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2733 CreateDeterministicNetworkSession();
2735 base::WeakPtr
<SpdySession
> session
=
2736 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2738 GURL
url1(kDefaultURL
);
2739 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2740 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2741 session
, url1
, MEDIUM
, BoundNetLog());
2742 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2743 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2744 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2745 spdy_stream1
->SetDelegate(&delegate1
);
2747 scoped_ptr
<SpdyHeaderBlock
> headers1(
2748 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2749 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2750 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2752 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2754 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2756 // Run until 1st read.
2757 EXPECT_EQ(0u, delegate1
.stream_id());
2759 EXPECT_EQ(1u, delegate1
.stream_id());
2760 EXPECT_EQ(0u, observer
.executed_count());
2762 // Read all the data and verify SpdySession::DoReadLoop has not
2765 EXPECT_EQ(NULL
, spdy_stream1
.get());
2767 // Verify task observer's executed_count is zero, which indicates DoRead read
2768 // all the available data.
2769 EXPECT_EQ(0u, observer
.executed_count());
2770 EXPECT_TRUE(data
.at_write_eof());
2771 EXPECT_TRUE(data
.at_read_eof());
2774 // Test that SpdySession::DoReadLoop yields while reading the
2775 // data. This test makes 32k + 1 bytes of data available on the socket
2776 // for reading. It then verifies that DoRead has yielded even though
2777 // there is data available for it to read (i.e, socket()->Read didn't
2778 // return ERR_IO_PENDING during socket reads).
2779 TEST_P(SpdySessionTest
, TestYieldingDuringReadData
) {
2780 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2781 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2783 scoped_ptr
<SpdyFrame
> req1(
2784 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2785 MockWrite writes
[] = {
2786 CreateMockWrite(*req1
, 0),
2789 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2790 // (-spdy_data_frame_size).
2791 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2792 const int kPayloadSize
=
2793 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2794 TestDataStream test_stream
;
2795 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
2796 char* payload_data
= payload
->data();
2797 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2799 scoped_ptr
<SpdyFrame
> partial_data_frame(
2800 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2801 scoped_ptr
<SpdyFrame
> finish_data_frame(
2802 framer
.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN
));
2804 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2806 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2807 MockRead reads
[] = {
2808 CreateMockRead(*resp1
, 1),
2809 CreateMockRead(*partial_data_frame
, 2),
2810 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2811 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2812 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2813 CreateMockRead(*finish_data_frame
, 6, SYNCHRONOUS
),
2814 MockRead(ASYNC
, 0, 7) // EOF
2817 // Create SpdySession and SpdyStream and send the request.
2818 DeterministicSocketData
data(reads
, arraysize(reads
),
2819 writes
, arraysize(writes
));
2820 data
.set_connect_data(connect_data
);
2821 session_deps_
.host_resolver
->set_synchronous_mode(true);
2822 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2824 CreateDeterministicNetworkSession();
2826 base::WeakPtr
<SpdySession
> session
=
2827 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2829 GURL
url1(kDefaultURL
);
2830 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2831 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2832 session
, url1
, MEDIUM
, BoundNetLog());
2833 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2834 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2835 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2836 spdy_stream1
->SetDelegate(&delegate1
);
2838 scoped_ptr
<SpdyHeaderBlock
> headers1(
2839 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2840 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2841 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2843 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2845 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2847 // Run until 1st read.
2848 EXPECT_EQ(0u, delegate1
.stream_id());
2850 EXPECT_EQ(1u, delegate1
.stream_id());
2851 EXPECT_EQ(0u, observer
.executed_count());
2853 // Read all the data and verify SpdySession::DoReadLoop has posted a
2856 EXPECT_EQ(NULL
, spdy_stream1
.get());
2858 // Verify task observer's executed_count is 1, which indicates DoRead has
2859 // posted only one task and thus yielded though there is data available for it
2861 EXPECT_EQ(1u, observer
.executed_count());
2862 EXPECT_TRUE(data
.at_write_eof());
2863 EXPECT_TRUE(data
.at_read_eof());
2866 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2867 // + async, by doing the following MockReads.
2869 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2870 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2872 // The above reads 26K synchronously. Since that is less that 32K, we
2873 // will attempt to read again. However, that DoRead() will return
2874 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2875 // yield. When we come back, DoRead() will read the results from the
2876 // async read, and rest of the data synchronously.
2877 TEST_P(SpdySessionTest
, TestYieldingDuringAsyncReadData
) {
2878 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2879 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2881 scoped_ptr
<SpdyFrame
> req1(
2882 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2883 MockWrite writes
[] = {
2884 CreateMockWrite(*req1
, 0),
2887 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2888 // (-spdy_data_frame_size).
2889 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2890 TestDataStream test_stream
;
2891 const int kEightKPayloadSize
=
2892 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2893 scoped_refptr
<net::IOBuffer
> eightk_payload(
2894 new net::IOBuffer(kEightKPayloadSize
));
2895 char* eightk_payload_data
= eightk_payload
->data();
2896 test_stream
.GetBytes(eightk_payload_data
, kEightKPayloadSize
);
2898 // Build buffer of 2k size.
2899 TestDataStream test_stream2
;
2900 const int kTwoKPayloadSize
= kEightKPayloadSize
- 6 * 1024;
2901 scoped_refptr
<net::IOBuffer
> twok_payload(
2902 new net::IOBuffer(kTwoKPayloadSize
));
2903 char* twok_payload_data
= twok_payload
->data();
2904 test_stream2
.GetBytes(twok_payload_data
, kTwoKPayloadSize
);
2906 scoped_ptr
<SpdyFrame
> eightk_data_frame(framer
.CreateDataFrame(
2907 1, eightk_payload_data
, kEightKPayloadSize
, DATA_FLAG_NONE
));
2908 scoped_ptr
<SpdyFrame
> twok_data_frame(framer
.CreateDataFrame(
2909 1, twok_payload_data
, kTwoKPayloadSize
, DATA_FLAG_NONE
));
2910 scoped_ptr
<SpdyFrame
> finish_data_frame(framer
.CreateDataFrame(
2911 1, "h", 1, DATA_FLAG_FIN
));
2913 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2915 MockRead reads
[] = {
2916 CreateMockRead(*resp1
, 1),
2917 CreateMockRead(*eightk_data_frame
, 2),
2918 CreateMockRead(*eightk_data_frame
, 3, SYNCHRONOUS
),
2919 CreateMockRead(*eightk_data_frame
, 4, SYNCHRONOUS
),
2920 CreateMockRead(*twok_data_frame
, 5, SYNCHRONOUS
),
2921 CreateMockRead(*eightk_data_frame
, 6, ASYNC
),
2922 CreateMockRead(*eightk_data_frame
, 7, SYNCHRONOUS
),
2923 CreateMockRead(*eightk_data_frame
, 8, SYNCHRONOUS
),
2924 CreateMockRead(*eightk_data_frame
, 9, SYNCHRONOUS
),
2925 CreateMockRead(*twok_data_frame
, 10, SYNCHRONOUS
),
2926 CreateMockRead(*finish_data_frame
, 11, SYNCHRONOUS
),
2927 MockRead(ASYNC
, 0, 12) // EOF
2930 // Create SpdySession and SpdyStream and send the request.
2931 DeterministicSocketData
data(reads
, arraysize(reads
),
2932 writes
, arraysize(writes
));
2933 data
.set_connect_data(connect_data
);
2934 session_deps_
.host_resolver
->set_synchronous_mode(true);
2935 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2937 CreateDeterministicNetworkSession();
2939 base::WeakPtr
<SpdySession
> session
=
2940 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2942 GURL
url1(kDefaultURL
);
2943 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2944 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2945 session
, url1
, MEDIUM
, BoundNetLog());
2946 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2947 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2948 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2949 spdy_stream1
->SetDelegate(&delegate1
);
2951 scoped_ptr
<SpdyHeaderBlock
> headers1(
2952 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2953 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2954 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2956 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2957 // posting of tasks.
2958 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2960 // Run until 1st read.
2961 EXPECT_EQ(0u, delegate1
.stream_id());
2963 EXPECT_EQ(1u, delegate1
.stream_id());
2964 EXPECT_EQ(0u, observer
.executed_count());
2966 // Read all the data and verify SpdySession::DoReadLoop has posted a
2969 EXPECT_EQ(NULL
, spdy_stream1
.get());
2971 // Verify task observer's executed_count is 1, which indicates DoRead has
2972 // posted only one task and thus yielded though there is data available for
2974 EXPECT_EQ(1u, observer
.executed_count());
2975 EXPECT_TRUE(data
.at_write_eof());
2976 EXPECT_TRUE(data
.at_read_eof());
2979 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2980 // nothing blows up.
2981 TEST_P(SpdySessionTest
, GoAwayWhileInDoReadLoop
) {
2982 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2983 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2985 scoped_ptr
<SpdyFrame
> req1(
2986 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2987 MockWrite writes
[] = {
2988 CreateMockWrite(*req1
, 0),
2991 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2992 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2993 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
2995 MockRead reads
[] = {
2996 CreateMockRead(*resp1
, 1),
2997 CreateMockRead(*body1
, 2),
2998 CreateMockRead(*goaway
, 3),
3001 // Create SpdySession and SpdyStream and send the request.
3002 DeterministicSocketData
data(reads
, arraysize(reads
),
3003 writes
, arraysize(writes
));
3004 data
.set_connect_data(connect_data
);
3005 session_deps_
.host_resolver
->set_synchronous_mode(true);
3006 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3008 CreateDeterministicNetworkSession();
3010 base::WeakPtr
<SpdySession
> session
=
3011 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3013 GURL
url1(kDefaultURL
);
3014 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3015 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3016 session
, url1
, MEDIUM
, BoundNetLog());
3017 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3018 spdy_stream1
->SetDelegate(&delegate1
);
3019 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
3020 EXPECT_EQ(0u, spdy_stream1
->stream_id());
3022 scoped_ptr
<SpdyHeaderBlock
> headers1(
3023 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
3024 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
3025 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3027 // Run until 1st read.
3028 EXPECT_EQ(0u, spdy_stream1
->stream_id());
3030 EXPECT_EQ(1u, spdy_stream1
->stream_id());
3032 // Run until GoAway.
3034 EXPECT_EQ(NULL
, spdy_stream1
.get());
3035 EXPECT_TRUE(data
.at_write_eof());
3036 EXPECT_TRUE(data
.at_read_eof());
3037 EXPECT_TRUE(session
== NULL
);
3040 // Within this framework, a SpdySession should be initialized with
3041 // flow control disabled for protocol version 2, with flow control
3042 // enabled only for streams for protocol version 3, and with flow
3043 // control enabled for streams and sessions for higher versions.
3044 TEST_P(SpdySessionTest
, ProtocolNegotiation
) {
3045 session_deps_
.host_resolver
->set_synchronous_mode(true);
3047 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3048 MockRead reads
[] = {
3049 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3051 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3052 data
.set_connect_data(connect_data
);
3053 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3055 CreateNetworkSession();
3056 base::WeakPtr
<SpdySession
> session
=
3057 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3059 EXPECT_EQ(spdy_util_
.spdy_version(),
3060 session
->buffered_spdy_framer_
->protocol_version());
3061 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3062 session
->flow_control_state());
3063 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3064 session
->session_send_window_size_
);
3065 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3066 session
->session_recv_window_size_
);
3067 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3070 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3071 // pointers to the idle session are currently held.
3072 TEST_P(SpdySessionTest
, CloseOneIdleConnection
) {
3073 ClientSocketPoolManager::set_max_sockets_per_group(
3074 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3075 ClientSocketPoolManager::set_max_sockets_per_pool(
3076 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3078 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3079 MockRead reads
[] = {
3080 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3082 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3083 data
.set_connect_data(connect_data
);
3084 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3085 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3087 CreateNetworkSession();
3089 TransportClientSocketPool
* pool
=
3090 http_session_
->GetTransportSocketPool(
3091 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3093 // Create an idle SPDY session.
3094 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3095 PRIVACY_MODE_DISABLED
);
3096 base::WeakPtr
<SpdySession
> session1
=
3097 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3098 EXPECT_FALSE(pool
->IsStalled());
3100 // Trying to create a new connection should cause the pool to be stalled, and
3101 // post a task asynchronously to try and close the session.
3102 TestCompletionCallback callback2
;
3103 HostPortPair
host_port2("2.com", 80);
3104 scoped_refptr
<TransportSocketParams
> params2(
3105 new TransportSocketParams(
3106 host_port2
, false, false, OnHostResolutionCallback(),
3107 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3108 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3109 EXPECT_EQ(ERR_IO_PENDING
,
3110 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3111 callback2
.callback(), pool
, BoundNetLog()));
3112 EXPECT_TRUE(pool
->IsStalled());
3114 // The socket pool should close the connection asynchronously and establish a
3116 EXPECT_EQ(OK
, callback2
.WaitForResult());
3117 EXPECT_FALSE(pool
->IsStalled());
3118 EXPECT_TRUE(session1
== NULL
);
3121 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3122 // pointers to the idle session are currently held, in the case the SPDY session
3124 TEST_P(SpdySessionTest
, CloseOneIdleConnectionWithAlias
) {
3125 ClientSocketPoolManager::set_max_sockets_per_group(
3126 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3127 ClientSocketPoolManager::set_max_sockets_per_pool(
3128 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3130 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3131 MockRead reads
[] = {
3132 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3134 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3135 data
.set_connect_data(connect_data
);
3136 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3137 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3139 session_deps_
.host_resolver
->set_synchronous_mode(true);
3140 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3141 "1.com", "192.168.0.2", std::string());
3142 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3143 "2.com", "192.168.0.2", std::string());
3144 // Not strictly needed.
3145 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
3146 "3.com", "192.168.0.3", std::string());
3148 CreateNetworkSession();
3150 TransportClientSocketPool
* pool
=
3151 http_session_
->GetTransportSocketPool(
3152 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3154 // Create an idle SPDY session.
3155 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3156 PRIVACY_MODE_DISABLED
);
3157 base::WeakPtr
<SpdySession
> session1
=
3158 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3159 EXPECT_FALSE(pool
->IsStalled());
3161 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3162 SpdySessionKey
key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3163 PRIVACY_MODE_DISABLED
);
3164 HostResolver::RequestInfo
info(key2
.host_port_pair());
3165 AddressList addresses
;
3166 // Pre-populate the DNS cache, since a synchronous resolution is required in
3167 // order to create the alias.
3168 session_deps_
.host_resolver
->Resolve(info
,
3171 CompletionCallback(),
3174 // Get a session for |key2|, which should return the session created earlier.
3175 base::WeakPtr
<SpdySession
> session2
=
3176 spdy_session_pool_
->FindAvailableSession(key2
, BoundNetLog());
3177 ASSERT_EQ(session1
.get(), session2
.get());
3178 EXPECT_FALSE(pool
->IsStalled());
3180 // Trying to create a new connection should cause the pool to be stalled, and
3181 // post a task asynchronously to try and close the session.
3182 TestCompletionCallback callback3
;
3183 HostPortPair
host_port3("3.com", 80);
3184 scoped_refptr
<TransportSocketParams
> params3(
3185 new TransportSocketParams(
3186 host_port3
, false, false, OnHostResolutionCallback(),
3187 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3188 scoped_ptr
<ClientSocketHandle
> connection3(new ClientSocketHandle
);
3189 EXPECT_EQ(ERR_IO_PENDING
,
3190 connection3
->Init(host_port3
.ToString(), params3
, DEFAULT_PRIORITY
,
3191 callback3
.callback(), pool
, BoundNetLog()));
3192 EXPECT_TRUE(pool
->IsStalled());
3194 // The socket pool should close the connection asynchronously and establish a
3196 EXPECT_EQ(OK
, callback3
.WaitForResult());
3197 EXPECT_FALSE(pool
->IsStalled());
3198 EXPECT_TRUE(session1
== NULL
);
3199 EXPECT_TRUE(session2
== NULL
);
3202 // Tests that when a SPDY session becomes idle, it closes itself if there is
3203 // a lower layer pool stalled on the per-pool socket limit.
3204 TEST_P(SpdySessionTest
, CloseSessionOnIdleWhenPoolStalled
) {
3205 ClientSocketPoolManager::set_max_sockets_per_group(
3206 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3207 ClientSocketPoolManager::set_max_sockets_per_pool(
3208 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
3210 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3211 MockRead reads
[] = {
3212 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3214 scoped_ptr
<SpdyFrame
> req1(
3215 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
3216 scoped_ptr
<SpdyFrame
> cancel1(
3217 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3218 MockWrite writes
[] = {
3219 CreateMockWrite(*req1
, 1),
3220 CreateMockWrite(*cancel1
, 1),
3222 StaticSocketDataProvider
data(reads
, arraysize(reads
),
3223 writes
, arraysize(writes
));
3224 data
.set_connect_data(connect_data
);
3225 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3227 MockRead http_reads
[] = {
3228 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
3230 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
3232 http_data
.set_connect_data(connect_data
);
3233 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
3236 CreateNetworkSession();
3238 TransportClientSocketPool
* pool
=
3239 http_session_
->GetTransportSocketPool(
3240 HttpNetworkSession::NORMAL_SOCKET_POOL
);
3242 // Create a SPDY session.
3243 GURL
url1(kDefaultURL
);
3244 SpdySessionKey
key1(HostPortPair(url1
.host(), 80),
3245 ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3246 base::WeakPtr
<SpdySession
> session1
=
3247 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
3248 EXPECT_FALSE(pool
->IsStalled());
3250 // Create a stream using the session, and send a request.
3252 TestCompletionCallback callback1
;
3253 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3254 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3255 session1
, url1
, DEFAULT_PRIORITY
,
3257 ASSERT_TRUE(spdy_stream1
.get());
3258 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
3259 spdy_stream1
->SetDelegate(&delegate1
);
3261 scoped_ptr
<SpdyHeaderBlock
> headers1(
3262 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
3263 EXPECT_EQ(ERR_IO_PENDING
,
3264 spdy_stream1
->SendRequestHeaders(
3265 headers1
.Pass(), NO_MORE_DATA_TO_SEND
));
3266 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
3268 base::MessageLoop::current()->RunUntilIdle();
3270 // Trying to create a new connection should cause the pool to be stalled, and
3271 // post a task asynchronously to try and close the session.
3272 TestCompletionCallback callback2
;
3273 HostPortPair
host_port2("2.com", 80);
3274 scoped_refptr
<TransportSocketParams
> params2(
3275 new TransportSocketParams(
3276 host_port2
, false, false, OnHostResolutionCallback(),
3277 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT
));
3278 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
3279 EXPECT_EQ(ERR_IO_PENDING
,
3280 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
3281 callback2
.callback(), pool
, BoundNetLog()));
3282 EXPECT_TRUE(pool
->IsStalled());
3284 // Running the message loop should cause the socket pool to ask the SPDY
3285 // session to close an idle socket, but since the socket is in use, nothing
3287 base::RunLoop().RunUntilIdle();
3288 EXPECT_TRUE(pool
->IsStalled());
3289 EXPECT_FALSE(callback2
.have_result());
3291 // Cancelling the request should result in the session's socket being
3292 // closed, since the pool is stalled.
3293 ASSERT_TRUE(spdy_stream1
.get());
3294 spdy_stream1
->Cancel();
3295 base::RunLoop().RunUntilIdle();
3296 ASSERT_FALSE(pool
->IsStalled());
3297 EXPECT_EQ(OK
, callback2
.WaitForResult());
3300 // Verify that SpdySessionKey and therefore SpdySession is different when
3301 // privacy mode is enabled or disabled.
3302 TEST_P(SpdySessionTest
, SpdySessionKeyPrivacyMode
) {
3303 CreateDeterministicNetworkSession();
3305 HostPortPair
host_port_pair("www.google.com", 443);
3306 SpdySessionKey
key_privacy_enabled(host_port_pair
, ProxyServer::Direct(),
3307 PRIVACY_MODE_ENABLED
);
3308 SpdySessionKey
key_privacy_disabled(host_port_pair
, ProxyServer::Direct(),
3309 PRIVACY_MODE_DISABLED
);
3311 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3312 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3314 // Add SpdySession with PrivacyMode Enabled to the pool.
3315 base::WeakPtr
<SpdySession
> session_privacy_enabled
=
3316 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_enabled
);
3318 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3319 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3321 // Add SpdySession with PrivacyMode Disabled to the pool.
3322 base::WeakPtr
<SpdySession
> session_privacy_disabled
=
3323 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_disabled
);
3325 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3326 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3328 session_privacy_enabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3329 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3330 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3332 session_privacy_disabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
3333 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
3334 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
3337 // Delegate that creates another stream when its stream is closed.
3338 class StreamCreatingDelegate
: public test::StreamDelegateDoNothing
{
3340 StreamCreatingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3341 const base::WeakPtr
<SpdySession
>& session
)
3342 : StreamDelegateDoNothing(stream
),
3343 session_(session
) {}
3345 ~StreamCreatingDelegate() override
{}
3347 void OnClose(int status
) override
{
3348 GURL
url(kDefaultURL
);
3350 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3351 session_
, url
, MEDIUM
, BoundNetLog()));
3355 const base::WeakPtr
<SpdySession
> session_
;
3358 // Create another stream in response to a stream being reset. Nothing
3359 // should blow up. This is a regression test for
3360 // http://crbug.com/263690 .
3361 TEST_P(SpdySessionTest
, CreateStreamOnStreamReset
) {
3362 session_deps_
.host_resolver
->set_synchronous_mode(true);
3364 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3366 scoped_ptr
<SpdyFrame
> req(
3367 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
3368 MockWrite writes
[] = {
3369 CreateMockWrite(*req
, 0),
3372 scoped_ptr
<SpdyFrame
> rst(
3373 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
3374 MockRead reads
[] = {
3375 CreateMockRead(*rst
, 1),
3376 MockRead(ASYNC
, 0, 2) // EOF
3378 DeterministicSocketData
data(reads
, arraysize(reads
),
3379 writes
, arraysize(writes
));
3380 data
.set_connect_data(connect_data
);
3381 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3383 CreateDeterministicNetworkSession();
3385 base::WeakPtr
<SpdySession
> session
=
3386 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3388 GURL
url(kDefaultURL
);
3389 base::WeakPtr
<SpdyStream
> spdy_stream
=
3390 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3391 session
, url
, MEDIUM
, BoundNetLog());
3392 ASSERT_TRUE(spdy_stream
.get() != NULL
);
3393 EXPECT_EQ(0u, spdy_stream
->stream_id());
3395 StreamCreatingDelegate
delegate(spdy_stream
, session
);
3396 spdy_stream
->SetDelegate(&delegate
);
3398 scoped_ptr
<SpdyHeaderBlock
> headers(
3399 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
3400 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
3401 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
3403 EXPECT_EQ(0u, spdy_stream
->stream_id());
3407 EXPECT_EQ(1u, spdy_stream
->stream_id());
3409 // Cause the stream to be reset, which should cause another stream
3413 EXPECT_EQ(NULL
, spdy_stream
.get());
3414 EXPECT_TRUE(delegate
.StreamIsClosed());
3415 EXPECT_EQ(0u, session
->num_active_streams());
3416 EXPECT_EQ(1u, session
->num_created_streams());
3419 // The tests below are only for SPDY/3 and above.
3421 TEST_P(SpdySessionTest
, UpdateStreamsSendWindowSize
) {
3422 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3424 SettingsMap new_settings
;
3425 int32 window_size
= 1;
3426 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
3427 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, window_size
);
3429 // Set up the socket so we read a SETTINGS frame that sets
3430 // INITIAL_WINDOW_SIZE.
3431 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3432 scoped_ptr
<SpdyFrame
> settings_frame(
3433 spdy_util_
.ConstructSpdySettings(new_settings
));
3434 MockRead reads
[] = {
3435 CreateMockRead(*settings_frame
, 0),
3436 MockRead(ASYNC
, 0, 1) // EOF
3439 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
3440 MockWrite writes
[] = {
3441 CreateMockWrite(*settings_ack
, 2),
3444 session_deps_
.host_resolver
->set_synchronous_mode(true);
3446 DeterministicSocketData
data(reads
, arraysize(reads
),
3447 writes
, arraysize(writes
));
3448 data
.set_connect_data(connect_data
);
3449 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3451 CreateDeterministicNetworkSession();
3453 base::WeakPtr
<SpdySession
> session
=
3454 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3455 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3456 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3457 session
, test_url_
, MEDIUM
, BoundNetLog());
3458 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
3459 TestCompletionCallback callback1
;
3460 EXPECT_NE(spdy_stream1
->send_window_size(), window_size
);
3462 data
.RunFor(1); // Process the SETTINGS frame, but not the EOF
3463 base::MessageLoop::current()->RunUntilIdle();
3464 EXPECT_EQ(session
->stream_initial_send_window_size(), window_size
);
3465 EXPECT_EQ(spdy_stream1
->send_window_size(), window_size
);
3467 // Release the first one, this will allow the second to be created.
3468 spdy_stream1
->Cancel();
3469 EXPECT_EQ(NULL
, spdy_stream1
.get());
3471 base::WeakPtr
<SpdyStream
> spdy_stream2
=
3472 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3473 session
, test_url_
, MEDIUM
, BoundNetLog());
3474 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
3475 EXPECT_EQ(spdy_stream2
->send_window_size(), window_size
);
3476 spdy_stream2
->Cancel();
3477 EXPECT_EQ(NULL
, spdy_stream2
.get());
3480 // The tests below are only for SPDY/3.1 and above.
3482 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3483 // adjust the session receive window size for SPDY 3.1 and higher. In
3484 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3485 // sending a WINDOW_UPDATE frame for a large enough delta.
3486 TEST_P(SpdySessionTest
, AdjustRecvWindowSize
) {
3487 if (GetParam() < kProtoSPDY31
)
3490 session_deps_
.host_resolver
->set_synchronous_mode(true);
3492 const int32 initial_window_size
=
3493 SpdySession::GetInitialWindowSize(GetParam());
3494 const int32 delta_window_size
= 100;
3496 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3497 MockRead reads
[] = {
3498 MockRead(ASYNC
, 0, 1) // EOF
3500 scoped_ptr
<SpdyFrame
> window_update(spdy_util_
.ConstructSpdyWindowUpdate(
3501 kSessionFlowControlStreamId
, initial_window_size
+ delta_window_size
));
3502 MockWrite writes
[] = {
3503 CreateMockWrite(*window_update
, 0),
3505 DeterministicSocketData
data(reads
, arraysize(reads
),
3506 writes
, arraysize(writes
));
3507 data
.set_connect_data(connect_data
);
3508 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3510 CreateDeterministicNetworkSession();
3511 base::WeakPtr
<SpdySession
> session
=
3512 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3513 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3514 session
->flow_control_state());
3516 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3517 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3519 session
->IncreaseRecvWindowSize(delta_window_size
);
3520 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3521 session
->session_recv_window_size_
);
3522 EXPECT_EQ(delta_window_size
, session
->session_unacked_recv_window_bytes_
);
3524 // Should trigger sending a WINDOW_UPDATE frame.
3525 session
->IncreaseRecvWindowSize(initial_window_size
);
3526 EXPECT_EQ(initial_window_size
+ delta_window_size
+ initial_window_size
,
3527 session
->session_recv_window_size_
);
3528 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3532 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3533 session
->in_io_loop_
= true;
3534 session
->DecreaseRecvWindowSize(initial_window_size
+ delta_window_size
+
3535 initial_window_size
);
3536 session
->in_io_loop_
= false;
3537 EXPECT_EQ(0, session
->session_recv_window_size_
);
3538 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3541 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3542 // adjust the session send window size when the "enable_spdy_31" flag
3544 TEST_P(SpdySessionTest
, AdjustSendWindowSize
) {
3545 if (GetParam() < kProtoSPDY31
)
3548 session_deps_
.host_resolver
->set_synchronous_mode(true);
3550 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3551 MockRead reads
[] = {
3552 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3554 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3555 data
.set_connect_data(connect_data
);
3556 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3558 CreateNetworkSession();
3559 base::WeakPtr
<SpdySession
> session
=
3560 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3561 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3562 session
->flow_control_state());
3564 const int32 initial_window_size
=
3565 SpdySession::GetInitialWindowSize(GetParam());
3566 const int32 delta_window_size
= 100;
3568 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3570 session
->IncreaseSendWindowSize(delta_window_size
);
3571 EXPECT_EQ(initial_window_size
+ delta_window_size
,
3572 session
->session_send_window_size_
);
3574 session
->DecreaseSendWindowSize(delta_window_size
);
3575 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3578 // Incoming data for an inactive stream should not cause the session
3579 // receive window size to decrease, but it should cause the unacked
3580 // bytes to increase.
3581 TEST_P(SpdySessionTest
, SessionFlowControlInactiveStream
) {
3582 if (GetParam() < kProtoSPDY31
)
3585 session_deps_
.host_resolver
->set_synchronous_mode(true);
3587 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3588 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(1, false));
3589 MockRead reads
[] = {
3590 CreateMockRead(*resp
, 0),
3591 MockRead(ASYNC
, 0, 1) // EOF
3593 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
3594 data
.set_connect_data(connect_data
);
3595 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3597 CreateDeterministicNetworkSession();
3598 base::WeakPtr
<SpdySession
> session
=
3599 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3600 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3601 session
->flow_control_state());
3603 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3604 session
->session_recv_window_size_
);
3605 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3609 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3610 session
->session_recv_window_size_
);
3611 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
3616 // The frame header is not included in flow control, but frame payload
3617 // (including optional pad length and padding) is.
3618 TEST_P(SpdySessionTest
, SessionFlowControlPadding
) {
3619 // Padding only exists in HTTP/2.
3620 if (GetParam() < kProtoSPDY4MinimumVersion
)
3623 session_deps_
.host_resolver
->set_synchronous_mode(true);
3625 const int padding_length
= 42;
3626 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3627 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(
3628 1, kUploadData
, kUploadDataSize
, false, padding_length
));
3629 MockRead reads
[] = {
3630 CreateMockRead(*resp
, 0), MockRead(ASYNC
, 0, 1) // EOF
3632 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
3633 data
.set_connect_data(connect_data
);
3634 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3636 CreateDeterministicNetworkSession();
3637 base::WeakPtr
<SpdySession
> session
=
3638 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3639 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3640 session
->flow_control_state());
3642 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3643 session
->session_recv_window_size_
);
3644 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3648 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3649 session
->session_recv_window_size_
);
3650 EXPECT_EQ(kUploadDataSize
+ padding_length
,
3651 session
->session_unacked_recv_window_bytes_
);
3656 // A delegate that drops any received data.
3657 class DropReceivedDataDelegate
: public test::StreamDelegateSendImmediate
{
3659 DropReceivedDataDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3660 base::StringPiece data
)
3661 : StreamDelegateSendImmediate(stream
, data
) {}
3663 ~DropReceivedDataDelegate() override
{}
3665 // Drop any received data.
3666 void OnDataReceived(scoped_ptr
<SpdyBuffer
> buffer
) override
{}
3669 // Send data back and forth but use a delegate that drops its received
3670 // data. The receive window should still increase to its original
3671 // value, i.e. we shouldn't "leak" receive window bytes.
3672 TEST_P(SpdySessionTest
, SessionFlowControlNoReceiveLeaks
) {
3673 if (GetParam() < kProtoSPDY31
)
3676 const char kStreamUrl
[] = "http://www.google.com/";
3678 const int32 msg_data_size
= 100;
3679 const std::string
msg_data(msg_data_size
, 'a');
3681 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3683 scoped_ptr
<SpdyFrame
> req(
3684 spdy_util_
.ConstructSpdyPost(
3685 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3686 scoped_ptr
<SpdyFrame
> msg(
3687 spdy_util_
.ConstructSpdyBodyFrame(
3688 1, msg_data
.data(), msg_data_size
, false));
3689 MockWrite writes
[] = {
3690 CreateMockWrite(*req
, 0),
3691 CreateMockWrite(*msg
, 2),
3694 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3695 scoped_ptr
<SpdyFrame
> echo(
3696 spdy_util_
.ConstructSpdyBodyFrame(
3697 1, msg_data
.data(), msg_data_size
, false));
3698 scoped_ptr
<SpdyFrame
> window_update(
3699 spdy_util_
.ConstructSpdyWindowUpdate(
3700 kSessionFlowControlStreamId
, msg_data_size
));
3701 MockRead reads
[] = {
3702 CreateMockRead(*resp
, 1),
3703 CreateMockRead(*echo
, 3),
3704 MockRead(ASYNC
, 0, 4) // EOF
3707 // Create SpdySession and SpdyStream and send the request.
3708 DeterministicSocketData
data(reads
, arraysize(reads
),
3709 writes
, arraysize(writes
));
3710 data
.set_connect_data(connect_data
);
3711 session_deps_
.host_resolver
->set_synchronous_mode(true);
3712 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3714 CreateDeterministicNetworkSession();
3716 base::WeakPtr
<SpdySession
> session
=
3717 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3719 GURL
url(kStreamUrl
);
3720 base::WeakPtr
<SpdyStream
> stream
=
3721 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3722 session
, url
, MEDIUM
, BoundNetLog());
3723 ASSERT_TRUE(stream
.get() != NULL
);
3724 EXPECT_EQ(0u, stream
->stream_id());
3726 DropReceivedDataDelegate
delegate(stream
, msg_data
);
3727 stream
->SetDelegate(&delegate
);
3729 scoped_ptr
<SpdyHeaderBlock
> headers(
3730 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3731 EXPECT_EQ(ERR_IO_PENDING
,
3732 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3733 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3735 const int32 initial_window_size
=
3736 SpdySession::GetInitialWindowSize(GetParam());
3737 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3738 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3742 EXPECT_TRUE(data
.at_write_eof());
3743 EXPECT_TRUE(data
.at_read_eof());
3745 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3746 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3749 EXPECT_EQ(NULL
, stream
.get());
3751 EXPECT_EQ(OK
, delegate
.WaitForClose());
3753 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3754 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3757 // Send data back and forth but close the stream before its data frame
3758 // can be written to the socket. The send window should then increase
3759 // to its original value, i.e. we shouldn't "leak" send window bytes.
3760 TEST_P(SpdySessionTest
, SessionFlowControlNoSendLeaks
) {
3761 if (GetParam() < kProtoSPDY31
)
3764 const char kStreamUrl
[] = "http://www.google.com/";
3766 const int32 msg_data_size
= 100;
3767 const std::string
msg_data(msg_data_size
, 'a');
3769 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3771 scoped_ptr
<SpdyFrame
> req(
3772 spdy_util_
.ConstructSpdyPost(
3773 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3774 MockWrite writes
[] = {
3775 CreateMockWrite(*req
, 0),
3778 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3779 MockRead reads
[] = {
3780 CreateMockRead(*resp
, 1),
3781 MockRead(ASYNC
, 0, 2) // EOF
3784 // Create SpdySession and SpdyStream and send the request.
3785 DeterministicSocketData
data(reads
, arraysize(reads
),
3786 writes
, arraysize(writes
));
3787 data
.set_connect_data(connect_data
);
3788 session_deps_
.host_resolver
->set_synchronous_mode(true);
3789 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3791 CreateDeterministicNetworkSession();
3793 base::WeakPtr
<SpdySession
> session
=
3794 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3796 GURL
url(kStreamUrl
);
3797 base::WeakPtr
<SpdyStream
> stream
=
3798 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3799 session
, url
, MEDIUM
, BoundNetLog());
3800 ASSERT_TRUE(stream
.get() != NULL
);
3801 EXPECT_EQ(0u, stream
->stream_id());
3803 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3804 stream
->SetDelegate(&delegate
);
3806 scoped_ptr
<SpdyHeaderBlock
> headers(
3807 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3808 EXPECT_EQ(ERR_IO_PENDING
,
3809 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3810 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3812 const int32 initial_window_size
=
3813 SpdySession::GetInitialWindowSize(GetParam());
3814 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3818 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3822 EXPECT_TRUE(data
.at_write_eof());
3823 EXPECT_TRUE(data
.at_read_eof());
3825 EXPECT_EQ(initial_window_size
- msg_data_size
,
3826 session
->session_send_window_size_
);
3828 // Closing the stream should increase the session's send window.
3830 EXPECT_EQ(NULL
, stream
.get());
3832 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3834 EXPECT_EQ(OK
, delegate
.WaitForClose());
3837 // Send data back and forth; the send and receive windows should
3838 // change appropriately.
3839 TEST_P(SpdySessionTest
, SessionFlowControlEndToEnd
) {
3840 if (GetParam() < kProtoSPDY31
)
3843 const char kStreamUrl
[] = "http://www.google.com/";
3845 const int32 msg_data_size
= 100;
3846 const std::string
msg_data(msg_data_size
, 'a');
3848 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3850 scoped_ptr
<SpdyFrame
> req(
3851 spdy_util_
.ConstructSpdyPost(
3852 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3853 scoped_ptr
<SpdyFrame
> msg(
3854 spdy_util_
.ConstructSpdyBodyFrame(
3855 1, msg_data
.data(), msg_data_size
, false));
3856 MockWrite writes
[] = {
3857 CreateMockWrite(*req
, 0),
3858 CreateMockWrite(*msg
, 2),
3861 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3862 scoped_ptr
<SpdyFrame
> echo(
3863 spdy_util_
.ConstructSpdyBodyFrame(
3864 1, msg_data
.data(), msg_data_size
, false));
3865 scoped_ptr
<SpdyFrame
> window_update(
3866 spdy_util_
.ConstructSpdyWindowUpdate(
3867 kSessionFlowControlStreamId
, msg_data_size
));
3868 MockRead reads
[] = {
3869 CreateMockRead(*resp
, 1),
3870 CreateMockRead(*echo
, 3),
3871 CreateMockRead(*window_update
, 4),
3872 MockRead(ASYNC
, 0, 5) // EOF
3875 // Create SpdySession and SpdyStream and send the request.
3876 DeterministicSocketData
data(reads
, arraysize(reads
),
3877 writes
, arraysize(writes
));
3878 data
.set_connect_data(connect_data
);
3879 session_deps_
.host_resolver
->set_synchronous_mode(true);
3880 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3882 CreateDeterministicNetworkSession();
3884 base::WeakPtr
<SpdySession
> session
=
3885 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3887 GURL
url(kStreamUrl
);
3888 base::WeakPtr
<SpdyStream
> stream
=
3889 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3890 session
, url
, MEDIUM
, BoundNetLog());
3891 ASSERT_TRUE(stream
.get() != NULL
);
3892 EXPECT_EQ(0u, stream
->stream_id());
3894 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3895 stream
->SetDelegate(&delegate
);
3897 scoped_ptr
<SpdyHeaderBlock
> headers(
3898 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3899 EXPECT_EQ(ERR_IO_PENDING
,
3900 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3901 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3903 const int32 initial_window_size
=
3904 SpdySession::GetInitialWindowSize(GetParam());
3905 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3906 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3907 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3911 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3912 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3913 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3917 EXPECT_EQ(initial_window_size
- msg_data_size
,
3918 session
->session_send_window_size_
);
3919 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3920 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3924 EXPECT_EQ(initial_window_size
- msg_data_size
,
3925 session
->session_send_window_size_
);
3926 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3927 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3931 EXPECT_EQ(initial_window_size
- msg_data_size
,
3932 session
->session_send_window_size_
);
3933 EXPECT_EQ(initial_window_size
- msg_data_size
,
3934 session
->session_recv_window_size_
);
3935 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3939 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3940 EXPECT_EQ(initial_window_size
- msg_data_size
,
3941 session
->session_recv_window_size_
);
3942 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3944 EXPECT_TRUE(data
.at_write_eof());
3945 EXPECT_TRUE(data
.at_read_eof());
3947 EXPECT_EQ(msg_data
, delegate
.TakeReceivedData());
3949 // Draining the delegate's read queue should increase the session's
3951 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3952 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3953 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3956 EXPECT_EQ(NULL
, stream
.get());
3958 EXPECT_EQ(OK
, delegate
.WaitForClose());
3960 EXPECT_EQ(initial_window_size
, session
->session_send_window_size_
);
3961 EXPECT_EQ(initial_window_size
, session
->session_recv_window_size_
);
3962 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3965 // Given a stall function and an unstall function, runs a test to make
3966 // sure that a stream resumes after unstall.
3967 void SpdySessionTest::RunResumeAfterUnstallTest(
3968 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
3969 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
3971 const char kStreamUrl
[] = "http://www.google.com/";
3972 GURL
url(kStreamUrl
);
3974 session_deps_
.host_resolver
->set_synchronous_mode(true);
3976 scoped_ptr
<SpdyFrame
> req(
3977 spdy_util_
.ConstructSpdyPost(
3978 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
3979 scoped_ptr
<SpdyFrame
> body(
3980 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
3981 MockWrite writes
[] = {
3982 CreateMockWrite(*req
, 0),
3983 CreateMockWrite(*body
, 1),
3986 scoped_ptr
<SpdyFrame
> resp(
3987 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3988 scoped_ptr
<SpdyFrame
> echo(
3989 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
3990 MockRead reads
[] = {
3991 CreateMockRead(*resp
, 2),
3992 MockRead(ASYNC
, 0, 0, 3), // EOF
3995 DeterministicSocketData
data(reads
, arraysize(reads
),
3996 writes
, arraysize(writes
));
3997 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3998 data
.set_connect_data(connect_data
);
4000 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4002 CreateDeterministicNetworkSession();
4003 base::WeakPtr
<SpdySession
> session
=
4004 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4005 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4006 session
->flow_control_state());
4008 base::WeakPtr
<SpdyStream
> stream
=
4009 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4010 session
, url
, LOWEST
, BoundNetLog());
4011 ASSERT_TRUE(stream
.get() != NULL
);
4013 test::StreamDelegateWithBody
delegate(stream
, kBodyDataStringPiece
);
4014 stream
->SetDelegate(&delegate
);
4016 EXPECT_FALSE(stream
->HasUrlFromHeaders());
4017 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4019 scoped_ptr
<SpdyHeaderBlock
> headers(
4020 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4021 EXPECT_EQ(ERR_IO_PENDING
,
4022 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
4023 EXPECT_TRUE(stream
->HasUrlFromHeaders());
4024 EXPECT_EQ(kStreamUrl
, stream
->GetUrlFromHeaders().spec());
4026 stall_function
.Run(session
.get(), stream
.get());
4030 EXPECT_TRUE(stream
->send_stalled_by_flow_control());
4032 unstall_function
.Run(session
.get(), stream
.get(), kBodyDataSize
);
4034 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
4038 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
4040 EXPECT_TRUE(delegate
.send_headers_completed());
4041 EXPECT_EQ("200", delegate
.GetResponseHeaderValue(":status"));
4042 EXPECT_EQ(std::string(), delegate
.TakeReceivedData());
4043 EXPECT_TRUE(data
.at_write_eof());
4046 // Run the resume-after-unstall test with all possible stall and
4047 // unstall sequences.
4049 TEST_P(SpdySessionTest
, ResumeAfterUnstallSession
) {
4050 if (GetParam() < kProtoSPDY31
)
4053 RunResumeAfterUnstallTest(
4054 base::Bind(&SpdySessionTest::StallSessionOnly
,
4055 base::Unretained(this)),
4056 base::Bind(&SpdySessionTest::UnstallSessionOnly
,
4057 base::Unretained(this)));
4061 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4062 TEST_P(SpdySessionTest
, ResumeAfterUnstallStream
) {
4063 if (GetParam() < kProtoSPDY31
)
4066 RunResumeAfterUnstallTest(
4067 base::Bind(&SpdySessionTest::StallStreamOnly
,
4068 base::Unretained(this)),
4069 base::Bind(&SpdySessionTest::UnstallStreamOnly
,
4070 base::Unretained(this)));
4073 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallSessionStream
) {
4074 if (GetParam() < kProtoSPDY31
)
4077 RunResumeAfterUnstallTest(
4078 base::Bind(&SpdySessionTest::StallSessionStream
,
4079 base::Unretained(this)),
4080 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4081 base::Unretained(this)));
4084 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallSessionStream
) {
4085 if (GetParam() < kProtoSPDY31
)
4088 RunResumeAfterUnstallTest(
4089 base::Bind(&SpdySessionTest::StallStreamSession
,
4090 base::Unretained(this)),
4091 base::Bind(&SpdySessionTest::UnstallSessionStream
,
4092 base::Unretained(this)));
4095 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallStreamSession
) {
4096 if (GetParam() < kProtoSPDY31
)
4099 RunResumeAfterUnstallTest(
4100 base::Bind(&SpdySessionTest::StallStreamSession
,
4101 base::Unretained(this)),
4102 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4103 base::Unretained(this)));
4106 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallStreamSession
) {
4107 if (GetParam() < kProtoSPDY31
)
4110 RunResumeAfterUnstallTest(
4111 base::Bind(&SpdySessionTest::StallSessionStream
,
4112 base::Unretained(this)),
4113 base::Bind(&SpdySessionTest::UnstallStreamSession
,
4114 base::Unretained(this)));
4117 // Cause a stall by reducing the flow control send window to 0. The
4118 // streams should resume in priority order when that window is then
4120 TEST_P(SpdySessionTest
, ResumeByPriorityAfterSendWindowSizeIncrease
) {
4121 if (GetParam() < kProtoSPDY31
)
4124 const char kStreamUrl
[] = "http://www.google.com/";
4125 GURL
url(kStreamUrl
);
4127 session_deps_
.host_resolver
->set_synchronous_mode(true);
4129 scoped_ptr
<SpdyFrame
> req1(
4130 spdy_util_
.ConstructSpdyPost(
4131 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4132 scoped_ptr
<SpdyFrame
> req2(
4133 spdy_util_
.ConstructSpdyPost(
4134 kStreamUrl
, 3, kBodyDataSize
, MEDIUM
, NULL
, 0));
4135 scoped_ptr
<SpdyFrame
> body1(
4136 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
4137 scoped_ptr
<SpdyFrame
> body2(
4138 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4139 MockWrite writes
[] = {
4140 CreateMockWrite(*req1
, 0),
4141 CreateMockWrite(*req2
, 1),
4142 CreateMockWrite(*body2
, 2),
4143 CreateMockWrite(*body1
, 3),
4146 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4147 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4148 MockRead reads
[] = {
4149 CreateMockRead(*resp1
, 4),
4150 CreateMockRead(*resp2
, 5),
4151 MockRead(ASYNC
, 0, 0, 6), // EOF
4154 DeterministicSocketData
data(reads
, arraysize(reads
),
4155 writes
, arraysize(writes
));
4156 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4157 data
.set_connect_data(connect_data
);
4159 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4161 CreateDeterministicNetworkSession();
4162 base::WeakPtr
<SpdySession
> session
=
4163 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4164 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4165 session
->flow_control_state());
4167 base::WeakPtr
<SpdyStream
> stream1
=
4168 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4169 session
, url
, LOWEST
, BoundNetLog());
4170 ASSERT_TRUE(stream1
.get() != NULL
);
4172 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4173 stream1
->SetDelegate(&delegate1
);
4175 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4177 base::WeakPtr
<SpdyStream
> stream2
=
4178 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4179 session
, url
, MEDIUM
, BoundNetLog());
4180 ASSERT_TRUE(stream2
.get() != NULL
);
4182 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4183 stream2
->SetDelegate(&delegate2
);
4185 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4187 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4188 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4190 StallSessionSend(session
.get());
4192 scoped_ptr
<SpdyHeaderBlock
> headers1(
4193 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4194 EXPECT_EQ(ERR_IO_PENDING
,
4195 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4196 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4197 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4200 EXPECT_EQ(1u, stream1
->stream_id());
4201 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4203 scoped_ptr
<SpdyHeaderBlock
> headers2(
4204 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4205 EXPECT_EQ(ERR_IO_PENDING
,
4206 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4207 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4208 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4211 EXPECT_EQ(3u, stream2
->stream_id());
4212 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4214 // This should unstall only stream2.
4215 UnstallSessionSend(session
.get(), kBodyDataSize
);
4217 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4218 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4222 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4223 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4225 // This should then unstall stream1.
4226 UnstallSessionSend(session
.get(), kBodyDataSize
);
4228 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4229 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4233 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4234 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4236 EXPECT_TRUE(delegate1
.send_headers_completed());
4237 EXPECT_EQ("200", delegate1
.GetResponseHeaderValue(":status"));
4238 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4240 EXPECT_TRUE(delegate2
.send_headers_completed());
4241 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4242 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4244 EXPECT_TRUE(data
.at_write_eof());
4247 // Delegate that closes a given stream after sending its body.
4248 class StreamClosingDelegate
: public test::StreamDelegateWithBody
{
4250 StreamClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
4251 base::StringPiece data
)
4252 : StreamDelegateWithBody(stream
, data
) {}
4254 ~StreamClosingDelegate() override
{}
4256 void set_stream_to_close(const base::WeakPtr
<SpdyStream
>& stream_to_close
) {
4257 stream_to_close_
= stream_to_close
;
4260 void OnDataSent() override
{
4261 test::StreamDelegateWithBody::OnDataSent();
4262 if (stream_to_close_
.get()) {
4263 stream_to_close_
->Close();
4264 EXPECT_EQ(NULL
, stream_to_close_
.get());
4269 base::WeakPtr
<SpdyStream
> stream_to_close_
;
4272 // Cause a stall by reducing the flow control send window to
4273 // 0. Unstalling the session should properly handle deleted streams.
4274 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedStreams
) {
4275 if (GetParam() < kProtoSPDY31
)
4278 const char kStreamUrl
[] = "http://www.google.com/";
4279 GURL
url(kStreamUrl
);
4281 session_deps_
.host_resolver
->set_synchronous_mode(true);
4283 scoped_ptr
<SpdyFrame
> req1(
4284 spdy_util_
.ConstructSpdyPost(
4285 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4286 scoped_ptr
<SpdyFrame
> req2(
4287 spdy_util_
.ConstructSpdyPost(
4288 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, NULL
, 0));
4289 scoped_ptr
<SpdyFrame
> req3(
4290 spdy_util_
.ConstructSpdyPost(
4291 kStreamUrl
, 5, kBodyDataSize
, LOWEST
, NULL
, 0));
4292 scoped_ptr
<SpdyFrame
> body2(
4293 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
4294 MockWrite writes
[] = {
4295 CreateMockWrite(*req1
, 0),
4296 CreateMockWrite(*req2
, 1),
4297 CreateMockWrite(*req3
, 2),
4298 CreateMockWrite(*body2
, 3),
4301 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4302 MockRead reads
[] = {
4303 CreateMockRead(*resp2
, 4),
4304 MockRead(ASYNC
, 0, 0, 5), // EOF
4307 DeterministicSocketData
data(reads
, arraysize(reads
),
4308 writes
, arraysize(writes
));
4309 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4310 data
.set_connect_data(connect_data
);
4312 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4314 CreateDeterministicNetworkSession();
4315 base::WeakPtr
<SpdySession
> session
=
4316 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4317 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4318 session
->flow_control_state());
4320 base::WeakPtr
<SpdyStream
> stream1
=
4321 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4322 session
, url
, LOWEST
, BoundNetLog());
4323 ASSERT_TRUE(stream1
.get() != NULL
);
4325 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4326 stream1
->SetDelegate(&delegate1
);
4328 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4330 base::WeakPtr
<SpdyStream
> stream2
=
4331 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4332 session
, url
, LOWEST
, BoundNetLog());
4333 ASSERT_TRUE(stream2
.get() != NULL
);
4335 StreamClosingDelegate
delegate2(stream2
, kBodyDataStringPiece
);
4336 stream2
->SetDelegate(&delegate2
);
4338 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4340 base::WeakPtr
<SpdyStream
> stream3
=
4341 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4342 session
, url
, LOWEST
, BoundNetLog());
4343 ASSERT_TRUE(stream3
.get() != NULL
);
4345 test::StreamDelegateWithBody
delegate3(stream3
, kBodyDataStringPiece
);
4346 stream3
->SetDelegate(&delegate3
);
4348 EXPECT_FALSE(stream3
->HasUrlFromHeaders());
4350 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4351 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4352 EXPECT_FALSE(stream3
->send_stalled_by_flow_control());
4354 StallSessionSend(session
.get());
4356 scoped_ptr
<SpdyHeaderBlock
> headers1(
4357 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4358 EXPECT_EQ(ERR_IO_PENDING
,
4359 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4360 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4361 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4364 EXPECT_EQ(1u, stream1
->stream_id());
4365 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4367 scoped_ptr
<SpdyHeaderBlock
> headers2(
4368 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4369 EXPECT_EQ(ERR_IO_PENDING
,
4370 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4371 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4372 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4375 EXPECT_EQ(3u, stream2
->stream_id());
4376 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4378 scoped_ptr
<SpdyHeaderBlock
> headers3(
4379 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4380 EXPECT_EQ(ERR_IO_PENDING
,
4381 stream3
->SendRequestHeaders(headers3
.Pass(), MORE_DATA_TO_SEND
));
4382 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
4383 EXPECT_EQ(kStreamUrl
, stream3
->GetUrlFromHeaders().spec());
4386 EXPECT_EQ(5u, stream3
->stream_id());
4387 EXPECT_TRUE(stream3
->send_stalled_by_flow_control());
4389 SpdyStreamId stream_id1
= stream1
->stream_id();
4390 SpdyStreamId stream_id2
= stream2
->stream_id();
4391 SpdyStreamId stream_id3
= stream3
->stream_id();
4393 // Close stream1 preemptively.
4394 session
->CloseActiveStream(stream_id1
, ERR_CONNECTION_CLOSED
);
4395 EXPECT_EQ(NULL
, stream1
.get());
4397 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4398 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4399 EXPECT_TRUE(session
->IsStreamActive(stream_id3
));
4401 // Unstall stream2, which should then close stream3.
4402 delegate2
.set_stream_to_close(stream3
);
4403 UnstallSessionSend(session
.get(), kBodyDataSize
);
4406 EXPECT_EQ(NULL
, stream3
.get());
4408 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4409 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4410 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4411 EXPECT_FALSE(session
->IsStreamActive(stream_id3
));
4414 EXPECT_EQ(NULL
, stream2
.get());
4416 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4417 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4418 EXPECT_EQ(OK
, delegate3
.WaitForClose());
4420 EXPECT_TRUE(delegate1
.send_headers_completed());
4421 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4423 EXPECT_TRUE(delegate2
.send_headers_completed());
4424 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4425 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4427 EXPECT_TRUE(delegate3
.send_headers_completed());
4428 EXPECT_EQ(std::string(), delegate3
.TakeReceivedData());
4430 EXPECT_TRUE(data
.at_write_eof());
4433 // Cause a stall by reducing the flow control send window to
4434 // 0. Unstalling the session should properly handle the session itself
4436 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedSession
) {
4437 if (GetParam() < kProtoSPDY31
)
4440 const char kStreamUrl
[] = "http://www.google.com/";
4441 GURL
url(kStreamUrl
);
4443 session_deps_
.host_resolver
->set_synchronous_mode(true);
4445 scoped_ptr
<SpdyFrame
> req1(
4446 spdy_util_
.ConstructSpdyPost(
4447 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4448 scoped_ptr
<SpdyFrame
> req2(
4449 spdy_util_
.ConstructSpdyPost(
4450 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, NULL
, 0));
4451 scoped_ptr
<SpdyFrame
> body1(
4452 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4453 MockWrite writes
[] = {
4454 CreateMockWrite(*req1
, 0),
4455 CreateMockWrite(*req2
, 1),
4458 MockRead reads
[] = {
4459 MockRead(ASYNC
, 0, 0, 2), // EOF
4462 DeterministicSocketData
data(reads
, arraysize(reads
),
4463 writes
, arraysize(writes
));
4464 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4465 data
.set_connect_data(connect_data
);
4467 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4469 CreateDeterministicNetworkSession();
4470 base::WeakPtr
<SpdySession
> session
=
4471 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4472 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4473 session
->flow_control_state());
4475 base::WeakPtr
<SpdyStream
> stream1
=
4476 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4477 session
, url
, LOWEST
, BoundNetLog());
4478 ASSERT_TRUE(stream1
.get() != NULL
);
4480 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4481 stream1
->SetDelegate(&delegate1
);
4483 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4485 base::WeakPtr
<SpdyStream
> stream2
=
4486 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4487 session
, url
, LOWEST
, BoundNetLog());
4488 ASSERT_TRUE(stream2
.get() != NULL
);
4490 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4491 stream2
->SetDelegate(&delegate2
);
4493 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4495 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4496 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4498 StallSessionSend(session
.get());
4500 scoped_ptr
<SpdyHeaderBlock
> headers1(
4501 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4502 EXPECT_EQ(ERR_IO_PENDING
,
4503 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4504 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4505 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4508 EXPECT_EQ(1u, stream1
->stream_id());
4509 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4511 scoped_ptr
<SpdyHeaderBlock
> headers2(
4512 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4513 EXPECT_EQ(ERR_IO_PENDING
,
4514 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4515 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4516 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4519 EXPECT_EQ(3u, stream2
->stream_id());
4520 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4522 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
4525 UnstallSessionSend(session
.get(), kBodyDataSize
);
4527 // Close the session (since we can't do it from within the delegate
4528 // method, since it's in the stream's loop).
4529 session
->CloseSessionOnError(ERR_CONNECTION_CLOSED
, "Closing session");
4530 base::RunLoop().RunUntilIdle();
4531 EXPECT_TRUE(session
== NULL
);
4533 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
4535 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4536 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4538 EXPECT_TRUE(delegate1
.send_headers_completed());
4539 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4541 EXPECT_TRUE(delegate2
.send_headers_completed());
4542 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4544 EXPECT_TRUE(data
.at_write_eof());
4547 TEST_P(SpdySessionTest
, GoAwayOnSessionFlowControlError
) {
4548 if (GetParam() < kProtoSPDY31
)
4551 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4553 scoped_ptr
<SpdyFrame
> req(
4554 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4555 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(
4557 GOAWAY_FLOW_CONTROL_ERROR
,
4558 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4559 "the receive window size of 1"));
4560 MockWrite writes
[] = {
4561 CreateMockWrite(*req
, 0), CreateMockWrite(*goaway
, 3),
4564 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4565 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
4566 MockRead reads
[] = {
4567 CreateMockRead(*resp
, 1), CreateMockRead(*body
, 2),
4570 DeterministicSocketData
data(
4571 reads
, arraysize(reads
), writes
, arraysize(writes
));
4572 data
.set_connect_data(connect_data
);
4573 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4575 CreateDeterministicNetworkSession();
4577 base::WeakPtr
<SpdySession
> session
=
4578 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4580 GURL
url(kDefaultURL
);
4581 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
4582 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, LOWEST
, BoundNetLog());
4583 ASSERT_TRUE(spdy_stream
.get() != NULL
);
4584 test::StreamDelegateDoNothing
delegate(spdy_stream
);
4585 spdy_stream
->SetDelegate(&delegate
);
4587 scoped_ptr
<SpdyHeaderBlock
> headers(
4588 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
4589 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4591 data
.RunFor(1); // Write request.
4593 // Put session on the edge of overflowing it's recv window.
4594 session
->session_recv_window_size_
= 1;
4596 // Read response headers & body. Body overflows the session window, and a
4597 // goaway is written.
4599 base::MessageLoop::current()->RunUntilIdle();
4601 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR
, delegate
.WaitForClose());
4602 EXPECT_TRUE(session
== NULL
);
4605 TEST_P(SpdySessionTest
, SplitHeaders
) {
4606 GURL
kStreamUrl("http://www.google.com/foo.dat");
4607 SpdyHeaderBlock headers
;
4608 spdy_util_
.AddUrlToHeaderBlock(kStreamUrl
.spec(), &headers
);
4609 headers
["alpha"] = "beta";
4611 SpdyHeaderBlock request_headers
;
4612 SpdyHeaderBlock response_headers
;
4614 SplitPushedHeadersToRequestAndResponse(
4615 headers
, spdy_util_
.spdy_version(), &request_headers
, &response_headers
);
4617 SpdyHeaderBlock::const_iterator it
= response_headers
.find("alpha");
4618 std::string alpha_val
=
4619 (it
== response_headers
.end()) ? std::string() : it
->second
;
4620 EXPECT_EQ("beta", alpha_val
);
4623 GetUrlFromHeaderBlock(request_headers
, spdy_util_
.spdy_version(), true);
4624 EXPECT_EQ(kStreamUrl
, request_url
);
4627 // Regression. Sorta. Push streams and client streams were sharing a single
4628 // limit for a long time.
4629 TEST_P(SpdySessionTest
, PushedStreamShouldNotCountToClientConcurrencyLimit
) {
4630 SettingsMap new_settings
;
4631 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
4632 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, 2);
4633 scoped_ptr
<SpdyFrame
> settings_frame(
4634 spdy_util_
.ConstructSpdySettings(new_settings
));
4635 scoped_ptr
<SpdyFrame
> pushed(spdy_util_
.ConstructSpdyPush(
4636 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4637 MockRead reads
[] = {
4638 CreateMockRead(*settings_frame
), CreateMockRead(*pushed
, 3),
4639 MockRead(ASYNC
, 0, 4),
4642 scoped_ptr
<SpdyFrame
> settings_ack(spdy_util_
.ConstructSpdySettingsAck());
4643 scoped_ptr
<SpdyFrame
> req(
4644 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4645 MockWrite writes
[] = {
4646 CreateMockWrite(*settings_ack
, 1), CreateMockWrite(*req
, 2),
4649 DeterministicSocketData
data(
4650 reads
, arraysize(reads
), writes
, arraysize(writes
));
4651 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4652 data
.set_connect_data(connect_data
);
4653 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4655 CreateDeterministicNetworkSession();
4657 base::WeakPtr
<SpdySession
> session
=
4658 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4660 // Read the settings frame.
4663 GURL
url1(kDefaultURL
);
4664 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4665 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4666 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4667 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4668 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4669 spdy_stream1
->SetDelegate(&delegate1
);
4671 EXPECT_EQ(0u, session
->num_active_streams());
4672 EXPECT_EQ(1u, session
->num_created_streams());
4673 EXPECT_EQ(0u, session
->num_pushed_streams());
4674 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4676 scoped_ptr
<SpdyHeaderBlock
> headers(
4677 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4678 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4679 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4681 // Run until 1st stream is activated.
4682 EXPECT_EQ(0u, delegate1
.stream_id());
4684 EXPECT_EQ(1u, delegate1
.stream_id());
4685 EXPECT_EQ(1u, session
->num_active_streams());
4686 EXPECT_EQ(0u, session
->num_created_streams());
4687 EXPECT_EQ(0u, session
->num_pushed_streams());
4688 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4690 // Run until pushed stream is created.
4692 EXPECT_EQ(2u, session
->num_active_streams());
4693 EXPECT_EQ(0u, session
->num_created_streams());
4694 EXPECT_EQ(1u, session
->num_pushed_streams());
4695 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4697 // Second stream should not be stalled, although we have 2 active streams, but
4698 // one of them is push stream and should not be taken into account when we
4699 // create streams on the client.
4700 base::WeakPtr
<SpdyStream
> spdy_stream2
= CreateStreamSynchronously(
4701 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4702 EXPECT_TRUE(spdy_stream2
.get() != NULL
);
4703 EXPECT_EQ(2u, session
->num_active_streams());
4704 EXPECT_EQ(1u, session
->num_created_streams());
4705 EXPECT_EQ(1u, session
->num_pushed_streams());
4706 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4712 TEST_P(SpdySessionTest
, RejectPushedStreamExceedingConcurrencyLimit
) {
4713 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4714 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4715 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
4716 NULL
, 0, 4, 1, "http://www.google.com/b.dat"));
4717 MockRead reads
[] = {
4718 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
4719 MockRead(ASYNC
, 0, 4),
4722 scoped_ptr
<SpdyFrame
> req(
4723 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4724 scoped_ptr
<SpdyFrame
> rst(
4725 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4726 MockWrite writes
[] = {
4727 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 3),
4730 DeterministicSocketData
data(
4731 reads
, arraysize(reads
), writes
, arraysize(writes
));
4732 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4733 data
.set_connect_data(connect_data
);
4734 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4736 CreateDeterministicNetworkSession();
4738 base::WeakPtr
<SpdySession
> session
=
4739 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4740 session
->set_max_concurrent_pushed_streams(1);
4742 GURL
url1(kDefaultURL
);
4743 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4744 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4745 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4746 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4747 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4748 spdy_stream1
->SetDelegate(&delegate1
);
4750 EXPECT_EQ(0u, session
->num_active_streams());
4751 EXPECT_EQ(1u, session
->num_created_streams());
4752 EXPECT_EQ(0u, session
->num_pushed_streams());
4753 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4755 scoped_ptr
<SpdyHeaderBlock
> headers(
4756 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4757 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4758 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4760 // Run until 1st stream is activated.
4761 EXPECT_EQ(0u, delegate1
.stream_id());
4763 EXPECT_EQ(1u, delegate1
.stream_id());
4764 EXPECT_EQ(1u, session
->num_active_streams());
4765 EXPECT_EQ(0u, session
->num_created_streams());
4766 EXPECT_EQ(0u, session
->num_pushed_streams());
4767 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4769 // Run until pushed stream is created.
4771 EXPECT_EQ(2u, session
->num_active_streams());
4772 EXPECT_EQ(0u, session
->num_created_streams());
4773 EXPECT_EQ(1u, session
->num_pushed_streams());
4774 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4776 // Reset incoming pushed stream.
4778 EXPECT_EQ(2u, session
->num_active_streams());
4779 EXPECT_EQ(0u, session
->num_created_streams());
4780 EXPECT_EQ(1u, session
->num_pushed_streams());
4781 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4787 TEST_P(SpdySessionTest
, IgnoreReservedRemoteStreamsCount
) {
4788 // Streams in reserved remote state exist only in SPDY4.
4789 if (spdy_util_
.spdy_version() < SPDY4
)
4792 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
4793 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
4794 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4795 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/b.dat",
4796 push_headers
.get());
4797 scoped_ptr
<SpdyFrame
> push_b(
4798 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 4, 1));
4799 scoped_ptr
<SpdyFrame
> headers_b(
4800 spdy_util_
.ConstructSpdyPushHeaders(4, NULL
, 0));
4801 MockRead reads
[] = {
4802 CreateMockRead(*push_a
, 1), CreateMockRead(*push_b
, 2),
4803 CreateMockRead(*headers_b
, 3), MockRead(ASYNC
, 0, 5),
4806 scoped_ptr
<SpdyFrame
> req(
4807 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4808 scoped_ptr
<SpdyFrame
> rst(
4809 spdy_util_
.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM
));
4810 MockWrite writes
[] = {
4811 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 4),
4814 DeterministicSocketData
data(
4815 reads
, arraysize(reads
), writes
, arraysize(writes
));
4816 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4817 data
.set_connect_data(connect_data
);
4818 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4820 CreateDeterministicNetworkSession();
4822 base::WeakPtr
<SpdySession
> session
=
4823 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4824 session
->set_max_concurrent_pushed_streams(1);
4826 GURL
url1(kDefaultURL
);
4827 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4828 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4829 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4830 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4831 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4832 spdy_stream1
->SetDelegate(&delegate1
);
4834 EXPECT_EQ(0u, session
->num_active_streams());
4835 EXPECT_EQ(1u, session
->num_created_streams());
4836 EXPECT_EQ(0u, session
->num_pushed_streams());
4837 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4839 scoped_ptr
<SpdyHeaderBlock
> headers(
4840 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4841 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4842 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4844 // Run until 1st stream is activated.
4845 EXPECT_EQ(0u, delegate1
.stream_id());
4847 EXPECT_EQ(1u, delegate1
.stream_id());
4848 EXPECT_EQ(1u, session
->num_active_streams());
4849 EXPECT_EQ(0u, session
->num_created_streams());
4850 EXPECT_EQ(0u, session
->num_pushed_streams());
4851 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4853 // Run until pushed stream is created.
4855 EXPECT_EQ(2u, session
->num_active_streams());
4856 EXPECT_EQ(0u, session
->num_created_streams());
4857 EXPECT_EQ(1u, session
->num_pushed_streams());
4858 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4860 // Accept promised stream. It should not count towards pushed stream limit.
4862 EXPECT_EQ(3u, session
->num_active_streams());
4863 EXPECT_EQ(0u, session
->num_created_streams());
4864 EXPECT_EQ(2u, session
->num_pushed_streams());
4865 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4867 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4868 // while we accept only one.
4870 EXPECT_EQ(2u, session
->num_active_streams());
4871 EXPECT_EQ(0u, session
->num_created_streams());
4872 EXPECT_EQ(1u, session
->num_pushed_streams());
4873 EXPECT_EQ(1u, session
->num_active_pushed_streams());
4879 TEST_P(SpdySessionTest
, CancelReservedStreamOnHeadersReceived
) {
4880 // Streams in reserved remote state exist only in SPDY4.
4881 if (spdy_util_
.spdy_version() < SPDY4
)
4884 const char kPushedUrl
[] = "http://www.google.com/a.dat";
4885 scoped_ptr
<SpdyHeaderBlock
> push_headers(new SpdyHeaderBlock
);
4886 spdy_util_
.AddUrlToHeaderBlock(kPushedUrl
, push_headers
.get());
4887 scoped_ptr
<SpdyFrame
> push_promise(
4888 spdy_util_
.ConstructInitialSpdyPushFrame(push_headers
.Pass(), 2, 1));
4889 scoped_ptr
<SpdyFrame
> headers_frame(
4890 spdy_util_
.ConstructSpdyPushHeaders(2, NULL
, 0));
4891 MockRead reads
[] = {
4892 CreateMockRead(*push_promise
, 1), CreateMockRead(*headers_frame
, 2),
4893 MockRead(ASYNC
, 0, 4),
4896 scoped_ptr
<SpdyFrame
> req(
4897 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
4898 scoped_ptr
<SpdyFrame
> rst(
4899 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_CANCEL
));
4900 MockWrite writes
[] = {
4901 CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 3),
4904 DeterministicSocketData
data(
4905 reads
, arraysize(reads
), writes
, arraysize(writes
));
4906 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4907 data
.set_connect_data(connect_data
);
4908 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4910 CreateDeterministicNetworkSession();
4912 base::WeakPtr
<SpdySession
> session
=
4913 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4915 GURL
url1(kDefaultURL
);
4916 base::WeakPtr
<SpdyStream
> spdy_stream1
= CreateStreamSynchronously(
4917 SPDY_REQUEST_RESPONSE_STREAM
, session
, url1
, LOWEST
, BoundNetLog());
4918 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
4919 EXPECT_EQ(0u, spdy_stream1
->stream_id());
4920 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
4921 spdy_stream1
->SetDelegate(&delegate1
);
4923 EXPECT_EQ(0u, session
->num_active_streams());
4924 EXPECT_EQ(1u, session
->num_created_streams());
4925 EXPECT_EQ(0u, session
->num_pushed_streams());
4926 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4928 scoped_ptr
<SpdyHeaderBlock
> headers(
4929 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
4930 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
4931 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
4933 // Run until 1st stream is activated.
4934 EXPECT_EQ(0u, delegate1
.stream_id());
4936 EXPECT_EQ(1u, delegate1
.stream_id());
4937 EXPECT_EQ(1u, session
->num_active_streams());
4938 EXPECT_EQ(0u, session
->num_created_streams());
4939 EXPECT_EQ(0u, session
->num_pushed_streams());
4940 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4942 // Run until pushed stream is created.
4944 EXPECT_EQ(2u, session
->num_active_streams());
4945 EXPECT_EQ(0u, session
->num_created_streams());
4946 EXPECT_EQ(1u, session
->num_pushed_streams());
4947 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4949 base::WeakPtr
<SpdyStream
> pushed_stream
;
4951 session
->GetPushStream(GURL(kPushedUrl
), &pushed_stream
, BoundNetLog());
4953 ASSERT_TRUE(pushed_stream
.get() != NULL
);
4954 test::StreamDelegateCloseOnHeaders
delegate2(pushed_stream
);
4955 pushed_stream
->SetDelegate(&delegate2
);
4957 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4958 // that all our counters are in consistent state.
4960 EXPECT_EQ(1u, session
->num_active_streams());
4961 EXPECT_EQ(0u, session
->num_created_streams());
4962 EXPECT_EQ(0u, session
->num_pushed_streams());
4963 EXPECT_EQ(0u, session
->num_active_pushed_streams());
4969 TEST_P(SpdySessionTest
, RejectInvalidUnknownFrames
) {
4970 session_deps_
.host_resolver
->set_synchronous_mode(true);
4972 MockRead reads
[] = {
4973 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
4976 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
4978 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4979 data
.set_connect_data(connect_data
);
4980 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4982 CreateNetworkSession();
4983 base::WeakPtr
<SpdySession
> session
=
4984 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4986 session
->stream_hi_water_mark_
= 5;
4987 // Low client (odd) ids are fine.
4988 EXPECT_TRUE(session
->OnUnknownFrame(3, 0));
4989 // Client id exceeding watermark.
4990 EXPECT_FALSE(session
->OnUnknownFrame(9, 0));
4992 session
->last_accepted_push_stream_id_
= 6;
4993 // Low server (even) ids are fine.
4994 EXPECT_TRUE(session
->OnUnknownFrame(2, 0));
4995 // Server id exceeding last accepted id.
4996 EXPECT_FALSE(session
->OnUnknownFrame(8, 0));
4999 TEST(MapFramerErrorToProtocolError
, MapsValues
) {
5001 SPDY_ERROR_INVALID_CONTROL_FRAME
,
5002 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
5004 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS
,
5005 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
5007 SPDY_ERROR_GOAWAY_FRAME_CORRUPT
,
5008 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT
));
5009 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME
,
5010 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME
));
5013 TEST(MapFramerErrorToNetError
, MapsValue
) {
5014 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR
,
5015 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
5016 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
5017 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE
));
5018 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR
,
5019 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE
));
5021 ERR_SPDY_FRAME_SIZE_ERROR
,
5022 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE
));
5025 TEST(MapRstStreamStatusToProtocolError
, MapsValues
) {
5026 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR
,
5027 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR
));
5028 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR
,
5029 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR
));
5030 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM
,
5031 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM
));
5032 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY
,
5033 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY
));
5034 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED
,
5035 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED
));
5038 TEST(MapNetErrorToGoAwayStatus
, MapsValue
) {
5039 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY
,
5040 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
));
5041 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR
,
5042 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR
));
5043 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
,
5044 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR
));
5045 CHECK_EQ(GOAWAY_COMPRESSION_ERROR
,
5046 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR
));
5047 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR
,
5048 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR
));
5049 CHECK_EQ(GOAWAY_PROTOCOL_ERROR
, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED
));
5052 TEST(CanPoolTest
, CanPool
) {
5053 // Load a cert that is valid for:
5058 TransportSecurityState tss
;
5060 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5061 "spdy_pooling.pem");
5063 EXPECT_TRUE(SpdySession::CanPool(
5064 &tss
, ssl_info
, "www.example.org", "www.example.org"));
5065 EXPECT_TRUE(SpdySession::CanPool(
5066 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5067 EXPECT_TRUE(SpdySession::CanPool(
5068 &tss
, ssl_info
, "www.example.org", "mail.example.com"));
5069 EXPECT_FALSE(SpdySession::CanPool(
5070 &tss
, ssl_info
, "www.example.org", "mail.google.com"));
5073 TEST(CanPoolTest
, CanNotPoolWithCertErrors
) {
5074 // Load a cert that is valid for:
5079 TransportSecurityState tss
;
5081 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5082 "spdy_pooling.pem");
5083 ssl_info
.cert_status
= CERT_STATUS_REVOKED
;
5085 EXPECT_FALSE(SpdySession::CanPool(
5086 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5089 TEST(CanPoolTest
, CanNotPoolWithClientCerts
) {
5090 // Load a cert that is valid for:
5095 TransportSecurityState tss
;
5097 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5098 "spdy_pooling.pem");
5099 ssl_info
.client_cert_sent
= true;
5101 EXPECT_FALSE(SpdySession::CanPool(
5102 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5105 TEST(CanPoolTest
, CanNotPoolAcrossETLDsWithChannelID
) {
5106 // Load a cert that is valid for:
5111 TransportSecurityState tss
;
5113 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5114 "spdy_pooling.pem");
5115 ssl_info
.channel_id_sent
= true;
5117 EXPECT_TRUE(SpdySession::CanPool(
5118 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5119 EXPECT_FALSE(SpdySession::CanPool(
5120 &tss
, ssl_info
, "www.example.org", "www.example.com"));
5123 TEST(CanPoolTest
, CanNotPoolWithBadPins
) {
5124 uint8 primary_pin
= 1;
5125 uint8 backup_pin
= 2;
5127 TransportSecurityState tss
;
5128 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5131 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5132 "spdy_pooling.pem");
5133 ssl_info
.is_issued_by_known_root
= true;
5134 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(bad_pin
));
5136 EXPECT_FALSE(SpdySession::CanPool(
5137 &tss
, ssl_info
, "www.example.org", "mail.example.org"));
5140 TEST(CanPoolTest
, CanPoolWithAcceptablePins
) {
5141 uint8 primary_pin
= 1;
5142 uint8 backup_pin
= 2;
5143 TransportSecurityState tss
;
5144 test::AddPin(&tss
, "mail.example.org", primary_pin
, backup_pin
);
5147 ssl_info
.cert
= ImportCertFromFile(GetTestCertsDirectory(),
5148 "spdy_pooling.pem");
5149 ssl_info
.is_issued_by_known_root
= true;
5150 ssl_info
.public_key_hashes
.push_back(test::GetTestHashValue(primary_pin
));
5152 EXPECT_TRUE(SpdySession::CanPool(
5153 &tss
, ssl_info
, "www.example.org", "mail.example.org"));