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"
8 #include "base/callback.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "net/base/io_buffer.h"
12 #include "net/base/ip_endpoint.h"
13 #include "net/base/net_log_unittest.h"
14 #include "net/base/request_priority.h"
15 #include "net/base/test_data_directory.h"
16 #include "net/base/test_data_stream.h"
17 #include "net/socket/client_socket_pool_manager.h"
18 #include "net/socket/next_proto.h"
19 #include "net/socket/socket_test_util.h"
20 #include "net/spdy/spdy_http_utils.h"
21 #include "net/spdy/spdy_session_pool.h"
22 #include "net/spdy/spdy_session_test_util.h"
23 #include "net/spdy/spdy_stream.h"
24 #include "net/spdy/spdy_stream_test_util.h"
25 #include "net/spdy/spdy_test_util_common.h"
26 #include "net/spdy/spdy_test_utils.h"
27 #include "net/test/cert_test_util.h"
28 #include "testing/platform_test.h"
34 static const char kTestUrl
[] = "http://www.example.org/";
35 static const char kTestHost
[] = "www.example.org";
36 static const int kTestPort
= 80;
38 const char kBodyData
[] = "Body data";
39 const size_t kBodyDataSize
= arraysize(kBodyData
);
40 const base::StringPiece
kBodyDataStringPiece(kBodyData
, kBodyDataSize
);
42 static base::TimeDelta g_time_delta
;
43 base::TimeTicks
TheNearFuture() {
44 return base::TimeTicks::Now() + g_time_delta
;
49 class SpdySessionTest
: public PlatformTest
,
50 public ::testing::WithParamInterface
<NextProto
> {
52 // Functions used with RunResumeAfterUnstallTest().
54 void StallSessionOnly(SpdySession
* session
, SpdyStream
* stream
) {
55 StallSessionSend(session
);
58 void StallStreamOnly(SpdySession
* session
, SpdyStream
* stream
) {
59 StallStreamSend(stream
);
62 void StallSessionStream(SpdySession
* session
, SpdyStream
* stream
) {
63 StallSessionSend(session
);
64 StallStreamSend(stream
);
67 void StallStreamSession(SpdySession
* session
, SpdyStream
* stream
) {
68 StallStreamSend(stream
);
69 StallSessionSend(session
);
72 void UnstallSessionOnly(SpdySession
* session
,
74 int32 delta_window_size
) {
75 UnstallSessionSend(session
, delta_window_size
);
78 void UnstallStreamOnly(SpdySession
* session
,
80 int32 delta_window_size
) {
81 UnstallStreamSend(stream
, delta_window_size
);
84 void UnstallSessionStream(SpdySession
* session
,
86 int32 delta_window_size
) {
87 UnstallSessionSend(session
, delta_window_size
);
88 UnstallStreamSend(stream
, delta_window_size
);
91 void UnstallStreamSession(SpdySession
* session
,
93 int32 delta_window_size
) {
94 UnstallStreamSend(stream
, delta_window_size
);
95 UnstallSessionSend(session
, delta_window_size
);
100 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
101 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
102 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
103 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
104 spdy_util_(GetParam()),
105 session_deps_(GetParam()),
106 spdy_session_pool_(NULL
),
108 test_host_port_pair_(kTestHost
, kTestPort
),
109 key_(test_host_port_pair_
, ProxyServer::Direct(),
110 kPrivacyModeDisabled
) {
113 virtual ~SpdySessionTest() {
114 // Important to restore the per-pool limit first, since the pool limit must
115 // always be greater than group limit, and the tests reduce both limits.
116 ClientSocketPoolManager::set_max_sockets_per_pool(
117 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
118 ClientSocketPoolManager::set_max_sockets_per_group(
119 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
122 virtual void SetUp() OVERRIDE
{
123 g_time_delta
= base::TimeDelta();
126 void CreateDeterministicNetworkSession() {
128 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
);
129 spdy_session_pool_
= http_session_
->spdy_session_pool();
132 void CreateNetworkSession() {
134 SpdySessionDependencies::SpdyCreateSession(&session_deps_
);
135 spdy_session_pool_
= http_session_
->spdy_session_pool();
138 void StallSessionSend(SpdySession
* session
) {
139 // Reduce the send window size to 0 to stall.
140 while (session
->session_send_window_size_
> 0) {
141 session
->DecreaseSendWindowSize(
142 std::min(kMaxSpdyFrameChunkSize
, session
->session_send_window_size_
));
146 void UnstallSessionSend(SpdySession
* session
, int32 delta_window_size
) {
147 session
->IncreaseSendWindowSize(delta_window_size
);
150 void StallStreamSend(SpdyStream
* stream
) {
151 // Reduce the send window size to 0 to stall.
152 while (stream
->send_window_size() > 0) {
153 stream
->DecreaseSendWindowSize(
154 std::min(kMaxSpdyFrameChunkSize
, stream
->send_window_size()));
158 void UnstallStreamSend(SpdyStream
* stream
, int32 delta_window_size
) {
159 stream
->IncreaseSendWindowSize(delta_window_size
);
162 void RunResumeAfterUnstallTest(
163 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
164 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
167 // Original socket limits. Some tests set these. Safest to always restore
168 // them once each test has been run.
169 int old_max_group_sockets_
;
170 int old_max_pool_sockets_
;
172 SpdyTestUtil spdy_util_
;
173 SpdySessionDependencies session_deps_
;
174 scoped_refptr
<HttpNetworkSession
> http_session_
;
175 SpdySessionPool
* spdy_session_pool_
;
177 HostPortPair test_host_port_pair_
;
181 INSTANTIATE_TEST_CASE_P(
184 testing::Values(kProtoDeprecatedSPDY2
,
185 kProtoSPDY3
, kProtoSPDY31
, kProtoSPDY4a2
,
186 kProtoHTTP2Draft04
));
188 // Try to create a SPDY session that will fail during
189 // initialization. Nothing should blow up.
190 TEST_P(SpdySessionTest
, InitialReadError
) {
191 CreateDeterministicNetworkSession();
193 base::WeakPtr
<SpdySession
> session
= TryCreateFakeSpdySessionExpectingFailure(
194 spdy_session_pool_
, key_
, ERR_FAILED
);
195 EXPECT_TRUE(session
);
197 base::RunLoop().RunUntilIdle();
198 EXPECT_FALSE(session
);
203 // A helper class that vends a callback that, when fired, destroys a
204 // given SpdyStreamRequest.
205 class StreamRequestDestroyingCallback
: public TestCompletionCallbackBase
{
207 StreamRequestDestroyingCallback() {}
209 virtual ~StreamRequestDestroyingCallback() {}
211 void SetRequestToDestroy(scoped_ptr
<SpdyStreamRequest
> request
) {
212 request_
= request
.Pass();
215 CompletionCallback
MakeCallback() {
216 return base::Bind(&StreamRequestDestroyingCallback::OnComplete
,
217 base::Unretained(this));
221 void OnComplete(int result
) {
226 scoped_ptr
<SpdyStreamRequest
> request_
;
231 // Request kInitialMaxConcurrentStreams streams. Request two more
232 // streams, but have the callback for one destroy the second stream
233 // request. Close the session. Nothing should blow up. This is a
234 // regression test for http://crbug.com/250841 .
235 TEST_P(SpdySessionTest
, PendingStreamCancellingAnother
) {
236 session_deps_
.host_resolver
->set_synchronous_mode(true);
238 MockRead reads
[] = {MockRead(ASYNC
, 0, 0), };
240 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
241 MockConnect
connect_data(SYNCHRONOUS
, OK
);
242 data
.set_connect_data(connect_data
);
243 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
245 CreateDeterministicNetworkSession();
247 base::WeakPtr
<SpdySession
> session
=
248 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
250 // Create the maximum number of concurrent streams.
251 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
252 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
253 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
, BoundNetLog());
254 ASSERT_TRUE(spdy_stream
!= NULL
);
257 SpdyStreamRequest request1
;
258 scoped_ptr
<SpdyStreamRequest
> request2(new SpdyStreamRequest
);
260 StreamRequestDestroyingCallback callback1
;
261 ASSERT_EQ(ERR_IO_PENDING
,
262 request1
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
,
267 callback1
.MakeCallback()));
269 // |callback2| is never called.
270 TestCompletionCallback callback2
;
271 ASSERT_EQ(ERR_IO_PENDING
,
272 request2
->StartRequest(SPDY_BIDIRECTIONAL_STREAM
,
277 callback2
.callback()));
279 callback1
.SetRequestToDestroy(request2
.Pass());
281 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
283 EXPECT_EQ(ERR_ABORTED
, callback1
.WaitForResult());
286 // A session receiving a GOAWAY frame with no active streams should
287 // immediately close.
288 TEST_P(SpdySessionTest
, GoAwayWithNoActiveStreams
) {
289 session_deps_
.host_resolver
->set_synchronous_mode(true);
291 MockConnect
connect_data(SYNCHRONOUS
, OK
);
292 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
294 CreateMockRead(*goaway
, 0),
296 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
297 data
.set_connect_data(connect_data
);
298 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
300 CreateDeterministicNetworkSession();
302 base::WeakPtr
<SpdySession
> session
=
303 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
305 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
307 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
309 // Read and process the GOAWAY frame.
312 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
314 EXPECT_TRUE(session
== NULL
);
317 // A session receiving a GOAWAY frame immediately with no active
318 // streams should then close.
319 TEST_P(SpdySessionTest
, GoAwayImmediatelyWithNoActiveStreams
) {
320 session_deps_
.host_resolver
->set_synchronous_mode(true);
322 MockConnect
connect_data(SYNCHRONOUS
, OK
);
323 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
325 CreateMockRead(*goaway
, 0, SYNCHRONOUS
),
327 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
328 data
.set_connect_data(connect_data
);
329 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
331 CreateDeterministicNetworkSession();
335 base::WeakPtr
<SpdySession
> session
=
336 TryCreateInsecureSpdySessionExpectingFailure(
337 http_session_
, key_
, ERR_CONNECTION_CLOSED
, BoundNetLog());
338 base::RunLoop().RunUntilIdle();
340 EXPECT_FALSE(session
);
341 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
344 // A session receiving a GOAWAY frame with active streams should close
345 // when the last active stream is closed.
346 TEST_P(SpdySessionTest
, GoAwayWithActiveStreams
) {
347 session_deps_
.host_resolver
->set_synchronous_mode(true);
349 MockConnect
connect_data(SYNCHRONOUS
, OK
);
350 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
352 CreateMockRead(*goaway
, 2),
353 MockRead(ASYNC
, 0, 3) // EOF
355 scoped_ptr
<SpdyFrame
> req1(
356 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
357 scoped_ptr
<SpdyFrame
> req2(
358 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
359 MockWrite writes
[] = {
360 CreateMockWrite(*req1
, 0),
361 CreateMockWrite(*req2
, 1),
363 DeterministicSocketData
data(reads
, arraysize(reads
),
364 writes
, arraysize(writes
));
365 data
.set_connect_data(connect_data
);
366 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
368 CreateDeterministicNetworkSession();
370 base::WeakPtr
<SpdySession
> session
=
371 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
373 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
375 GURL
url(kDefaultURL
);
376 base::WeakPtr
<SpdyStream
> spdy_stream1
=
377 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
378 session
, url
, MEDIUM
, BoundNetLog());
379 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
380 spdy_stream1
->SetDelegate(&delegate1
);
382 base::WeakPtr
<SpdyStream
> spdy_stream2
=
383 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
384 session
, url
, MEDIUM
, BoundNetLog());
385 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
386 spdy_stream2
->SetDelegate(&delegate2
);
388 scoped_ptr
<SpdyHeaderBlock
> headers(
389 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
390 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
392 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
393 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
394 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
395 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
399 EXPECT_EQ(1u, spdy_stream1
->stream_id());
400 EXPECT_EQ(3u, spdy_stream2
->stream_id());
402 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
404 // Read and process the GOAWAY frame.
407 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
409 EXPECT_FALSE(session
->IsStreamActive(3));
410 EXPECT_EQ(NULL
, spdy_stream2
.get());
411 EXPECT_TRUE(session
->IsStreamActive(1));
413 EXPECT_FALSE(session
->IsClosed());
415 // Should close the session.
416 spdy_stream1
->Close();
417 EXPECT_EQ(NULL
, spdy_stream1
.get());
419 EXPECT_TRUE(session
== NULL
);
422 // Have a session receive two GOAWAY frames, with the last one causing
423 // the last active stream to be closed. The session should then be
424 // closed after the second GOAWAY frame.
425 TEST_P(SpdySessionTest
, GoAwayTwice
) {
426 session_deps_
.host_resolver
->set_synchronous_mode(true);
428 MockConnect
connect_data(SYNCHRONOUS
, OK
);
429 scoped_ptr
<SpdyFrame
> goaway1(spdy_util_
.ConstructSpdyGoAway(1));
430 scoped_ptr
<SpdyFrame
> goaway2(spdy_util_
.ConstructSpdyGoAway(0));
432 CreateMockRead(*goaway1
, 2),
433 CreateMockRead(*goaway2
, 3),
434 MockRead(ASYNC
, 0, 4) // EOF
436 scoped_ptr
<SpdyFrame
> req1(
437 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
438 scoped_ptr
<SpdyFrame
> req2(
439 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
440 MockWrite writes
[] = {
441 CreateMockWrite(*req1
, 0),
442 CreateMockWrite(*req2
, 1),
444 DeterministicSocketData
data(reads
, arraysize(reads
),
445 writes
, arraysize(writes
));
446 data
.set_connect_data(connect_data
);
447 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
449 CreateDeterministicNetworkSession();
451 base::WeakPtr
<SpdySession
> session
=
452 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
454 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
456 GURL
url(kDefaultURL
);
457 base::WeakPtr
<SpdyStream
> spdy_stream1
=
458 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
459 session
, url
, MEDIUM
, BoundNetLog());
460 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
461 spdy_stream1
->SetDelegate(&delegate1
);
463 base::WeakPtr
<SpdyStream
> spdy_stream2
=
464 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
465 session
, url
, MEDIUM
, BoundNetLog());
466 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
467 spdy_stream2
->SetDelegate(&delegate2
);
469 scoped_ptr
<SpdyHeaderBlock
> headers(
470 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
471 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
473 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
474 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
475 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
476 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
480 EXPECT_EQ(1u, spdy_stream1
->stream_id());
481 EXPECT_EQ(3u, spdy_stream2
->stream_id());
483 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
485 // Read and process the first GOAWAY frame.
488 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
490 EXPECT_FALSE(session
->IsStreamActive(3));
491 EXPECT_EQ(NULL
, spdy_stream2
.get());
492 EXPECT_TRUE(session
->IsStreamActive(1));
494 EXPECT_FALSE(session
->IsClosed());
496 // Read and process the second GOAWAY frame, which should close the
500 EXPECT_TRUE(session
== NULL
);
503 // Have a session with active streams receive a GOAWAY frame and then
504 // close it. It should handle the close properly (i.e., not try to
505 // make itself unavailable in its pool twice).
506 TEST_P(SpdySessionTest
, GoAwayWithActiveStreamsThenClose
) {
507 session_deps_
.host_resolver
->set_synchronous_mode(true);
509 MockConnect
connect_data(SYNCHRONOUS
, OK
);
510 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
512 CreateMockRead(*goaway
, 2),
513 MockRead(ASYNC
, 0, 3) // EOF
515 scoped_ptr
<SpdyFrame
> req1(
516 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
517 scoped_ptr
<SpdyFrame
> req2(
518 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
519 MockWrite writes
[] = {
520 CreateMockWrite(*req1
, 0),
521 CreateMockWrite(*req2
, 1),
523 DeterministicSocketData
data(reads
, arraysize(reads
),
524 writes
, arraysize(writes
));
525 data
.set_connect_data(connect_data
);
526 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
528 CreateDeterministicNetworkSession();
530 base::WeakPtr
<SpdySession
> session
=
531 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
533 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
535 GURL
url(kDefaultURL
);
536 base::WeakPtr
<SpdyStream
> spdy_stream1
=
537 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
538 session
, url
, MEDIUM
, BoundNetLog());
539 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
540 spdy_stream1
->SetDelegate(&delegate1
);
542 base::WeakPtr
<SpdyStream
> spdy_stream2
=
543 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
544 session
, url
, MEDIUM
, BoundNetLog());
545 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
546 spdy_stream2
->SetDelegate(&delegate2
);
548 scoped_ptr
<SpdyHeaderBlock
> headers(
549 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
550 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
552 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
553 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
554 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
555 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
559 EXPECT_EQ(1u, spdy_stream1
->stream_id());
560 EXPECT_EQ(3u, spdy_stream2
->stream_id());
562 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
564 // Read and process the GOAWAY frame.
567 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
569 EXPECT_FALSE(session
->IsStreamActive(3));
570 EXPECT_EQ(NULL
, spdy_stream2
.get());
571 EXPECT_TRUE(session
->IsStreamActive(1));
573 EXPECT_FALSE(session
->IsClosed());
575 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
577 EXPECT_EQ(NULL
, spdy_stream1
.get());
578 EXPECT_TRUE(session
== NULL
);
581 // Try to create a stream after receiving a GOAWAY frame. It should
583 TEST_P(SpdySessionTest
, CreateStreamAfterGoAway
) {
584 session_deps_
.host_resolver
->set_synchronous_mode(true);
586 MockConnect
connect_data(SYNCHRONOUS
, OK
);
587 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
589 CreateMockRead(*goaway
, 1),
590 MockRead(ASYNC
, 0, 2) // EOF
592 scoped_ptr
<SpdyFrame
> req(
593 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
594 MockWrite writes
[] = {
595 CreateMockWrite(*req
, 0),
597 DeterministicSocketData
data(reads
, arraysize(reads
),
598 writes
, arraysize(writes
));
599 data
.set_connect_data(connect_data
);
600 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
602 CreateDeterministicNetworkSession();
604 base::WeakPtr
<SpdySession
> session
=
605 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
607 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
609 GURL
url(kDefaultURL
);
610 base::WeakPtr
<SpdyStream
> spdy_stream
=
611 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
612 session
, url
, MEDIUM
, BoundNetLog());
613 test::StreamDelegateDoNothing
delegate(spdy_stream
);
614 spdy_stream
->SetDelegate(&delegate
);
616 scoped_ptr
<SpdyHeaderBlock
> headers(
617 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
618 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
619 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
623 EXPECT_EQ(1u, spdy_stream
->stream_id());
625 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
627 // Read and process the GOAWAY frame.
630 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
631 EXPECT_TRUE(session
->IsStreamActive(1));
633 SpdyStreamRequest stream_request
;
634 int rv
= stream_request
.StartRequest(
635 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog(),
636 CompletionCallback());
637 EXPECT_EQ(ERR_FAILED
, rv
);
639 // Read and process EOF.
642 EXPECT_TRUE(session
== NULL
);
645 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
646 // the stream being refused.
647 TEST_P(SpdySessionTest
, SynStreamAfterGoAway
) {
648 session_deps_
.host_resolver
->set_synchronous_mode(true);
650 MockConnect
connect_data(SYNCHRONOUS
, OK
);
651 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
652 scoped_ptr
<SpdyFrame
>
653 push(spdy_util_
.ConstructSpdyPush(NULL
, 0, 2, 1, kDefaultURL
));
655 CreateMockRead(*goaway
, 1),
656 CreateMockRead(*push
, 2),
657 MockRead(ASYNC
, 0, 4) // EOF
659 scoped_ptr
<SpdyFrame
> req(
660 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
661 scoped_ptr
<SpdyFrame
> rst(
662 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
663 MockWrite writes
[] = {
664 CreateMockWrite(*req
, 0),
665 CreateMockWrite(*rst
, 3)
667 DeterministicSocketData
data(reads
, arraysize(reads
),
668 writes
, arraysize(writes
));
669 data
.set_connect_data(connect_data
);
670 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
672 CreateDeterministicNetworkSession();
674 base::WeakPtr
<SpdySession
> session
=
675 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
677 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
679 GURL
url(kDefaultURL
);
680 base::WeakPtr
<SpdyStream
> spdy_stream
=
681 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
682 session
, url
, MEDIUM
, BoundNetLog());
683 test::StreamDelegateDoNothing
delegate(spdy_stream
);
684 spdy_stream
->SetDelegate(&delegate
);
686 scoped_ptr
<SpdyHeaderBlock
> headers(
687 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
688 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
689 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
693 EXPECT_EQ(1u, spdy_stream
->stream_id());
695 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
697 // Read and process the GOAWAY frame.
700 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
701 EXPECT_TRUE(session
->IsStreamActive(1));
703 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
707 EXPECT_TRUE(session
== NULL
);
710 // A session observing a network change with active streams should close
711 // when the last active stream is closed.
712 TEST_P(SpdySessionTest
, NetworkChangeWithActiveStreams
) {
713 session_deps_
.host_resolver
->set_synchronous_mode(true);
715 MockConnect
connect_data(SYNCHRONOUS
, OK
);
717 MockRead(ASYNC
, 0, 1) // EOF
719 scoped_ptr
<SpdyFrame
> req1(
720 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
721 MockWrite writes
[] = {
722 CreateMockWrite(*req1
, 0),
724 DeterministicSocketData
data(reads
, arraysize(reads
),
725 writes
, arraysize(writes
));
726 data
.set_connect_data(connect_data
);
727 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
729 CreateDeterministicNetworkSession();
731 base::WeakPtr
<SpdySession
> session
=
732 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
734 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
736 base::WeakPtr
<SpdyStream
> spdy_stream
=
737 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
, session
,
738 GURL(kDefaultURL
), MEDIUM
, BoundNetLog());
739 test::StreamDelegateDoNothing
delegate(spdy_stream
);
740 spdy_stream
->SetDelegate(&delegate
);
742 scoped_ptr
<SpdyHeaderBlock
> headers(
743 spdy_util_
.ConstructGetHeaderBlock(kDefaultURL
));
745 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
746 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
750 EXPECT_EQ(1u, spdy_stream
->stream_id());
752 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
754 spdy_session_pool_
->OnIPAddressChanged();
756 // The SpdySessionPool behavior differs based on how the OSs reacts to
757 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
758 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
759 // For OSs where the TCP connections will close upon relevant network
760 // changes, SpdySessionPool doesn't need to force them to close, so in these
761 // cases verify the session has become unavailable but remains open and the
762 // pre-existing stream is still active.
763 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
765 EXPECT_FALSE(session
->IsClosed());
767 EXPECT_TRUE(session
->IsStreamActive(1));
769 // Should close the session.
770 spdy_stream
->Close();
772 EXPECT_EQ(NULL
, spdy_stream
.get());
774 EXPECT_TRUE(session
== NULL
);
777 TEST_P(SpdySessionTest
, ClientPing
) {
778 session_deps_
.enable_ping
= true;
779 session_deps_
.host_resolver
->set_synchronous_mode(true);
781 MockConnect
connect_data(SYNCHRONOUS
, OK
);
782 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(1, true));
784 CreateMockRead(*read_ping
, 1),
785 MockRead(ASYNC
, 0, 0, 2) // EOF
787 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
788 MockWrite writes
[] = {
789 CreateMockWrite(*write_ping
, 0),
791 DeterministicSocketData
data(
792 reads
, arraysize(reads
), writes
, arraysize(writes
));
793 data
.set_connect_data(connect_data
);
794 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
796 CreateDeterministicNetworkSession();
798 base::WeakPtr
<SpdySession
> session
=
799 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
801 base::WeakPtr
<SpdyStream
> spdy_stream1
=
802 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
803 session
, test_url_
, MEDIUM
, BoundNetLog());
804 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
805 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
806 spdy_stream1
->SetDelegate(&delegate
);
808 base::TimeTicks before_ping_time
= base::TimeTicks::Now();
810 session
->set_connection_at_risk_of_loss_time(
811 base::TimeDelta::FromSeconds(-1));
812 session
->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
814 session
->SendPrefacePingIfNoneInFlight();
818 session
->CheckPingStatus(before_ping_time
);
820 EXPECT_EQ(0, session
->pings_in_flight());
821 EXPECT_GE(session
->next_ping_id(), static_cast<uint32
>(1));
822 EXPECT_FALSE(session
->check_ping_status_pending());
823 EXPECT_GE(session
->last_activity_time(), before_ping_time
);
827 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
829 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
830 EXPECT_TRUE(session
== NULL
);
833 TEST_P(SpdySessionTest
, ServerPing
) {
834 session_deps_
.host_resolver
->set_synchronous_mode(true);
836 MockConnect
connect_data(SYNCHRONOUS
, OK
);
837 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(2, false));
839 CreateMockRead(*read_ping
),
840 MockRead(SYNCHRONOUS
, 0, 0) // EOF
842 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(2, true));
843 MockWrite writes
[] = {
844 CreateMockWrite(*write_ping
),
846 StaticSocketDataProvider
data(
847 reads
, arraysize(reads
), writes
, arraysize(writes
));
848 data
.set_connect_data(connect_data
);
849 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
851 CreateNetworkSession();
853 base::WeakPtr
<SpdySession
> session
=
854 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
856 base::WeakPtr
<SpdyStream
> spdy_stream1
=
857 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
858 session
, test_url_
, MEDIUM
, BoundNetLog());
859 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
860 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
861 spdy_stream1
->SetDelegate(&delegate
);
863 // Flush the read completion task.
864 base::MessageLoop::current()->RunUntilIdle();
866 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
868 EXPECT_TRUE(session
== NULL
);
869 EXPECT_EQ(NULL
, spdy_stream1
.get());
872 // Cause a ping to be sent out while producing a write. The write loop
873 // should handle this properly, i.e. another DoWriteLoop task should
874 // not be posted. This is a regression test for
875 // http://crbug.com/261043 .
876 TEST_P(SpdySessionTest
, PingAndWriteLoop
) {
877 session_deps_
.enable_ping
= true;
878 session_deps_
.time_func
= TheNearFuture
;
880 MockConnect
connect_data(SYNCHRONOUS
, OK
);
881 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
882 scoped_ptr
<SpdyFrame
> req(
883 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
884 MockWrite writes
[] = {
885 CreateMockWrite(*req
, 0),
886 CreateMockWrite(*write_ping
, 1),
890 MockRead(ASYNC
, 0, 2) // EOF
893 session_deps_
.host_resolver
->set_synchronous_mode(true);
895 DeterministicSocketData
data(reads
, arraysize(reads
),
896 writes
, arraysize(writes
));
897 data
.set_connect_data(connect_data
);
898 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
900 CreateDeterministicNetworkSession();
902 base::WeakPtr
<SpdySession
> session
=
903 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
905 GURL
url(kDefaultURL
);
906 base::WeakPtr
<SpdyStream
> spdy_stream
=
907 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
908 session
, url
, LOWEST
, BoundNetLog());
909 test::StreamDelegateDoNothing
delegate(spdy_stream
);
910 spdy_stream
->SetDelegate(&delegate
);
912 scoped_ptr
<SpdyHeaderBlock
> headers(
913 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
914 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
916 // Shift time so that a ping will be sent out.
917 g_time_delta
= base::TimeDelta::FromSeconds(11);
921 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting");
924 TEST_P(SpdySessionTest
, DeleteExpiredPushStreams
) {
925 session_deps_
.host_resolver
->set_synchronous_mode(true);
926 session_deps_
.time_func
= TheNearFuture
;
928 scoped_ptr
<SpdyFrame
> req(
929 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
930 scoped_ptr
<SpdyFrame
> rst(
931 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
933 scoped_ptr
<SpdyFrame
> push_a(spdy_util_
.ConstructSpdyPush(
934 NULL
, 0, 2, 1, "http://www.google.com/a.dat"));
935 scoped_ptr
<SpdyFrame
> push_a_body(
936 spdy_util_
.ConstructSpdyBodyFrame(2, false));
937 scoped_ptr
<SpdyFrame
> push_b(spdy_util_
.ConstructSpdyPush(
938 NULL
, 0, 4, 1, "http://www.google.com/b.dat"));
939 MockWrite writes
[] = {CreateMockWrite(*req
, 0), CreateMockWrite(*rst
, 4)};
941 CreateMockRead(*push_a
, 1), CreateMockRead(*push_a_body
, 2),
942 CreateMockRead(*push_b
, 3), MockRead(ASYNC
, 0, 5), // EOF
944 DeterministicSocketData
data(
945 reads
, arraysize(reads
), writes
, arraysize(writes
));
947 MockConnect
connect_data(SYNCHRONOUS
, OK
);
948 data
.set_connect_data(connect_data
);
949 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
951 CreateDeterministicNetworkSession();
952 base::WeakPtr
<SpdySession
> session
=
953 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
955 // Process the principal request, and the first push stream request & body.
956 GURL
url(kDefaultURL
);
957 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
958 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog());
959 test::StreamDelegateDoNothing
delegate(spdy_stream
);
960 spdy_stream
->SetDelegate(&delegate
);
962 scoped_ptr
<SpdyHeaderBlock
> headers(
963 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
964 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
968 // Verify that there is one unclaimed push stream.
969 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
970 SpdySession::PushedStreamMap::iterator iter
=
971 session
->unclaimed_pushed_streams_
.find(
972 GURL("http://www.google.com/a.dat"));
973 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
975 if (session
->flow_control_state_
==
976 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
977 // Unclaimed push body consumed bytes from the session window.
978 EXPECT_EQ(kSpdySessionInitialWindowSize
- kUploadDataSize
,
979 session
->session_recv_window_size_
);
980 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
983 // Shift time to expire the push stream. Read the second SYN_STREAM,
984 // and verify a RST_STREAM was written.
985 g_time_delta
= base::TimeDelta::FromSeconds(301);
988 // Verify that the second pushed stream evicted the first pushed stream.
989 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
990 iter
= session
->unclaimed_pushed_streams_
.find(
991 GURL("http://www.google.com/b.dat"));
992 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
994 if (session
->flow_control_state_
==
995 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
) {
996 // Verify that the session window reclaimed the evicted stream body.
997 EXPECT_EQ(kSpdySessionInitialWindowSize
,
998 session
->session_recv_window_size_
);
999 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
1002 // Read and process EOF.
1004 EXPECT_TRUE(session
== NULL
);
1007 TEST_P(SpdySessionTest
, FailedPing
) {
1008 session_deps_
.host_resolver
->set_synchronous_mode(true);
1010 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1011 MockRead reads
[] = {
1012 MockRead(ASYNC
, 0, 0, 0) // EOF
1014 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1, false));
1015 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
1016 data
.set_connect_data(connect_data
);
1017 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1019 CreateDeterministicNetworkSession();
1021 base::WeakPtr
<SpdySession
> session
=
1022 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1024 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1025 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1026 session
, test_url_
, MEDIUM
, BoundNetLog());
1027 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1028 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
1029 spdy_stream1
->SetDelegate(&delegate
);
1031 session
->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1032 session
->set_hung_interval(base::TimeDelta::FromSeconds(0));
1034 // Send a PING frame.
1035 session
->WritePingFrame(1, false);
1036 EXPECT_LT(0, session
->pings_in_flight());
1037 EXPECT_GE(session
->next_ping_id(), static_cast<uint32
>(1));
1038 EXPECT_TRUE(session
->check_ping_status_pending());
1040 // Assert session is not closed.
1041 EXPECT_FALSE(session
->IsClosed());
1042 EXPECT_LT(0u, session
->num_active_streams() + session
->num_created_streams());
1043 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1045 // We set last time we have received any data in 1 sec less than now.
1046 // CheckPingStatus will trigger timeout because hung interval is zero.
1047 base::TimeTicks now
= base::TimeTicks::Now();
1048 session
->last_activity_time_
= now
- base::TimeDelta::FromSeconds(1);
1049 session
->CheckPingStatus(now
);
1051 EXPECT_TRUE(session
== NULL
);
1052 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1053 EXPECT_EQ(NULL
, spdy_stream1
.get());
1056 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1057 // settings frame increasing the max concurrent streams by 1. Make
1058 // sure nothing blows up. This is a regression test for
1059 // http://crbug.com/57331 .
1060 TEST_P(SpdySessionTest
, OnSettings
) {
1061 session_deps_
.host_resolver
->set_synchronous_mode(true);
1063 const SpdySettingsIds kSpdySettingsIds
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1065 SettingsMap new_settings
;
1066 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1067 new_settings
[kSpdySettingsIds
] =
1068 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1069 scoped_ptr
<SpdyFrame
> settings_frame(
1070 spdy_util_
.ConstructSpdySettings(new_settings
));
1071 MockRead reads
[] = {
1072 CreateMockRead(*settings_frame
, 0),
1073 MockRead(ASYNC
, 0, 1),
1076 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
1077 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1078 data
.set_connect_data(connect_data
);
1079 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1081 CreateDeterministicNetworkSession();
1083 base::WeakPtr
<SpdySession
> session
=
1084 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1086 // Create the maximum number of concurrent streams.
1087 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1088 base::WeakPtr
<SpdyStream
> spdy_stream
=
1089 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1090 session
, test_url_
, MEDIUM
, BoundNetLog());
1091 ASSERT_TRUE(spdy_stream
!= NULL
);
1094 StreamReleaserCallback stream_releaser
;
1095 SpdyStreamRequest request
;
1096 ASSERT_EQ(ERR_IO_PENDING
,
1097 request
.StartRequest(
1098 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1100 stream_releaser
.MakeCallback(&request
)));
1104 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1107 EXPECT_TRUE(session
== NULL
);
1110 // Start with a persisted value for max concurrent streams. Receive a
1111 // settings frame increasing the max concurrent streams by 1 and which
1112 // also clears the persisted data. Verify that persisted data is
1114 TEST_P(SpdySessionTest
, ClearSettings
) {
1115 if (spdy_util_
.spdy_version() >= SPDY4
) {
1116 // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1117 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4.
1120 session_deps_
.host_resolver
->set_synchronous_mode(true);
1122 SettingsMap new_settings
;
1123 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1124 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1125 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1126 scoped_ptr
<SpdyFrame
> settings_frame(
1127 spdy_util_
.ConstructSpdySettings(new_settings
));
1128 uint8 flags
= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
1129 test::SetFrameFlags(settings_frame
.get(), flags
, spdy_util_
.spdy_version());
1130 MockRead reads
[] = {
1131 CreateMockRead(*settings_frame
, 0),
1132 MockRead(ASYNC
, 0, 1),
1135 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
1136 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1137 data
.set_connect_data(connect_data
);
1138 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1140 CreateDeterministicNetworkSession();
1142 // Initialize the SpdySetting with the default.
1143 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1144 test_host_port_pair_
,
1145 SETTINGS_MAX_CONCURRENT_STREAMS
,
1146 SETTINGS_FLAG_PLEASE_PERSIST
,
1147 kInitialMaxConcurrentStreams
);
1150 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1151 test_host_port_pair_
).empty());
1153 base::WeakPtr
<SpdySession
> session
=
1154 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1156 // Create the maximum number of concurrent streams.
1157 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1158 base::WeakPtr
<SpdyStream
> spdy_stream
=
1159 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1160 session
, test_url_
, MEDIUM
, BoundNetLog());
1161 ASSERT_TRUE(spdy_stream
!= NULL
);
1164 StreamReleaserCallback stream_releaser
;
1166 SpdyStreamRequest request
;
1167 ASSERT_EQ(ERR_IO_PENDING
,
1168 request
.StartRequest(
1169 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1171 stream_releaser
.MakeCallback(&request
)));
1175 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1177 // Make sure that persisted data is cleared.
1179 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1180 test_host_port_pair_
).empty());
1182 // Make sure session's max_concurrent_streams is correct.
1183 EXPECT_EQ(kInitialMaxConcurrentStreams
+ 1,
1184 session
->max_concurrent_streams());
1187 EXPECT_TRUE(session
== NULL
);
1190 // Start with max concurrent streams set to 1. Request two streams.
1191 // When the first completes, have the callback close its stream, which
1192 // should trigger the second stream creation. Then cancel that one
1193 // immediately. Don't crash. This is a regression test for
1194 // http://crbug.com/63532 .
1195 TEST_P(SpdySessionTest
, CancelPendingCreateStream
) {
1196 session_deps_
.host_resolver
->set_synchronous_mode(true);
1198 MockRead reads
[] = {
1199 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1202 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1203 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1205 data
.set_connect_data(connect_data
);
1206 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1208 CreateNetworkSession();
1210 // Initialize the SpdySetting with 1 max concurrent streams.
1211 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1212 test_host_port_pair_
,
1213 SETTINGS_MAX_CONCURRENT_STREAMS
,
1214 SETTINGS_FLAG_PLEASE_PERSIST
,
1217 base::WeakPtr
<SpdySession
> session
=
1218 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1220 // Leave room for only one more stream to be created.
1221 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
1222 base::WeakPtr
<SpdyStream
> spdy_stream
=
1223 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1224 session
, test_url_
, MEDIUM
, BoundNetLog());
1225 ASSERT_TRUE(spdy_stream
!= NULL
);
1228 // Create 2 more streams. First will succeed. Second will be pending.
1229 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1230 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1231 session
, test_url_
, MEDIUM
, BoundNetLog());
1232 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1234 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1235 // a valgrind error if the callback is invoked when it's not supposed to be.
1236 scoped_ptr
<TestCompletionCallback
> callback(new TestCompletionCallback
);
1238 SpdyStreamRequest request
;
1239 ASSERT_EQ(ERR_IO_PENDING
,
1240 request
.StartRequest(
1241 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1243 callback
->callback()));
1245 // Release the first one, this will allow the second to be created.
1246 spdy_stream1
->Cancel();
1247 EXPECT_EQ(NULL
, spdy_stream1
.get());
1249 request
.CancelRequest();
1252 // Should not crash when running the pending callback.
1253 base::MessageLoop::current()->RunUntilIdle();
1256 TEST_P(SpdySessionTest
, SendInitialDataOnNewSession
) {
1257 session_deps_
.host_resolver
->set_synchronous_mode(true);
1259 MockRead reads
[] = {
1260 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1263 SettingsMap settings
;
1264 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1265 const SpdySettingsIds kSpdySettingsIds2
= SETTINGS_INITIAL_WINDOW_SIZE
;
1266 const uint32 kInitialRecvWindowSize
= 10 * 1024 * 1024;
1267 settings
[kSpdySettingsIds1
] =
1268 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
1269 if (spdy_util_
.spdy_version() >= SPDY3
) {
1270 settings
[kSpdySettingsIds2
] =
1271 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kInitialRecvWindowSize
);
1273 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1274 scoped_ptr
<SpdyFrame
> settings_frame(
1275 spdy_util_
.ConstructSpdySettings(settings
));
1276 scoped_ptr
<SpdyFrame
> initial_window_update(
1277 spdy_util_
.ConstructSpdyWindowUpdate(
1278 kSessionFlowControlStreamId
,
1279 kDefaultInitialRecvWindowSize
- kSpdySessionInitialWindowSize
));
1280 std::vector
<MockWrite
> writes
;
1281 if (GetParam() == kProtoHTTP2Draft04
) {
1284 kHttp2ConnectionHeaderPrefix
,
1285 kHttp2ConnectionHeaderPrefixSize
));
1287 writes
.push_back(CreateMockWrite(*settings_frame
));
1288 if (GetParam() >= kProtoSPDY31
) {
1289 writes
.push_back(CreateMockWrite(*initial_window_update
));
1292 SettingsMap server_settings
;
1293 const uint32 initial_max_concurrent_streams
= 1;
1294 server_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1295 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED
,
1296 initial_max_concurrent_streams
);
1297 scoped_ptr
<SpdyFrame
> server_settings_frame(
1298 spdy_util_
.ConstructSpdySettings(server_settings
));
1299 writes
.push_back(CreateMockWrite(*server_settings_frame
));
1301 session_deps_
.stream_initial_recv_window_size
= kInitialRecvWindowSize
;
1303 StaticSocketDataProvider
data(reads
, arraysize(reads
),
1304 vector_as_array(&writes
), writes
.size());
1305 data
.set_connect_data(connect_data
);
1306 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1308 CreateNetworkSession();
1310 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1311 test_host_port_pair_
,
1312 SETTINGS_MAX_CONCURRENT_STREAMS
,
1313 SETTINGS_FLAG_PLEASE_PERSIST
,
1314 initial_max_concurrent_streams
);
1316 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
1317 pool_peer
.SetEnableSendingInitialData(true);
1319 base::WeakPtr
<SpdySession
> session
=
1320 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1322 base::MessageLoop::current()->RunUntilIdle();
1323 EXPECT_TRUE(data
.at_write_eof());
1326 TEST_P(SpdySessionTest
, ClearSettingsStorageOnIPAddressChanged
) {
1327 CreateNetworkSession();
1329 base::WeakPtr
<HttpServerProperties
> test_http_server_properties
=
1330 spdy_session_pool_
->http_server_properties();
1331 SettingsFlagsAndValue
flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST
, 2);
1332 test_http_server_properties
->SetSpdySetting(
1333 test_host_port_pair_
,
1334 SETTINGS_MAX_CONCURRENT_STREAMS
,
1335 SETTINGS_FLAG_PLEASE_PERSIST
,
1337 EXPECT_NE(0u, test_http_server_properties
->GetSpdySettings(
1338 test_host_port_pair_
).size());
1339 spdy_session_pool_
->OnIPAddressChanged();
1340 EXPECT_EQ(0u, test_http_server_properties
->GetSpdySettings(
1341 test_host_port_pair_
).size());
1344 TEST_P(SpdySessionTest
, Initialize
) {
1345 CapturingBoundNetLog log
;
1346 session_deps_
.net_log
= log
.bound().net_log();
1347 session_deps_
.host_resolver
->set_synchronous_mode(true);
1349 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1350 MockRead reads
[] = {
1351 MockRead(ASYNC
, 0, 0) // EOF
1354 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1355 data
.set_connect_data(connect_data
);
1356 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1358 CreateNetworkSession();
1360 base::WeakPtr
<SpdySession
> session
=
1361 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1362 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1364 // Flush the read completion task.
1365 base::MessageLoop::current()->RunUntilIdle();
1367 net::CapturingNetLog::CapturedEntryList entries
;
1368 log
.GetEntries(&entries
);
1369 EXPECT_LT(0u, entries
.size());
1371 // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly.
1372 int pos
= net::ExpectLogContainsSomewhere(
1374 net::NetLog::TYPE_SPDY_SESSION_INITIALIZED
,
1375 net::NetLog::PHASE_NONE
);
1378 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1379 NetLog::Source socket_source
;
1380 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry
.params
.get(),
1382 EXPECT_TRUE(socket_source
.IsValid());
1383 EXPECT_NE(log
.bound().source().id
, socket_source
.id
);
1386 TEST_P(SpdySessionTest
, CloseSessionOnError
) {
1387 session_deps_
.host_resolver
->set_synchronous_mode(true);
1389 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1390 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
1391 MockRead reads
[] = {
1392 CreateMockRead(*goaway
),
1393 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1396 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1397 data
.set_connect_data(connect_data
);
1398 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1400 CreateNetworkSession();
1402 CapturingBoundNetLog log
;
1403 base::WeakPtr
<SpdySession
> session
=
1404 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1405 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1407 // Flush the read completion task.
1408 base::MessageLoop::current()->RunUntilIdle();
1410 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1411 EXPECT_TRUE(session
== NULL
);
1413 // Check that the NetLog was filled reasonably.
1414 net::CapturingNetLog::CapturedEntryList entries
;
1415 log
.GetEntries(&entries
);
1416 EXPECT_LT(0u, entries
.size());
1418 // Check that we logged SPDY_SESSION_CLOSE correctly.
1419 int pos
= net::ExpectLogContainsSomewhere(
1421 net::NetLog::TYPE_SPDY_SESSION_CLOSE
,
1422 net::NetLog::PHASE_NONE
);
1424 if (pos
< static_cast<int>(entries
.size())) {
1425 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1427 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1428 EXPECT_EQ(ERR_CONNECTION_CLOSED
, error_code
);
1434 // Queue up a low-priority SYN_STREAM followed by a high-priority
1435 // one. The high priority one should still send first and receive
1437 TEST_P(SpdySessionTest
, OutOfOrderSynStreams
) {
1438 // Construct the request.
1439 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1440 scoped_ptr
<SpdyFrame
> req_highest(
1441 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, HIGHEST
, true));
1442 scoped_ptr
<SpdyFrame
> req_lowest(
1443 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1444 MockWrite writes
[] = {
1445 CreateMockWrite(*req_highest
, 0),
1446 CreateMockWrite(*req_lowest
, 1),
1449 scoped_ptr
<SpdyFrame
> resp_highest(
1450 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1451 scoped_ptr
<SpdyFrame
> body_highest(
1452 spdy_util_
.ConstructSpdyBodyFrame(1, true));
1453 scoped_ptr
<SpdyFrame
> resp_lowest(
1454 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1455 scoped_ptr
<SpdyFrame
> body_lowest(
1456 spdy_util_
.ConstructSpdyBodyFrame(3, true));
1457 MockRead reads
[] = {
1458 CreateMockRead(*resp_highest
, 2),
1459 CreateMockRead(*body_highest
, 3),
1460 CreateMockRead(*resp_lowest
, 4),
1461 CreateMockRead(*body_lowest
, 5),
1462 MockRead(ASYNC
, 0, 6) // EOF
1465 session_deps_
.host_resolver
->set_synchronous_mode(true);
1467 DeterministicSocketData
data(reads
, arraysize(reads
),
1468 writes
, arraysize(writes
));
1469 data
.set_connect_data(connect_data
);
1470 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1472 CreateDeterministicNetworkSession();
1474 base::WeakPtr
<SpdySession
> session
=
1475 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1477 GURL
url(kDefaultURL
);
1479 base::WeakPtr
<SpdyStream
> spdy_stream_lowest
=
1480 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1481 session
, url
, LOWEST
, BoundNetLog());
1482 ASSERT_TRUE(spdy_stream_lowest
);
1483 EXPECT_EQ(0u, spdy_stream_lowest
->stream_id());
1484 test::StreamDelegateDoNothing
delegate_lowest(spdy_stream_lowest
);
1485 spdy_stream_lowest
->SetDelegate(&delegate_lowest
);
1487 base::WeakPtr
<SpdyStream
> spdy_stream_highest
=
1488 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1489 session
, url
, HIGHEST
, BoundNetLog());
1490 ASSERT_TRUE(spdy_stream_highest
);
1491 EXPECT_EQ(0u, spdy_stream_highest
->stream_id());
1492 test::StreamDelegateDoNothing
delegate_highest(spdy_stream_highest
);
1493 spdy_stream_highest
->SetDelegate(&delegate_highest
);
1495 // Queue the lower priority one first.
1497 scoped_ptr
<SpdyHeaderBlock
> headers_lowest(
1498 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1499 spdy_stream_lowest
->SendRequestHeaders(
1500 headers_lowest
.Pass(), NO_MORE_DATA_TO_SEND
);
1501 EXPECT_TRUE(spdy_stream_lowest
->HasUrlFromHeaders());
1503 scoped_ptr
<SpdyHeaderBlock
> headers_highest(
1504 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1505 spdy_stream_highest
->SendRequestHeaders(
1506 headers_highest
.Pass(), NO_MORE_DATA_TO_SEND
);
1507 EXPECT_TRUE(spdy_stream_highest
->HasUrlFromHeaders());
1511 EXPECT_FALSE(spdy_stream_lowest
);
1512 EXPECT_FALSE(spdy_stream_highest
);
1513 EXPECT_EQ(3u, delegate_lowest
.stream_id());
1514 EXPECT_EQ(1u, delegate_highest
.stream_id());
1517 TEST_P(SpdySessionTest
, CancelStream
) {
1518 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1519 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1520 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1521 scoped_ptr
<SpdyFrame
> req2(
1522 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1523 MockWrite writes
[] = {
1524 CreateMockWrite(*req2
, 0),
1527 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1528 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1529 MockRead reads
[] = {
1530 CreateMockRead(*resp2
, 1),
1531 CreateMockRead(*body2
, 2),
1532 MockRead(ASYNC
, 0, 3) // EOF
1535 session_deps_
.host_resolver
->set_synchronous_mode(true);
1537 DeterministicSocketData
data(reads
, arraysize(reads
),
1538 writes
, arraysize(writes
));
1539 data
.set_connect_data(connect_data
);
1540 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1542 CreateDeterministicNetworkSession();
1544 base::WeakPtr
<SpdySession
> session
=
1545 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1547 GURL
url1(kDefaultURL
);
1548 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1549 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1550 session
, url1
, HIGHEST
, BoundNetLog());
1551 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1552 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1553 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
1554 spdy_stream1
->SetDelegate(&delegate1
);
1556 GURL
url2(kDefaultURL
);
1557 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1558 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1559 session
, url2
, LOWEST
, BoundNetLog());
1560 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1561 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1562 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
1563 spdy_stream2
->SetDelegate(&delegate2
);
1565 scoped_ptr
<SpdyHeaderBlock
> headers(
1566 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1567 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1568 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1570 scoped_ptr
<SpdyHeaderBlock
> headers2(
1571 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1572 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1573 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1575 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1577 spdy_stream1
->Cancel();
1578 EXPECT_EQ(NULL
, spdy_stream1
.get());
1580 EXPECT_EQ(0u, delegate1
.stream_id());
1584 EXPECT_EQ(0u, delegate1
.stream_id());
1585 EXPECT_EQ(1u, delegate2
.stream_id());
1587 spdy_stream2
->Cancel();
1588 EXPECT_EQ(NULL
, spdy_stream2
.get());
1591 // Create two streams that are set to re-close themselves on close,
1592 // and then close the session. Nothing should blow up. Also a
1593 // regression test for http://crbug.com/139518 .
1594 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedSelfClosingStreams
) {
1595 session_deps_
.host_resolver
->set_synchronous_mode(true);
1597 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1599 // No actual data will be sent.
1600 MockWrite writes
[] = {
1601 MockWrite(ASYNC
, 0, 1) // EOF
1604 MockRead reads
[] = {
1605 MockRead(ASYNC
, 0, 0) // EOF
1607 DeterministicSocketData
data(reads
, arraysize(reads
),
1608 writes
, arraysize(writes
));
1609 data
.set_connect_data(connect_data
);
1610 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1612 CreateDeterministicNetworkSession();
1614 base::WeakPtr
<SpdySession
> session
=
1615 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1617 GURL
url1(kDefaultURL
);
1618 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1619 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1620 session
, url1
, HIGHEST
, BoundNetLog());
1621 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1622 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1624 GURL
url2(kDefaultURL
);
1625 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1626 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1627 session
, url2
, LOWEST
, BoundNetLog());
1628 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1629 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1631 test::ClosingDelegate
delegate1(spdy_stream1
);
1632 spdy_stream1
->SetDelegate(&delegate1
);
1634 test::ClosingDelegate
delegate2(spdy_stream2
);
1635 spdy_stream2
->SetDelegate(&delegate2
);
1637 scoped_ptr
<SpdyHeaderBlock
> headers(
1638 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1639 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1640 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1642 scoped_ptr
<SpdyHeaderBlock
> headers2(
1643 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1644 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1645 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1647 // Ensure that the streams have not yet been activated and assigned an id.
1648 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1649 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1651 // Ensure we don't crash while closing the session.
1652 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
1654 EXPECT_EQ(NULL
, spdy_stream1
.get());
1655 EXPECT_EQ(NULL
, spdy_stream2
.get());
1657 EXPECT_TRUE(delegate1
.StreamIsClosed());
1658 EXPECT_TRUE(delegate2
.StreamIsClosed());
1660 EXPECT_TRUE(session
== NULL
);
1663 // Create two streams that are set to close each other on close, and
1664 // then close the session. Nothing should blow up.
1665 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedMutuallyClosingStreams
) {
1666 session_deps_
.host_resolver
->set_synchronous_mode(true);
1668 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1670 // No actual data will be sent.
1671 MockWrite writes
[] = {
1672 MockWrite(ASYNC
, 0, 1) // EOF
1675 MockRead reads
[] = {
1676 MockRead(ASYNC
, 0, 0) // EOF
1678 DeterministicSocketData
data(reads
, arraysize(reads
),
1679 writes
, arraysize(writes
));
1680 data
.set_connect_data(connect_data
);
1681 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1683 CreateDeterministicNetworkSession();
1685 base::WeakPtr
<SpdySession
> session
=
1686 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1688 GURL
url1(kDefaultURL
);
1689 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1690 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1691 session
, url1
, HIGHEST
, BoundNetLog());
1692 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1693 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1695 GURL
url2(kDefaultURL
);
1696 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1697 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1698 session
, url2
, LOWEST
, BoundNetLog());
1699 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1700 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1702 // Make |spdy_stream1| close |spdy_stream2|.
1703 test::ClosingDelegate
delegate1(spdy_stream2
);
1704 spdy_stream1
->SetDelegate(&delegate1
);
1706 // Make |spdy_stream2| close |spdy_stream1|.
1707 test::ClosingDelegate
delegate2(spdy_stream1
);
1708 spdy_stream2
->SetDelegate(&delegate2
);
1710 scoped_ptr
<SpdyHeaderBlock
> headers(
1711 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1712 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1713 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1715 scoped_ptr
<SpdyHeaderBlock
> headers2(
1716 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1717 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1718 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1720 // Ensure that the streams have not yet been activated and assigned an id.
1721 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1722 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1724 // Ensure we don't crash while closing the session.
1725 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
1727 EXPECT_EQ(NULL
, spdy_stream1
.get());
1728 EXPECT_EQ(NULL
, spdy_stream2
.get());
1730 EXPECT_TRUE(delegate1
.StreamIsClosed());
1731 EXPECT_TRUE(delegate2
.StreamIsClosed());
1733 EXPECT_TRUE(session
== NULL
);
1736 // Create two streams that are set to re-close themselves on close,
1737 // activate them, and then close the session. Nothing should blow up.
1738 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedSelfClosingStreams
) {
1739 session_deps_
.host_resolver
->set_synchronous_mode(true);
1741 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1743 scoped_ptr
<SpdyFrame
> req1(
1744 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
1745 scoped_ptr
<SpdyFrame
> req2(
1746 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
1747 MockWrite writes
[] = {
1748 CreateMockWrite(*req1
, 0),
1749 CreateMockWrite(*req2
, 1),
1752 MockRead reads
[] = {
1753 MockRead(ASYNC
, 0, 2) // EOF
1756 DeterministicSocketData
data(reads
, arraysize(reads
),
1757 writes
, arraysize(writes
));
1758 data
.set_connect_data(connect_data
);
1759 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1761 CreateDeterministicNetworkSession();
1763 base::WeakPtr
<SpdySession
> session
=
1764 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1766 GURL
url1(kDefaultURL
);
1767 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1768 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1769 session
, url1
, MEDIUM
, BoundNetLog());
1770 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1771 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1773 GURL
url2(kDefaultURL
);
1774 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1775 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1776 session
, url2
, MEDIUM
, BoundNetLog());
1777 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1778 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1780 test::ClosingDelegate
delegate1(spdy_stream1
);
1781 spdy_stream1
->SetDelegate(&delegate1
);
1783 test::ClosingDelegate
delegate2(spdy_stream2
);
1784 spdy_stream2
->SetDelegate(&delegate2
);
1786 scoped_ptr
<SpdyHeaderBlock
> headers(
1787 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1788 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1789 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1791 scoped_ptr
<SpdyHeaderBlock
> headers2(
1792 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1793 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1794 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1796 // Ensure that the streams have not yet been activated and assigned an id.
1797 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1798 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1802 EXPECT_EQ(1u, spdy_stream1
->stream_id());
1803 EXPECT_EQ(3u, spdy_stream2
->stream_id());
1805 // Ensure we don't crash while closing the session.
1806 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
1808 EXPECT_EQ(NULL
, spdy_stream1
.get());
1809 EXPECT_EQ(NULL
, spdy_stream2
.get());
1811 EXPECT_TRUE(delegate1
.StreamIsClosed());
1812 EXPECT_TRUE(delegate2
.StreamIsClosed());
1814 EXPECT_TRUE(session
== NULL
);
1817 // Create two streams that are set to close each other on close,
1818 // activate them, and then close the session. Nothing should blow up.
1819 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedMutuallyClosingStreams
) {
1820 session_deps_
.host_resolver
->set_synchronous_mode(true);
1822 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1824 scoped_ptr
<SpdyFrame
> req1(
1825 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
1826 scoped_ptr
<SpdyFrame
> req2(
1827 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
1828 MockWrite writes
[] = {
1829 CreateMockWrite(*req1
, 0),
1830 CreateMockWrite(*req2
, 1),
1833 MockRead reads
[] = {
1834 MockRead(ASYNC
, 0, 2) // EOF
1837 DeterministicSocketData
data(reads
, arraysize(reads
),
1838 writes
, arraysize(writes
));
1839 data
.set_connect_data(connect_data
);
1840 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1842 CreateDeterministicNetworkSession();
1844 base::WeakPtr
<SpdySession
> session
=
1845 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1847 GURL
url1(kDefaultURL
);
1848 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1849 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1850 session
, url1
, MEDIUM
, BoundNetLog());
1851 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1852 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1854 GURL
url2(kDefaultURL
);
1855 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1856 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1857 session
, url2
, MEDIUM
, BoundNetLog());
1858 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1859 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1861 // Make |spdy_stream1| close |spdy_stream2|.
1862 test::ClosingDelegate
delegate1(spdy_stream2
);
1863 spdy_stream1
->SetDelegate(&delegate1
);
1865 // Make |spdy_stream2| close |spdy_stream1|.
1866 test::ClosingDelegate
delegate2(spdy_stream1
);
1867 spdy_stream2
->SetDelegate(&delegate2
);
1869 scoped_ptr
<SpdyHeaderBlock
> headers(
1870 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1871 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1872 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1874 scoped_ptr
<SpdyHeaderBlock
> headers2(
1875 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1876 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1877 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1879 // Ensure that the streams have not yet been activated and assigned an id.
1880 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1881 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1885 EXPECT_EQ(1u, spdy_stream1
->stream_id());
1886 EXPECT_EQ(3u, spdy_stream2
->stream_id());
1888 // Ensure we don't crash while closing the session.
1889 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
1891 EXPECT_EQ(NULL
, spdy_stream1
.get());
1892 EXPECT_EQ(NULL
, spdy_stream2
.get());
1894 EXPECT_TRUE(delegate1
.StreamIsClosed());
1895 EXPECT_TRUE(delegate2
.StreamIsClosed());
1897 EXPECT_TRUE(session
== NULL
);
1900 // Delegate that closes a given session when the stream is closed.
1901 class SessionClosingDelegate
: public test::StreamDelegateDoNothing
{
1903 SessionClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
1904 const base::WeakPtr
<SpdySession
>& session_to_close
)
1905 : StreamDelegateDoNothing(stream
),
1906 session_to_close_(session_to_close
) {}
1908 virtual ~SessionClosingDelegate() {}
1910 virtual void OnClose(int status
) OVERRIDE
{
1911 session_to_close_
->CloseSessionOnError(ERR_ABORTED
, "Aborted");
1915 base::WeakPtr
<SpdySession
> session_to_close_
;
1918 // Close an activated stream that closes its session. Nothing should
1919 // blow up. This is a regression test for http://crbug.com/263691 .
1920 TEST_P(SpdySessionTest
, CloseActivatedStreamThatClosesSession
) {
1921 session_deps_
.host_resolver
->set_synchronous_mode(true);
1923 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1925 scoped_ptr
<SpdyFrame
> req(
1926 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
1927 MockWrite writes
[] = {
1928 CreateMockWrite(*req
, 0),
1931 MockRead reads
[] = {
1932 MockRead(ASYNC
, 0, 1) // EOF
1934 DeterministicSocketData
data(reads
, arraysize(reads
),
1935 writes
, arraysize(writes
));
1936 data
.set_connect_data(connect_data
);
1937 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1939 CreateDeterministicNetworkSession();
1941 base::WeakPtr
<SpdySession
> session
=
1942 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1944 GURL
url(kDefaultURL
);
1945 base::WeakPtr
<SpdyStream
> spdy_stream
=
1946 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1947 session
, url
, MEDIUM
, BoundNetLog());
1948 ASSERT_TRUE(spdy_stream
.get() != NULL
);
1949 EXPECT_EQ(0u, spdy_stream
->stream_id());
1951 SessionClosingDelegate
delegate(spdy_stream
, session
);
1952 spdy_stream
->SetDelegate(&delegate
);
1954 scoped_ptr
<SpdyHeaderBlock
> headers(
1955 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1956 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1957 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
1959 EXPECT_EQ(0u, spdy_stream
->stream_id());
1963 EXPECT_EQ(1u, spdy_stream
->stream_id());
1965 // Ensure we don't crash while closing the stream (which closes the
1967 spdy_stream
->Cancel();
1969 EXPECT_EQ(NULL
, spdy_stream
.get());
1970 EXPECT_TRUE(delegate
.StreamIsClosed());
1971 EXPECT_TRUE(session
== NULL
);
1974 TEST_P(SpdySessionTest
, VerifyDomainAuthentication
) {
1975 session_deps_
.host_resolver
->set_synchronous_mode(true);
1977 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1979 // No actual data will be sent.
1980 MockWrite writes
[] = {
1981 MockWrite(ASYNC
, 0, 1) // EOF
1984 MockRead reads
[] = {
1985 MockRead(ASYNC
, 0, 0) // EOF
1987 DeterministicSocketData
data(reads
, arraysize(reads
),
1988 writes
, arraysize(writes
));
1989 data
.set_connect_data(connect_data
);
1990 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1992 // Load a cert that is valid for:
1996 base::FilePath certs_dir
= GetTestCertsDirectory();
1997 scoped_refptr
<X509Certificate
> test_cert(
1998 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
1999 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
);
2001 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2002 ssl
.cert
= test_cert
;
2003 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2005 CreateDeterministicNetworkSession();
2007 base::WeakPtr
<SpdySession
> session
=
2008 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2010 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2011 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2012 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.com"));
2013 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2016 TEST_P(SpdySessionTest
, ConnectionPooledWithTlsChannelId
) {
2017 session_deps_
.host_resolver
->set_synchronous_mode(true);
2019 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2021 // No actual data will be sent.
2022 MockWrite writes
[] = {
2023 MockWrite(ASYNC
, 0, 1) // EOF
2026 MockRead reads
[] = {
2027 MockRead(ASYNC
, 0, 0) // EOF
2029 DeterministicSocketData
data(reads
, arraysize(reads
),
2030 writes
, arraysize(writes
));
2031 data
.set_connect_data(connect_data
);
2032 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2034 // Load a cert that is valid for:
2038 base::FilePath certs_dir
= GetTestCertsDirectory();
2039 scoped_refptr
<X509Certificate
> test_cert(
2040 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2041 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
);
2043 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2044 ssl
.channel_id_sent
= true;
2045 ssl
.cert
= test_cert
;
2046 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2048 CreateDeterministicNetworkSession();
2050 base::WeakPtr
<SpdySession
> session
=
2051 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2053 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2054 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2055 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.example.com"));
2056 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2059 TEST_P(SpdySessionTest
, CloseTwoStalledCreateStream
) {
2060 // TODO(rtenneti): Define a helper class/methods and move the common code in
2062 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2064 SettingsMap new_settings
;
2065 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
2066 const uint32 max_concurrent_streams
= 1;
2067 new_settings
[kSpdySettingsIds1
] =
2068 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
2070 scoped_ptr
<SpdyFrame
> req1(
2071 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2072 scoped_ptr
<SpdyFrame
> req2(
2073 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
2074 scoped_ptr
<SpdyFrame
> req3(
2075 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
2076 MockWrite writes
[] = {
2077 CreateMockWrite(*req1
, 1),
2078 CreateMockWrite(*req2
, 4),
2079 CreateMockWrite(*req3
, 7),
2082 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2084 scoped_ptr
<SpdyFrame
> settings_frame(
2085 spdy_util_
.ConstructSpdySettings(new_settings
));
2087 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2088 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2090 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
2091 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
2093 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
2094 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
2096 MockRead reads
[] = {
2097 CreateMockRead(*settings_frame
),
2098 CreateMockRead(*resp1
, 2),
2099 CreateMockRead(*body1
, 3),
2100 CreateMockRead(*resp2
, 5),
2101 CreateMockRead(*body2
, 6),
2102 CreateMockRead(*resp3
, 8),
2103 CreateMockRead(*body3
, 9),
2104 MockRead(ASYNC
, 0, 10) // EOF
2107 DeterministicSocketData
data(reads
, arraysize(reads
),
2108 writes
, arraysize(writes
));
2109 data
.set_connect_data(connect_data
);
2110 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2112 CreateDeterministicNetworkSession();
2114 base::WeakPtr
<SpdySession
> session
=
2115 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2117 // Read the settings frame.
2120 GURL
url1(kDefaultURL
);
2121 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2122 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2123 session
, url1
, LOWEST
, BoundNetLog());
2124 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2125 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2126 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2127 spdy_stream1
->SetDelegate(&delegate1
);
2129 TestCompletionCallback callback2
;
2130 GURL
url2(kDefaultURL
);
2131 SpdyStreamRequest request2
;
2132 ASSERT_EQ(ERR_IO_PENDING
,
2133 request2
.StartRequest(
2134 SPDY_REQUEST_RESPONSE_STREAM
,
2135 session
, url2
, LOWEST
, BoundNetLog(), callback2
.callback()));
2137 TestCompletionCallback callback3
;
2138 GURL
url3(kDefaultURL
);
2139 SpdyStreamRequest request3
;
2140 ASSERT_EQ(ERR_IO_PENDING
,
2141 request3
.StartRequest(
2142 SPDY_REQUEST_RESPONSE_STREAM
,
2143 session
, url3
, LOWEST
, BoundNetLog(), callback3
.callback()));
2145 EXPECT_EQ(0u, session
->num_active_streams());
2146 EXPECT_EQ(1u, session
->num_created_streams());
2147 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2149 scoped_ptr
<SpdyHeaderBlock
> headers(
2150 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2151 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2152 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2154 // Run until 1st stream is activated and then closed.
2155 EXPECT_EQ(0u, delegate1
.stream_id());
2157 EXPECT_EQ(NULL
, spdy_stream1
.get());
2158 EXPECT_EQ(1u, delegate1
.stream_id());
2160 EXPECT_EQ(0u, session
->num_active_streams());
2161 EXPECT_EQ(0u, session
->num_created_streams());
2162 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2164 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2165 // create the 2nd stream.
2166 base::MessageLoop::current()->RunUntilIdle();
2168 EXPECT_EQ(0u, session
->num_active_streams());
2169 EXPECT_EQ(1u, session
->num_created_streams());
2170 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2172 base::WeakPtr
<SpdyStream
> stream2
= request2
.ReleaseStream();
2173 test::StreamDelegateDoNothing
delegate2(stream2
);
2174 stream2
->SetDelegate(&delegate2
);
2175 scoped_ptr
<SpdyHeaderBlock
> headers2(
2176 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2177 stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2178 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
2180 // Run until 2nd stream is activated and then closed.
2181 EXPECT_EQ(0u, delegate2
.stream_id());
2183 EXPECT_EQ(NULL
, stream2
.get());
2184 EXPECT_EQ(3u, delegate2
.stream_id());
2186 EXPECT_EQ(0u, session
->num_active_streams());
2187 EXPECT_EQ(0u, session
->num_created_streams());
2188 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2190 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2191 // create the 3rd stream.
2192 base::MessageLoop::current()->RunUntilIdle();
2194 EXPECT_EQ(0u, session
->num_active_streams());
2195 EXPECT_EQ(1u, session
->num_created_streams());
2196 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2198 base::WeakPtr
<SpdyStream
> stream3
= request3
.ReleaseStream();
2199 test::StreamDelegateDoNothing
delegate3(stream3
);
2200 stream3
->SetDelegate(&delegate3
);
2201 scoped_ptr
<SpdyHeaderBlock
> headers3(
2202 spdy_util_
.ConstructGetHeaderBlock(url3
.spec()));
2203 stream3
->SendRequestHeaders(headers3
.Pass(), NO_MORE_DATA_TO_SEND
);
2204 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
2206 // Run until 2nd stream is activated and then closed.
2207 EXPECT_EQ(0u, delegate3
.stream_id());
2209 EXPECT_EQ(NULL
, stream3
.get());
2210 EXPECT_EQ(5u, delegate3
.stream_id());
2212 EXPECT_EQ(0u, session
->num_active_streams());
2213 EXPECT_EQ(0u, session
->num_created_streams());
2214 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2219 TEST_P(SpdySessionTest
, CancelTwoStalledCreateStream
) {
2220 session_deps_
.host_resolver
->set_synchronous_mode(true);
2222 MockRead reads
[] = {
2223 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2226 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
2227 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2229 data
.set_connect_data(connect_data
);
2230 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2232 CreateNetworkSession();
2234 base::WeakPtr
<SpdySession
> session
=
2235 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2237 // Leave room for only one more stream to be created.
2238 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
2239 base::WeakPtr
<SpdyStream
> spdy_stream
=
2240 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2241 session
, test_url_
, MEDIUM
, BoundNetLog());
2242 ASSERT_TRUE(spdy_stream
!= NULL
);
2245 GURL
url1(kDefaultURL
);
2246 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2247 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2248 session
, url1
, LOWEST
, BoundNetLog());
2249 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2250 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2252 TestCompletionCallback callback2
;
2253 GURL
url2(kDefaultURL
);
2254 SpdyStreamRequest request2
;
2255 ASSERT_EQ(ERR_IO_PENDING
,
2256 request2
.StartRequest(
2257 SPDY_BIDIRECTIONAL_STREAM
, session
, url2
, LOWEST
, BoundNetLog(),
2258 callback2
.callback()));
2260 TestCompletionCallback callback3
;
2261 GURL
url3(kDefaultURL
);
2262 SpdyStreamRequest request3
;
2263 ASSERT_EQ(ERR_IO_PENDING
,
2264 request3
.StartRequest(
2265 SPDY_BIDIRECTIONAL_STREAM
, session
, url3
, LOWEST
, BoundNetLog(),
2266 callback3
.callback()));
2268 EXPECT_EQ(0u, session
->num_active_streams());
2269 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2270 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2272 // Cancel the first stream; this will allow the second stream to be created.
2273 EXPECT_TRUE(spdy_stream1
.get() != NULL
);
2274 spdy_stream1
->Cancel();
2275 EXPECT_EQ(NULL
, spdy_stream1
.get());
2277 EXPECT_EQ(OK
, callback2
.WaitForResult());
2278 EXPECT_EQ(0u, session
->num_active_streams());
2279 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2280 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2282 // Cancel the second stream; this will allow the third stream to be created.
2283 base::WeakPtr
<SpdyStream
> spdy_stream2
= request2
.ReleaseStream();
2284 spdy_stream2
->Cancel();
2285 EXPECT_EQ(NULL
, spdy_stream2
.get());
2287 EXPECT_EQ(OK
, callback3
.WaitForResult());
2288 EXPECT_EQ(0u, session
->num_active_streams());
2289 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2290 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2292 // Cancel the third stream.
2293 base::WeakPtr
<SpdyStream
> spdy_stream3
= request3
.ReleaseStream();
2294 spdy_stream3
->Cancel();
2295 EXPECT_EQ(NULL
, spdy_stream3
.get());
2296 EXPECT_EQ(0u, session
->num_active_streams());
2297 EXPECT_EQ(kInitialMaxConcurrentStreams
- 1, session
->num_created_streams());
2298 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2301 // Test that SpdySession::DoReadLoop reads data from the socket
2302 // without yielding. This test makes 32k - 1 bytes of data available
2303 // on the socket for reading. It then verifies that it has read all
2304 // the available data without yielding.
2305 TEST_P(SpdySessionTest
, ReadDataWithoutYielding
) {
2306 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2307 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2309 scoped_ptr
<SpdyFrame
> req1(
2310 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2311 MockWrite writes
[] = {
2312 CreateMockWrite(*req1
, 0),
2315 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2316 // (-spdy_data_frame_size).
2317 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2318 const int kPayloadSize
=
2319 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2320 TestDataStream test_stream
;
2321 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
2322 char* payload_data
= payload
->data();
2323 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2325 scoped_ptr
<SpdyFrame
> partial_data_frame(
2326 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2327 scoped_ptr
<SpdyFrame
> finish_data_frame(
2328 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
- 1, DATA_FLAG_FIN
));
2330 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2332 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2334 MockRead reads
[] = {
2335 CreateMockRead(*resp1
, 1),
2336 CreateMockRead(*partial_data_frame
, 2),
2337 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2338 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2339 CreateMockRead(*finish_data_frame
, 5, SYNCHRONOUS
),
2340 MockRead(ASYNC
, 0, 6) // EOF
2343 // Create SpdySession and SpdyStream and send the request.
2344 DeterministicSocketData
data(reads
, arraysize(reads
),
2345 writes
, arraysize(writes
));
2346 data
.set_connect_data(connect_data
);
2347 session_deps_
.host_resolver
->set_synchronous_mode(true);
2348 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2350 CreateDeterministicNetworkSession();
2352 base::WeakPtr
<SpdySession
> session
=
2353 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2355 GURL
url1(kDefaultURL
);
2356 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2357 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2358 session
, url1
, MEDIUM
, BoundNetLog());
2359 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2360 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2361 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2362 spdy_stream1
->SetDelegate(&delegate1
);
2364 scoped_ptr
<SpdyHeaderBlock
> headers1(
2365 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2366 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2367 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2369 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2371 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2373 // Run until 1st read.
2374 EXPECT_EQ(0u, delegate1
.stream_id());
2376 EXPECT_EQ(1u, delegate1
.stream_id());
2377 EXPECT_EQ(0u, observer
.executed_count());
2379 // Read all the data and verify SpdySession::DoReadLoop has not
2382 EXPECT_EQ(NULL
, spdy_stream1
.get());
2384 // Verify task observer's executed_count is zero, which indicates DoRead read
2385 // all the available data.
2386 EXPECT_EQ(0u, observer
.executed_count());
2387 EXPECT_TRUE(data
.at_write_eof());
2388 EXPECT_TRUE(data
.at_read_eof());
2391 // Test that SpdySession::DoReadLoop yields while reading the
2392 // data. This test makes 32k + 1 bytes of data available on the socket
2393 // for reading. It then verifies that DoRead has yielded even though
2394 // there is data available for it to read (i.e, socket()->Read didn't
2395 // return ERR_IO_PENDING during socket reads).
2396 TEST_P(SpdySessionTest
, TestYieldingDuringReadData
) {
2397 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2398 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2400 scoped_ptr
<SpdyFrame
> req1(
2401 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2402 MockWrite writes
[] = {
2403 CreateMockWrite(*req1
, 0),
2406 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2407 // (-spdy_data_frame_size).
2408 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2409 const int kPayloadSize
=
2410 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2411 TestDataStream test_stream
;
2412 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
2413 char* payload_data
= payload
->data();
2414 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2416 scoped_ptr
<SpdyFrame
> partial_data_frame(
2417 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2418 scoped_ptr
<SpdyFrame
> finish_data_frame(
2419 framer
.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN
));
2421 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2423 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2424 MockRead reads
[] = {
2425 CreateMockRead(*resp1
, 1),
2426 CreateMockRead(*partial_data_frame
, 2),
2427 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2428 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2429 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2430 CreateMockRead(*finish_data_frame
, 6, SYNCHRONOUS
),
2431 MockRead(ASYNC
, 0, 7) // EOF
2434 // Create SpdySession and SpdyStream and send the request.
2435 DeterministicSocketData
data(reads
, arraysize(reads
),
2436 writes
, arraysize(writes
));
2437 data
.set_connect_data(connect_data
);
2438 session_deps_
.host_resolver
->set_synchronous_mode(true);
2439 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2441 CreateDeterministicNetworkSession();
2443 base::WeakPtr
<SpdySession
> session
=
2444 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2446 GURL
url1(kDefaultURL
);
2447 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2448 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2449 session
, url1
, MEDIUM
, BoundNetLog());
2450 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2451 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2452 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2453 spdy_stream1
->SetDelegate(&delegate1
);
2455 scoped_ptr
<SpdyHeaderBlock
> headers1(
2456 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2457 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2458 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2460 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2462 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2464 // Run until 1st read.
2465 EXPECT_EQ(0u, delegate1
.stream_id());
2467 EXPECT_EQ(1u, delegate1
.stream_id());
2468 EXPECT_EQ(0u, observer
.executed_count());
2470 // Read all the data and verify SpdySession::DoReadLoop has posted a
2473 EXPECT_EQ(NULL
, spdy_stream1
.get());
2475 // Verify task observer's executed_count is 1, which indicates DoRead has
2476 // posted only one task and thus yielded though there is data available for it
2478 EXPECT_EQ(1u, observer
.executed_count());
2479 EXPECT_TRUE(data
.at_write_eof());
2480 EXPECT_TRUE(data
.at_read_eof());
2483 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2484 // + async, by doing the following MockReads.
2486 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2487 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2489 // The above reads 26K synchronously. Since that is less that 32K, we
2490 // will attempt to read again. However, that DoRead() will return
2491 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2492 // yield. When we come back, DoRead() will read the results from the
2493 // async read, and rest of the data synchronously.
2494 TEST_P(SpdySessionTest
, TestYieldingDuringAsyncReadData
) {
2495 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2496 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2498 scoped_ptr
<SpdyFrame
> req1(
2499 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2500 MockWrite writes
[] = {
2501 CreateMockWrite(*req1
, 0),
2504 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2505 // (-spdy_data_frame_size).
2506 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2507 TestDataStream test_stream
;
2508 const int kEightKPayloadSize
=
2509 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2510 scoped_refptr
<net::IOBuffer
> eightk_payload(
2511 new net::IOBuffer(kEightKPayloadSize
));
2512 char* eightk_payload_data
= eightk_payload
->data();
2513 test_stream
.GetBytes(eightk_payload_data
, kEightKPayloadSize
);
2515 // Build buffer of 2k size.
2516 TestDataStream test_stream2
;
2517 const int kTwoKPayloadSize
= kEightKPayloadSize
- 6 * 1024;
2518 scoped_refptr
<net::IOBuffer
> twok_payload(
2519 new net::IOBuffer(kTwoKPayloadSize
));
2520 char* twok_payload_data
= twok_payload
->data();
2521 test_stream2
.GetBytes(twok_payload_data
, kTwoKPayloadSize
);
2523 scoped_ptr
<SpdyFrame
> eightk_data_frame(framer
.CreateDataFrame(
2524 1, eightk_payload_data
, kEightKPayloadSize
, DATA_FLAG_NONE
));
2525 scoped_ptr
<SpdyFrame
> twok_data_frame(framer
.CreateDataFrame(
2526 1, twok_payload_data
, kTwoKPayloadSize
, DATA_FLAG_NONE
));
2527 scoped_ptr
<SpdyFrame
> finish_data_frame(framer
.CreateDataFrame(
2528 1, "h", 1, DATA_FLAG_FIN
));
2530 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2532 MockRead reads
[] = {
2533 CreateMockRead(*resp1
, 1),
2534 CreateMockRead(*eightk_data_frame
, 2),
2535 CreateMockRead(*eightk_data_frame
, 3, SYNCHRONOUS
),
2536 CreateMockRead(*eightk_data_frame
, 4, SYNCHRONOUS
),
2537 CreateMockRead(*twok_data_frame
, 5, SYNCHRONOUS
),
2538 CreateMockRead(*eightk_data_frame
, 6, ASYNC
),
2539 CreateMockRead(*eightk_data_frame
, 7, SYNCHRONOUS
),
2540 CreateMockRead(*eightk_data_frame
, 8, SYNCHRONOUS
),
2541 CreateMockRead(*eightk_data_frame
, 9, SYNCHRONOUS
),
2542 CreateMockRead(*twok_data_frame
, 10, SYNCHRONOUS
),
2543 CreateMockRead(*finish_data_frame
, 11, SYNCHRONOUS
),
2544 MockRead(ASYNC
, 0, 12) // EOF
2547 // Create SpdySession and SpdyStream and send the request.
2548 DeterministicSocketData
data(reads
, arraysize(reads
),
2549 writes
, arraysize(writes
));
2550 data
.set_connect_data(connect_data
);
2551 session_deps_
.host_resolver
->set_synchronous_mode(true);
2552 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2554 CreateDeterministicNetworkSession();
2556 base::WeakPtr
<SpdySession
> session
=
2557 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2559 GURL
url1(kDefaultURL
);
2560 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2561 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2562 session
, url1
, MEDIUM
, BoundNetLog());
2563 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2564 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2565 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2566 spdy_stream1
->SetDelegate(&delegate1
);
2568 scoped_ptr
<SpdyHeaderBlock
> headers1(
2569 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2570 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2571 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2573 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2574 // posting of tasks.
2575 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2577 // Run until 1st read.
2578 EXPECT_EQ(0u, delegate1
.stream_id());
2580 EXPECT_EQ(1u, delegate1
.stream_id());
2581 EXPECT_EQ(0u, observer
.executed_count());
2583 // Read all the data and verify SpdySession::DoReadLoop has posted a
2586 EXPECT_EQ(NULL
, spdy_stream1
.get());
2588 // Verify task observer's executed_count is 1, which indicates DoRead has
2589 // posted only one task and thus yielded though there is data available for
2591 EXPECT_EQ(1u, observer
.executed_count());
2592 EXPECT_TRUE(data
.at_write_eof());
2593 EXPECT_TRUE(data
.at_read_eof());
2596 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2597 // nothing blows up.
2598 TEST_P(SpdySessionTest
, GoAwayWhileInDoReadLoop
) {
2599 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2600 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2602 scoped_ptr
<SpdyFrame
> req1(
2603 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2604 MockWrite writes
[] = {
2605 CreateMockWrite(*req1
, 0),
2608 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2609 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2610 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
2612 MockRead reads
[] = {
2613 CreateMockRead(*resp1
, 1),
2614 CreateMockRead(*body1
, 2),
2615 CreateMockRead(*goaway
, 3),
2618 // Create SpdySession and SpdyStream and send the request.
2619 DeterministicSocketData
data(reads
, arraysize(reads
),
2620 writes
, arraysize(writes
));
2621 data
.set_connect_data(connect_data
);
2622 session_deps_
.host_resolver
->set_synchronous_mode(true);
2623 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2625 CreateDeterministicNetworkSession();
2627 base::WeakPtr
<SpdySession
> session
=
2628 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2630 GURL
url1(kDefaultURL
);
2631 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2632 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2633 session
, url1
, MEDIUM
, BoundNetLog());
2634 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2635 spdy_stream1
->SetDelegate(&delegate1
);
2636 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2637 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2639 scoped_ptr
<SpdyHeaderBlock
> headers1(
2640 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2641 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2642 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2644 // Run until 1st read.
2645 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2647 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2649 // Run until GoAway.
2651 EXPECT_EQ(NULL
, spdy_stream1
.get());
2652 EXPECT_TRUE(data
.at_write_eof());
2653 EXPECT_TRUE(data
.at_read_eof());
2654 EXPECT_TRUE(session
== NULL
);
2657 // Within this framework, a SpdySession should be initialized with
2658 // flow control disabled for protocol version 2, with flow control
2659 // enabled only for streams for protocol version 3, and with flow
2660 // control enabled for streams and sessions for higher versions.
2661 TEST_P(SpdySessionTest
, ProtocolNegotiation
) {
2662 session_deps_
.host_resolver
->set_synchronous_mode(true);
2664 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2665 MockRead reads
[] = {
2666 MockRead(SYNCHRONOUS
, 0, 0) // EOF
2668 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
2669 data
.set_connect_data(connect_data
);
2670 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2672 CreateNetworkSession();
2673 base::WeakPtr
<SpdySession
> session
=
2674 CreateFakeSpdySession(spdy_session_pool_
, key_
);
2676 EXPECT_EQ(spdy_util_
.spdy_version(),
2677 session
->buffered_spdy_framer_
->protocol_version());
2678 if (GetParam() == kProtoDeprecatedSPDY2
) {
2679 EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE
, session
->flow_control_state());
2680 EXPECT_EQ(0, session
->session_send_window_size_
);
2681 EXPECT_EQ(0, session
->session_recv_window_size_
);
2682 } else if (GetParam() == kProtoSPDY3
) {
2683 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM
, session
->flow_control_state());
2684 EXPECT_EQ(0, session
->session_send_window_size_
);
2685 EXPECT_EQ(0, session
->session_recv_window_size_
);
2687 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
2688 session
->flow_control_state());
2689 EXPECT_EQ(kSpdySessionInitialWindowSize
,
2690 session
->session_send_window_size_
);
2691 EXPECT_EQ(kSpdySessionInitialWindowSize
,
2692 session
->session_recv_window_size_
);
2694 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
2697 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2698 // pointers to the idle session are currently held.
2699 TEST_P(SpdySessionTest
, CloseOneIdleConnection
) {
2700 ClientSocketPoolManager::set_max_sockets_per_group(
2701 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2702 ClientSocketPoolManager::set_max_sockets_per_pool(
2703 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2705 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2706 MockRead reads
[] = {
2707 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2709 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
2710 data
.set_connect_data(connect_data
);
2711 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2712 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2714 CreateNetworkSession();
2716 TransportClientSocketPool
* pool
=
2717 http_session_
->GetTransportSocketPool(
2718 HttpNetworkSession::NORMAL_SOCKET_POOL
);
2720 // Create an idle SPDY session.
2721 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2722 kPrivacyModeDisabled
);
2723 base::WeakPtr
<SpdySession
> session1
=
2724 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
2725 EXPECT_FALSE(pool
->IsStalled());
2727 // Trying to create a new connection should cause the pool to be stalled, and
2728 // post a task asynchronously to try and close the session.
2729 TestCompletionCallback callback2
;
2730 HostPortPair
host_port2("2.com", 80);
2731 scoped_refptr
<TransportSocketParams
> params2(
2732 new TransportSocketParams(host_port2
, false, false,
2733 OnHostResolutionCallback()));
2734 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
2735 EXPECT_EQ(ERR_IO_PENDING
,
2736 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
2737 callback2
.callback(), pool
, BoundNetLog()));
2738 EXPECT_TRUE(pool
->IsStalled());
2740 // The socket pool should close the connection asynchronously and establish a
2742 EXPECT_EQ(OK
, callback2
.WaitForResult());
2743 EXPECT_FALSE(pool
->IsStalled());
2744 EXPECT_TRUE(session1
== NULL
);
2747 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2748 // pointers to the idle session are currently held, in the case the SPDY session
2750 TEST_P(SpdySessionTest
, CloseOneIdleConnectionWithAlias
) {
2751 ClientSocketPoolManager::set_max_sockets_per_group(
2752 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2753 ClientSocketPoolManager::set_max_sockets_per_pool(
2754 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2756 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2757 MockRead reads
[] = {
2758 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2760 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
2761 data
.set_connect_data(connect_data
);
2762 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2763 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2765 session_deps_
.host_resolver
->set_synchronous_mode(true);
2766 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
2767 "1.com", "192.168.0.2", std::string());
2768 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
2769 "2.com", "192.168.0.2", std::string());
2770 // Not strictly needed.
2771 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
2772 "3.com", "192.168.0.3", std::string());
2774 CreateNetworkSession();
2776 TransportClientSocketPool
* pool
=
2777 http_session_
->GetTransportSocketPool(
2778 HttpNetworkSession::NORMAL_SOCKET_POOL
);
2780 // Create an idle SPDY session.
2781 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2782 kPrivacyModeDisabled
);
2783 base::WeakPtr
<SpdySession
> session1
=
2784 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
2785 EXPECT_FALSE(pool
->IsStalled());
2787 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
2788 SpdySessionKey
key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
2789 kPrivacyModeDisabled
);
2790 HostResolver::RequestInfo
info(key2
.host_port_pair());
2791 AddressList addresses
;
2792 // Pre-populate the DNS cache, since a synchronous resolution is required in
2793 // order to create the alias.
2794 session_deps_
.host_resolver
->Resolve(info
,
2797 CompletionCallback(),
2800 // Get a session for |key2|, which should return the session created earlier.
2801 base::WeakPtr
<SpdySession
> session2
=
2802 spdy_session_pool_
->FindAvailableSession(key2
, BoundNetLog());
2803 ASSERT_EQ(session1
.get(), session2
.get());
2804 EXPECT_FALSE(pool
->IsStalled());
2806 // Trying to create a new connection should cause the pool to be stalled, and
2807 // post a task asynchronously to try and close the session.
2808 TestCompletionCallback callback3
;
2809 HostPortPair
host_port3("3.com", 80);
2810 scoped_refptr
<TransportSocketParams
> params3(
2811 new TransportSocketParams(host_port3
, false, false,
2812 OnHostResolutionCallback()));
2813 scoped_ptr
<ClientSocketHandle
> connection3(new ClientSocketHandle
);
2814 EXPECT_EQ(ERR_IO_PENDING
,
2815 connection3
->Init(host_port3
.ToString(), params3
, DEFAULT_PRIORITY
,
2816 callback3
.callback(), pool
, BoundNetLog()));
2817 EXPECT_TRUE(pool
->IsStalled());
2819 // The socket pool should close the connection asynchronously and establish a
2821 EXPECT_EQ(OK
, callback3
.WaitForResult());
2822 EXPECT_FALSE(pool
->IsStalled());
2823 EXPECT_TRUE(session1
== NULL
);
2824 EXPECT_TRUE(session2
== NULL
);
2827 // Tests that when a SPDY session becomes idle, it closes itself if there is
2828 // a lower layer pool stalled on the per-pool socket limit.
2829 TEST_P(SpdySessionTest
, CloseSessionOnIdleWhenPoolStalled
) {
2830 ClientSocketPoolManager::set_max_sockets_per_group(
2831 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2832 ClientSocketPoolManager::set_max_sockets_per_pool(
2833 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2835 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2836 MockRead reads
[] = {
2837 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2839 scoped_ptr
<SpdyFrame
> req1(
2840 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2841 scoped_ptr
<SpdyFrame
> cancel1(
2842 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2843 MockWrite writes
[] = {
2844 CreateMockWrite(*req1
, 1),
2845 CreateMockWrite(*cancel1
, 1),
2847 StaticSocketDataProvider
data(reads
, arraysize(reads
),
2848 writes
, arraysize(writes
));
2849 data
.set_connect_data(connect_data
);
2850 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2852 MockRead http_reads
[] = {
2853 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2855 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
2857 http_data
.set_connect_data(connect_data
);
2858 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
2861 CreateNetworkSession();
2863 TransportClientSocketPool
* pool
=
2864 http_session_
->GetTransportSocketPool(
2865 HttpNetworkSession::NORMAL_SOCKET_POOL
);
2867 // Create a SPDY session.
2868 GURL
url1(kDefaultURL
);
2869 SpdySessionKey
key1(HostPortPair(url1
.host(), 80),
2870 ProxyServer::Direct(), kPrivacyModeDisabled
);
2871 base::WeakPtr
<SpdySession
> session1
=
2872 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
2873 EXPECT_FALSE(pool
->IsStalled());
2875 // Create a stream using the session, and send a request.
2877 TestCompletionCallback callback1
;
2878 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2879 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2880 session1
, url1
, DEFAULT_PRIORITY
,
2882 ASSERT_TRUE(spdy_stream1
.get());
2883 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2884 spdy_stream1
->SetDelegate(&delegate1
);
2886 scoped_ptr
<SpdyHeaderBlock
> headers1(
2887 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2888 EXPECT_EQ(ERR_IO_PENDING
,
2889 spdy_stream1
->SendRequestHeaders(
2890 headers1
.Pass(), NO_MORE_DATA_TO_SEND
));
2891 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2893 base::MessageLoop::current()->RunUntilIdle();
2895 // Trying to create a new connection should cause the pool to be stalled, and
2896 // post a task asynchronously to try and close the session.
2897 TestCompletionCallback callback2
;
2898 HostPortPair
host_port2("2.com", 80);
2899 scoped_refptr
<TransportSocketParams
> params2(
2900 new TransportSocketParams(host_port2
, false, false,
2901 OnHostResolutionCallback()));
2902 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
2903 EXPECT_EQ(ERR_IO_PENDING
,
2904 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
2905 callback2
.callback(), pool
, BoundNetLog()));
2906 EXPECT_TRUE(pool
->IsStalled());
2908 // Running the message loop should cause the socket pool to ask the SPDY
2909 // session to close an idle socket, but since the socket is in use, nothing
2911 base::RunLoop().RunUntilIdle();
2912 EXPECT_TRUE(pool
->IsStalled());
2913 EXPECT_FALSE(callback2
.have_result());
2915 // Cancelling the request should result in the session's socket being
2916 // closed, since the pool is stalled.
2917 ASSERT_TRUE(spdy_stream1
.get());
2918 spdy_stream1
->Cancel();
2919 base::RunLoop().RunUntilIdle();
2920 ASSERT_FALSE(pool
->IsStalled());
2921 EXPECT_EQ(OK
, callback2
.WaitForResult());
2924 // Verify that SpdySessionKey and therefore SpdySession is different when
2925 // privacy mode is enabled or disabled.
2926 TEST_P(SpdySessionTest
, SpdySessionKeyPrivacyMode
) {
2927 CreateDeterministicNetworkSession();
2929 HostPortPair
host_port_pair("www.google.com", 443);
2930 SpdySessionKey
key_privacy_enabled(host_port_pair
, ProxyServer::Direct(),
2931 kPrivacyModeEnabled
);
2932 SpdySessionKey
key_privacy_disabled(host_port_pair
, ProxyServer::Direct(),
2933 kPrivacyModeDisabled
);
2935 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
2936 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
2938 // Add SpdySession with PrivacyMode Enabled to the pool.
2939 base::WeakPtr
<SpdySession
> session_privacy_enabled
=
2940 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_enabled
);
2942 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
2943 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
2945 // Add SpdySession with PrivacyMode Disabled to the pool.
2946 base::WeakPtr
<SpdySession
> session_privacy_disabled
=
2947 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_disabled
);
2949 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
2950 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
2952 session_privacy_enabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
2953 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
2954 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
2956 session_privacy_disabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
2957 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
2958 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
2961 // Delegate that creates another stream when its stream is closed.
2962 class StreamCreatingDelegate
: public test::StreamDelegateDoNothing
{
2964 StreamCreatingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
2965 const base::WeakPtr
<SpdySession
>& session
)
2966 : StreamDelegateDoNothing(stream
),
2967 session_(session
) {}
2969 virtual ~StreamCreatingDelegate() {}
2971 virtual void OnClose(int status
) OVERRIDE
{
2972 GURL
url(kDefaultURL
);
2974 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2975 session_
, url
, MEDIUM
, BoundNetLog()));
2979 const base::WeakPtr
<SpdySession
> session_
;
2982 // Create another stream in response to a stream being reset. Nothing
2983 // should blow up. This is a regression test for
2984 // http://crbug.com/263690 .
2985 TEST_P(SpdySessionTest
, CreateStreamOnStreamReset
) {
2986 session_deps_
.host_resolver
->set_synchronous_mode(true);
2988 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2990 scoped_ptr
<SpdyFrame
> req(
2991 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2992 MockWrite writes
[] = {
2993 CreateMockWrite(*req
, 0),
2996 scoped_ptr
<SpdyFrame
> rst(
2997 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
2998 MockRead reads
[] = {
2999 CreateMockRead(*rst
, 1),
3000 MockRead(ASYNC
, 0, 2) // EOF
3002 DeterministicSocketData
data(reads
, arraysize(reads
),
3003 writes
, arraysize(writes
));
3004 data
.set_connect_data(connect_data
);
3005 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3007 CreateDeterministicNetworkSession();
3009 base::WeakPtr
<SpdySession
> session
=
3010 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3012 GURL
url(kDefaultURL
);
3013 base::WeakPtr
<SpdyStream
> spdy_stream
=
3014 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3015 session
, url
, MEDIUM
, BoundNetLog());
3016 ASSERT_TRUE(spdy_stream
.get() != NULL
);
3017 EXPECT_EQ(0u, spdy_stream
->stream_id());
3019 StreamCreatingDelegate
delegate(spdy_stream
, session
);
3020 spdy_stream
->SetDelegate(&delegate
);
3022 scoped_ptr
<SpdyHeaderBlock
> headers(
3023 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
3024 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
3025 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
3027 EXPECT_EQ(0u, spdy_stream
->stream_id());
3031 EXPECT_EQ(1u, spdy_stream
->stream_id());
3033 // Cause the stream to be reset, which should cause another stream
3037 EXPECT_EQ(NULL
, spdy_stream
.get());
3038 EXPECT_TRUE(delegate
.StreamIsClosed());
3039 EXPECT_EQ(0u, session
->num_active_streams());
3040 EXPECT_EQ(1u, session
->num_created_streams());
3043 // The tests below are only for SPDY/3 and above.
3045 TEST_P(SpdySessionTest
, UpdateStreamsSendWindowSize
) {
3046 if (GetParam() < kProtoSPDY3
)
3049 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3051 SettingsMap new_settings
;
3052 int32 window_size
= 1;
3053 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
3054 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, window_size
);
3056 // Set up the socket so we read a SETTINGS frame that sets
3057 // INITIAL_WINDOW_SIZE.
3058 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3059 scoped_ptr
<SpdyFrame
> settings_frame(
3060 spdy_util_
.ConstructSpdySettings(new_settings
));
3061 MockRead reads
[] = {
3062 CreateMockRead(*settings_frame
, 0),
3063 MockRead(ASYNC
, 0, 1) // EOF
3066 session_deps_
.host_resolver
->set_synchronous_mode(true);
3068 scoped_ptr
<DeterministicSocketData
> data(
3069 new DeterministicSocketData(reads
, arraysize(reads
), NULL
, 0));
3070 data
->set_connect_data(connect_data
);
3071 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(data
.get());
3073 CreateDeterministicNetworkSession();
3075 base::WeakPtr
<SpdySession
> session
=
3076 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3077 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3078 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3079 session
, test_url_
, MEDIUM
, BoundNetLog());
3080 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
3081 TestCompletionCallback callback1
;
3082 EXPECT_NE(spdy_stream1
->send_window_size(), window_size
);
3084 data
->RunFor(1); // Process the SETTINGS frame, but not the EOF
3085 base::MessageLoop::current()->RunUntilIdle();
3086 EXPECT_EQ(session
->stream_initial_send_window_size(), window_size
);
3087 EXPECT_EQ(spdy_stream1
->send_window_size(), window_size
);
3089 // Release the first one, this will allow the second to be created.
3090 spdy_stream1
->Cancel();
3091 EXPECT_EQ(NULL
, spdy_stream1
.get());
3093 base::WeakPtr
<SpdyStream
> spdy_stream2
=
3094 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3095 session
, test_url_
, MEDIUM
, BoundNetLog());
3096 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
3097 EXPECT_EQ(spdy_stream2
->send_window_size(), window_size
);
3098 spdy_stream2
->Cancel();
3099 EXPECT_EQ(NULL
, spdy_stream2
.get());
3102 // The tests below are only for SPDY/3.1 and above.
3104 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3105 // adjust the session receive window size for SPDY 3.1 and higher. In
3106 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3107 // sending a WINDOW_UPDATE frame for a large enough delta.
3108 TEST_P(SpdySessionTest
, AdjustRecvWindowSize
) {
3109 if (GetParam() < kProtoSPDY31
)
3112 session_deps_
.host_resolver
->set_synchronous_mode(true);
3114 const int32 delta_window_size
= 100;
3116 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3117 MockRead reads
[] = {
3118 MockRead(ASYNC
, 0, 1) // EOF
3120 scoped_ptr
<SpdyFrame
> window_update(
3121 spdy_util_
.ConstructSpdyWindowUpdate(
3122 kSessionFlowControlStreamId
,
3123 kSpdySessionInitialWindowSize
+ delta_window_size
));
3124 MockWrite writes
[] = {
3125 CreateMockWrite(*window_update
, 0),
3127 DeterministicSocketData
data(reads
, arraysize(reads
),
3128 writes
, arraysize(writes
));
3129 data
.set_connect_data(connect_data
);
3130 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3132 CreateDeterministicNetworkSession();
3133 base::WeakPtr
<SpdySession
> session
=
3134 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3135 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3136 session
->flow_control_state());
3138 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3139 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3141 session
->IncreaseRecvWindowSize(delta_window_size
);
3142 EXPECT_EQ(kSpdySessionInitialWindowSize
+ delta_window_size
,
3143 session
->session_recv_window_size_
);
3144 EXPECT_EQ(delta_window_size
, session
->session_unacked_recv_window_bytes_
);
3146 // Should trigger sending a WINDOW_UPDATE frame.
3147 session
->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize
);
3148 EXPECT_EQ(kSpdySessionInitialWindowSize
+ delta_window_size
+
3149 kSpdySessionInitialWindowSize
,
3150 session
->session_recv_window_size_
);
3151 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3155 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3156 session
->in_io_loop_
= true;
3157 session
->DecreaseRecvWindowSize(
3158 kSpdySessionInitialWindowSize
+ delta_window_size
+
3159 kSpdySessionInitialWindowSize
);
3160 session
->in_io_loop_
= false;
3161 EXPECT_EQ(0, session
->session_recv_window_size_
);
3162 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3165 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3166 // adjust the session send window size when the "enable_spdy_31" flag
3168 TEST_P(SpdySessionTest
, AdjustSendWindowSize
) {
3169 if (GetParam() < kProtoSPDY31
)
3172 session_deps_
.host_resolver
->set_synchronous_mode(true);
3174 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3175 MockRead reads
[] = {
3176 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3178 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3179 data
.set_connect_data(connect_data
);
3180 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3182 CreateNetworkSession();
3183 base::WeakPtr
<SpdySession
> session
=
3184 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3185 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3186 session
->flow_control_state());
3188 const int32 delta_window_size
= 100;
3190 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3192 session
->IncreaseSendWindowSize(delta_window_size
);
3193 EXPECT_EQ(kSpdySessionInitialWindowSize
+ delta_window_size
,
3194 session
->session_send_window_size_
);
3196 session
->DecreaseSendWindowSize(delta_window_size
);
3197 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3200 // Incoming data for an inactive stream should not cause the session
3201 // receive window size to decrease, but it should cause the unacked
3202 // bytes to increase.
3203 TEST_P(SpdySessionTest
, SessionFlowControlInactiveStream
) {
3204 if (GetParam() < kProtoSPDY31
)
3207 session_deps_
.host_resolver
->set_synchronous_mode(true);
3209 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3210 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(1, false));
3211 MockRead reads
[] = {
3212 CreateMockRead(*resp
, 0),
3213 MockRead(ASYNC
, 0, 1) // EOF
3215 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
3216 data
.set_connect_data(connect_data
);
3217 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3219 CreateDeterministicNetworkSession();
3220 base::WeakPtr
<SpdySession
> session
=
3221 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3222 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3223 session
->flow_control_state());
3225 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3226 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3230 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3231 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
3236 // A delegate that drops any received data.
3237 class DropReceivedDataDelegate
: public test::StreamDelegateSendImmediate
{
3239 DropReceivedDataDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3240 base::StringPiece data
)
3241 : StreamDelegateSendImmediate(stream
, data
) {}
3243 virtual ~DropReceivedDataDelegate() {}
3245 // Drop any received data.
3246 virtual void OnDataReceived(scoped_ptr
<SpdyBuffer
> buffer
) OVERRIDE
{}
3249 // Send data back and forth but use a delegate that drops its received
3250 // data. The receive window should still increase to its original
3251 // value, i.e. we shouldn't "leak" receive window bytes.
3252 TEST_P(SpdySessionTest
, SessionFlowControlNoReceiveLeaks
) {
3253 if (GetParam() < kProtoSPDY31
)
3256 const char kStreamUrl
[] = "http://www.google.com/";
3258 const int32 msg_data_size
= 100;
3259 const std::string
msg_data(msg_data_size
, 'a');
3261 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3263 scoped_ptr
<SpdyFrame
> req(
3264 spdy_util_
.ConstructSpdyPost(
3265 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3266 scoped_ptr
<SpdyFrame
> msg(
3267 spdy_util_
.ConstructSpdyBodyFrame(
3268 1, msg_data
.data(), msg_data_size
, false));
3269 MockWrite writes
[] = {
3270 CreateMockWrite(*req
, 0),
3271 CreateMockWrite(*msg
, 2),
3274 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3275 scoped_ptr
<SpdyFrame
> echo(
3276 spdy_util_
.ConstructSpdyBodyFrame(
3277 1, msg_data
.data(), msg_data_size
, false));
3278 scoped_ptr
<SpdyFrame
> window_update(
3279 spdy_util_
.ConstructSpdyWindowUpdate(
3280 kSessionFlowControlStreamId
, msg_data_size
));
3281 MockRead reads
[] = {
3282 CreateMockRead(*resp
, 1),
3283 CreateMockRead(*echo
, 3),
3284 MockRead(ASYNC
, 0, 4) // EOF
3287 // Create SpdySession and SpdyStream and send the request.
3288 DeterministicSocketData
data(reads
, arraysize(reads
),
3289 writes
, arraysize(writes
));
3290 data
.set_connect_data(connect_data
);
3291 session_deps_
.host_resolver
->set_synchronous_mode(true);
3292 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3294 CreateDeterministicNetworkSession();
3296 base::WeakPtr
<SpdySession
> session
=
3297 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3299 GURL
url(kStreamUrl
);
3300 base::WeakPtr
<SpdyStream
> stream
=
3301 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3302 session
, url
, MEDIUM
, BoundNetLog());
3303 ASSERT_TRUE(stream
.get() != NULL
);
3304 EXPECT_EQ(0u, stream
->stream_id());
3306 DropReceivedDataDelegate
delegate(stream
, msg_data
);
3307 stream
->SetDelegate(&delegate
);
3309 scoped_ptr
<SpdyHeaderBlock
> headers(
3310 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3311 EXPECT_EQ(ERR_IO_PENDING
,
3312 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3313 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3315 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3316 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3320 EXPECT_TRUE(data
.at_write_eof());
3321 EXPECT_TRUE(data
.at_read_eof());
3323 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3324 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3327 EXPECT_EQ(NULL
, stream
.get());
3329 EXPECT_EQ(OK
, delegate
.WaitForClose());
3331 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3332 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3335 // Send data back and forth but close the stream before its data frame
3336 // can be written to the socket. The send window should then increase
3337 // to its original value, i.e. we shouldn't "leak" send window bytes.
3338 TEST_P(SpdySessionTest
, SessionFlowControlNoSendLeaks
) {
3339 if (GetParam() < kProtoSPDY31
)
3342 const char kStreamUrl
[] = "http://www.google.com/";
3344 const int32 msg_data_size
= 100;
3345 const std::string
msg_data(msg_data_size
, 'a');
3347 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3349 scoped_ptr
<SpdyFrame
> req(
3350 spdy_util_
.ConstructSpdyPost(
3351 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3352 MockWrite writes
[] = {
3353 CreateMockWrite(*req
, 0),
3356 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3357 MockRead reads
[] = {
3358 CreateMockRead(*resp
, 1),
3359 MockRead(ASYNC
, 0, 2) // EOF
3362 // Create SpdySession and SpdyStream and send the request.
3363 DeterministicSocketData
data(reads
, arraysize(reads
),
3364 writes
, arraysize(writes
));
3365 data
.set_connect_data(connect_data
);
3366 session_deps_
.host_resolver
->set_synchronous_mode(true);
3367 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3369 CreateDeterministicNetworkSession();
3371 base::WeakPtr
<SpdySession
> session
=
3372 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3374 GURL
url(kStreamUrl
);
3375 base::WeakPtr
<SpdyStream
> stream
=
3376 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3377 session
, url
, MEDIUM
, BoundNetLog());
3378 ASSERT_TRUE(stream
.get() != NULL
);
3379 EXPECT_EQ(0u, stream
->stream_id());
3381 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3382 stream
->SetDelegate(&delegate
);
3384 scoped_ptr
<SpdyHeaderBlock
> headers(
3385 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3386 EXPECT_EQ(ERR_IO_PENDING
,
3387 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3388 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3390 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3394 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3398 EXPECT_TRUE(data
.at_write_eof());
3399 EXPECT_TRUE(data
.at_read_eof());
3401 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3402 session
->session_send_window_size_
);
3404 // Closing the stream should increase the session's send window.
3406 EXPECT_EQ(NULL
, stream
.get());
3408 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3410 EXPECT_EQ(OK
, delegate
.WaitForClose());
3413 // Send data back and forth; the send and receive windows should
3414 // change appropriately.
3415 TEST_P(SpdySessionTest
, SessionFlowControlEndToEnd
) {
3416 if (GetParam() < kProtoSPDY31
)
3419 const char kStreamUrl
[] = "http://www.google.com/";
3421 const int32 msg_data_size
= 100;
3422 const std::string
msg_data(msg_data_size
, 'a');
3424 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3426 scoped_ptr
<SpdyFrame
> req(
3427 spdy_util_
.ConstructSpdyPost(
3428 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3429 scoped_ptr
<SpdyFrame
> msg(
3430 spdy_util_
.ConstructSpdyBodyFrame(
3431 1, msg_data
.data(), msg_data_size
, false));
3432 MockWrite writes
[] = {
3433 CreateMockWrite(*req
, 0),
3434 CreateMockWrite(*msg
, 2),
3437 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3438 scoped_ptr
<SpdyFrame
> echo(
3439 spdy_util_
.ConstructSpdyBodyFrame(
3440 1, msg_data
.data(), msg_data_size
, false));
3441 scoped_ptr
<SpdyFrame
> window_update(
3442 spdy_util_
.ConstructSpdyWindowUpdate(
3443 kSessionFlowControlStreamId
, msg_data_size
));
3444 MockRead reads
[] = {
3445 CreateMockRead(*resp
, 1),
3446 CreateMockRead(*echo
, 3),
3447 CreateMockRead(*window_update
, 4),
3448 MockRead(ASYNC
, 0, 5) // EOF
3451 // Create SpdySession and SpdyStream and send the request.
3452 DeterministicSocketData
data(reads
, arraysize(reads
),
3453 writes
, arraysize(writes
));
3454 data
.set_connect_data(connect_data
);
3455 session_deps_
.host_resolver
->set_synchronous_mode(true);
3456 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3458 CreateDeterministicNetworkSession();
3460 base::WeakPtr
<SpdySession
> session
=
3461 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3463 GURL
url(kStreamUrl
);
3464 base::WeakPtr
<SpdyStream
> stream
=
3465 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3466 session
, url
, MEDIUM
, BoundNetLog());
3467 ASSERT_TRUE(stream
.get() != NULL
);
3468 EXPECT_EQ(0u, stream
->stream_id());
3470 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3471 stream
->SetDelegate(&delegate
);
3473 scoped_ptr
<SpdyHeaderBlock
> headers(
3474 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3475 EXPECT_EQ(ERR_IO_PENDING
,
3476 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3477 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3479 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3480 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3481 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3485 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3486 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3487 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3491 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3492 session
->session_send_window_size_
);
3493 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3494 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3498 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3499 session
->session_send_window_size_
);
3500 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3501 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3505 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3506 session
->session_send_window_size_
);
3507 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3508 session
->session_recv_window_size_
);
3509 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3513 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3514 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3515 session
->session_recv_window_size_
);
3516 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3518 EXPECT_TRUE(data
.at_write_eof());
3519 EXPECT_TRUE(data
.at_read_eof());
3521 EXPECT_EQ(msg_data
, delegate
.TakeReceivedData());
3523 // Draining the delegate's read queue should increase the session's
3525 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3526 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3527 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3530 EXPECT_EQ(NULL
, stream
.get());
3532 EXPECT_EQ(OK
, delegate
.WaitForClose());
3534 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3535 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3536 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3539 // Given a stall function and an unstall function, runs a test to make
3540 // sure that a stream resumes after unstall.
3541 void SpdySessionTest::RunResumeAfterUnstallTest(
3542 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
3543 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
3545 const char kStreamUrl
[] = "http://www.google.com/";
3546 GURL
url(kStreamUrl
);
3548 session_deps_
.host_resolver
->set_synchronous_mode(true);
3550 scoped_ptr
<SpdyFrame
> req(
3551 spdy_util_
.ConstructSpdyPost(
3552 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
3553 scoped_ptr
<SpdyFrame
> body(
3554 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
3555 MockWrite writes
[] = {
3556 CreateMockWrite(*req
, 0),
3557 CreateMockWrite(*body
, 1),
3560 scoped_ptr
<SpdyFrame
> resp(
3561 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3562 scoped_ptr
<SpdyFrame
> echo(
3563 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
3564 MockRead reads
[] = {
3565 CreateMockRead(*resp
, 2),
3566 MockRead(ASYNC
, 0, 0, 3), // EOF
3569 DeterministicSocketData
data(reads
, arraysize(reads
),
3570 writes
, arraysize(writes
));
3571 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3572 data
.set_connect_data(connect_data
);
3574 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3576 CreateDeterministicNetworkSession();
3577 base::WeakPtr
<SpdySession
> session
=
3578 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3579 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3580 session
->flow_control_state());
3582 base::WeakPtr
<SpdyStream
> stream
=
3583 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3584 session
, url
, LOWEST
, BoundNetLog());
3585 ASSERT_TRUE(stream
.get() != NULL
);
3587 test::StreamDelegateWithBody
delegate(stream
, kBodyDataStringPiece
);
3588 stream
->SetDelegate(&delegate
);
3590 EXPECT_FALSE(stream
->HasUrlFromHeaders());
3591 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
3593 scoped_ptr
<SpdyHeaderBlock
> headers(
3594 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
3595 EXPECT_EQ(ERR_IO_PENDING
,
3596 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3597 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3598 EXPECT_EQ(kStreamUrl
, stream
->GetUrlFromHeaders().spec());
3600 stall_function
.Run(session
.get(), stream
.get());
3604 EXPECT_TRUE(stream
->send_stalled_by_flow_control());
3606 unstall_function
.Run(session
.get(), stream
.get(), kBodyDataSize
);
3608 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
3612 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
3614 EXPECT_TRUE(delegate
.send_headers_completed());
3615 EXPECT_EQ("200", delegate
.GetResponseHeaderValue(":status"));
3616 EXPECT_EQ("HTTP/1.1", delegate
.GetResponseHeaderValue(":version"));
3617 EXPECT_EQ(std::string(), delegate
.TakeReceivedData());
3618 EXPECT_TRUE(data
.at_write_eof());
3621 // Run the resume-after-unstall test with all possible stall and
3622 // unstall sequences.
3624 TEST_P(SpdySessionTest
, ResumeAfterUnstallSession
) {
3625 if (GetParam() < kProtoSPDY31
)
3628 RunResumeAfterUnstallTest(
3629 base::Bind(&SpdySessionTest::StallSessionOnly
,
3630 base::Unretained(this)),
3631 base::Bind(&SpdySessionTest::UnstallSessionOnly
,
3632 base::Unretained(this)));
3636 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
3637 TEST_P(SpdySessionTest
, ResumeAfterUnstallStream
) {
3638 if (GetParam() < kProtoSPDY31
)
3641 RunResumeAfterUnstallTest(
3642 base::Bind(&SpdySessionTest::StallStreamOnly
,
3643 base::Unretained(this)),
3644 base::Bind(&SpdySessionTest::UnstallStreamOnly
,
3645 base::Unretained(this)));
3648 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallSessionStream
) {
3649 if (GetParam() < kProtoSPDY31
)
3652 RunResumeAfterUnstallTest(
3653 base::Bind(&SpdySessionTest::StallSessionStream
,
3654 base::Unretained(this)),
3655 base::Bind(&SpdySessionTest::UnstallSessionStream
,
3656 base::Unretained(this)));
3659 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallSessionStream
) {
3660 if (GetParam() < kProtoSPDY31
)
3663 RunResumeAfterUnstallTest(
3664 base::Bind(&SpdySessionTest::StallStreamSession
,
3665 base::Unretained(this)),
3666 base::Bind(&SpdySessionTest::UnstallSessionStream
,
3667 base::Unretained(this)));
3670 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallStreamSession
) {
3671 if (GetParam() < kProtoSPDY31
)
3674 RunResumeAfterUnstallTest(
3675 base::Bind(&SpdySessionTest::StallStreamSession
,
3676 base::Unretained(this)),
3677 base::Bind(&SpdySessionTest::UnstallStreamSession
,
3678 base::Unretained(this)));
3681 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallStreamSession
) {
3682 if (GetParam() < kProtoSPDY31
)
3685 RunResumeAfterUnstallTest(
3686 base::Bind(&SpdySessionTest::StallSessionStream
,
3687 base::Unretained(this)),
3688 base::Bind(&SpdySessionTest::UnstallStreamSession
,
3689 base::Unretained(this)));
3692 // Cause a stall by reducing the flow control send window to 0. The
3693 // streams should resume in priority order when that window is then
3695 TEST_P(SpdySessionTest
, ResumeByPriorityAfterSendWindowSizeIncrease
) {
3696 if (GetParam() < kProtoSPDY31
)
3699 const char kStreamUrl
[] = "http://www.google.com/";
3700 GURL
url(kStreamUrl
);
3702 session_deps_
.host_resolver
->set_synchronous_mode(true);
3704 scoped_ptr
<SpdyFrame
> req1(
3705 spdy_util_
.ConstructSpdyPost(
3706 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
3707 scoped_ptr
<SpdyFrame
> req2(
3708 spdy_util_
.ConstructSpdyPost(
3709 kStreamUrl
, 3, kBodyDataSize
, MEDIUM
, NULL
, 0));
3710 scoped_ptr
<SpdyFrame
> body1(
3711 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
3712 scoped_ptr
<SpdyFrame
> body2(
3713 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
3714 MockWrite writes
[] = {
3715 CreateMockWrite(*req1
, 0),
3716 CreateMockWrite(*req2
, 1),
3717 CreateMockWrite(*body2
, 2),
3718 CreateMockWrite(*body1
, 3),
3721 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3722 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3723 MockRead reads
[] = {
3724 CreateMockRead(*resp1
, 4),
3725 CreateMockRead(*resp2
, 5),
3726 MockRead(ASYNC
, 0, 0, 6), // EOF
3729 DeterministicSocketData
data(reads
, arraysize(reads
),
3730 writes
, arraysize(writes
));
3731 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3732 data
.set_connect_data(connect_data
);
3734 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3736 CreateDeterministicNetworkSession();
3737 base::WeakPtr
<SpdySession
> session
=
3738 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3739 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3740 session
->flow_control_state());
3742 base::WeakPtr
<SpdyStream
> stream1
=
3743 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3744 session
, url
, LOWEST
, BoundNetLog());
3745 ASSERT_TRUE(stream1
.get() != NULL
);
3747 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
3748 stream1
->SetDelegate(&delegate1
);
3750 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
3752 base::WeakPtr
<SpdyStream
> stream2
=
3753 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3754 session
, url
, MEDIUM
, BoundNetLog());
3755 ASSERT_TRUE(stream2
.get() != NULL
);
3757 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
3758 stream2
->SetDelegate(&delegate2
);
3760 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
3762 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
3763 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
3765 StallSessionSend(session
.get());
3767 scoped_ptr
<SpdyHeaderBlock
> headers1(
3768 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
3769 EXPECT_EQ(ERR_IO_PENDING
,
3770 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
3771 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
3772 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
3775 EXPECT_EQ(1u, stream1
->stream_id());
3776 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
3778 scoped_ptr
<SpdyHeaderBlock
> headers2(
3779 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
3780 EXPECT_EQ(ERR_IO_PENDING
,
3781 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
3782 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
3783 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
3786 EXPECT_EQ(3u, stream2
->stream_id());
3787 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
3789 // This should unstall only stream2.
3790 UnstallSessionSend(session
.get(), kBodyDataSize
);
3792 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
3793 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
3797 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
3798 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
3800 // This should then unstall stream1.
3801 UnstallSessionSend(session
.get(), kBodyDataSize
);
3803 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
3804 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
3808 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
3809 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
3811 EXPECT_TRUE(delegate1
.send_headers_completed());
3812 EXPECT_EQ("200", delegate1
.GetResponseHeaderValue(":status"));
3813 EXPECT_EQ("HTTP/1.1", delegate1
.GetResponseHeaderValue(":version"));
3814 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
3816 EXPECT_TRUE(delegate2
.send_headers_completed());
3817 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
3818 EXPECT_EQ("HTTP/1.1", delegate2
.GetResponseHeaderValue(":version"));
3819 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
3821 EXPECT_TRUE(data
.at_write_eof());
3824 // Delegate that closes a given stream after sending its body.
3825 class StreamClosingDelegate
: public test::StreamDelegateWithBody
{
3827 StreamClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3828 base::StringPiece data
)
3829 : StreamDelegateWithBody(stream
, data
) {}
3831 virtual ~StreamClosingDelegate() {}
3833 void set_stream_to_close(const base::WeakPtr
<SpdyStream
>& stream_to_close
) {
3834 stream_to_close_
= stream_to_close
;
3837 virtual void OnDataSent() OVERRIDE
{
3838 test::StreamDelegateWithBody::OnDataSent();
3839 if (stream_to_close_
.get()) {
3840 stream_to_close_
->Close();
3841 EXPECT_EQ(NULL
, stream_to_close_
.get());
3846 base::WeakPtr
<SpdyStream
> stream_to_close_
;
3849 // Cause a stall by reducing the flow control send window to
3850 // 0. Unstalling the session should properly handle deleted streams.
3851 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedStreams
) {
3852 if (GetParam() < kProtoSPDY31
)
3855 const char kStreamUrl
[] = "http://www.google.com/";
3856 GURL
url(kStreamUrl
);
3858 session_deps_
.host_resolver
->set_synchronous_mode(true);
3860 scoped_ptr
<SpdyFrame
> req1(
3861 spdy_util_
.ConstructSpdyPost(
3862 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
3863 scoped_ptr
<SpdyFrame
> req2(
3864 spdy_util_
.ConstructSpdyPost(
3865 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, NULL
, 0));
3866 scoped_ptr
<SpdyFrame
> req3(
3867 spdy_util_
.ConstructSpdyPost(
3868 kStreamUrl
, 5, kBodyDataSize
, LOWEST
, NULL
, 0));
3869 scoped_ptr
<SpdyFrame
> body2(
3870 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
3871 MockWrite writes
[] = {
3872 CreateMockWrite(*req1
, 0),
3873 CreateMockWrite(*req2
, 1),
3874 CreateMockWrite(*req3
, 2),
3875 CreateMockWrite(*body2
, 3),
3878 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3879 MockRead reads
[] = {
3880 CreateMockRead(*resp2
, 4),
3881 MockRead(ASYNC
, 0, 0, 5), // EOF
3884 DeterministicSocketData
data(reads
, arraysize(reads
),
3885 writes
, arraysize(writes
));
3886 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3887 data
.set_connect_data(connect_data
);
3889 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3891 CreateDeterministicNetworkSession();
3892 base::WeakPtr
<SpdySession
> session
=
3893 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3894 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3895 session
->flow_control_state());
3897 base::WeakPtr
<SpdyStream
> stream1
=
3898 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3899 session
, url
, LOWEST
, BoundNetLog());
3900 ASSERT_TRUE(stream1
.get() != NULL
);
3902 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
3903 stream1
->SetDelegate(&delegate1
);
3905 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
3907 base::WeakPtr
<SpdyStream
> stream2
=
3908 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3909 session
, url
, LOWEST
, BoundNetLog());
3910 ASSERT_TRUE(stream2
.get() != NULL
);
3912 StreamClosingDelegate
delegate2(stream2
, kBodyDataStringPiece
);
3913 stream2
->SetDelegate(&delegate2
);
3915 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
3917 base::WeakPtr
<SpdyStream
> stream3
=
3918 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3919 session
, url
, LOWEST
, BoundNetLog());
3920 ASSERT_TRUE(stream3
.get() != NULL
);
3922 test::StreamDelegateWithBody
delegate3(stream3
, kBodyDataStringPiece
);
3923 stream3
->SetDelegate(&delegate3
);
3925 EXPECT_FALSE(stream3
->HasUrlFromHeaders());
3927 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
3928 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
3929 EXPECT_FALSE(stream3
->send_stalled_by_flow_control());
3931 StallSessionSend(session
.get());
3933 scoped_ptr
<SpdyHeaderBlock
> headers1(
3934 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
3935 EXPECT_EQ(ERR_IO_PENDING
,
3936 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
3937 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
3938 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
3941 EXPECT_EQ(1u, stream1
->stream_id());
3942 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
3944 scoped_ptr
<SpdyHeaderBlock
> headers2(
3945 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
3946 EXPECT_EQ(ERR_IO_PENDING
,
3947 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
3948 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
3949 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
3952 EXPECT_EQ(3u, stream2
->stream_id());
3953 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
3955 scoped_ptr
<SpdyHeaderBlock
> headers3(
3956 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
3957 EXPECT_EQ(ERR_IO_PENDING
,
3958 stream3
->SendRequestHeaders(headers3
.Pass(), MORE_DATA_TO_SEND
));
3959 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
3960 EXPECT_EQ(kStreamUrl
, stream3
->GetUrlFromHeaders().spec());
3963 EXPECT_EQ(5u, stream3
->stream_id());
3964 EXPECT_TRUE(stream3
->send_stalled_by_flow_control());
3966 SpdyStreamId stream_id1
= stream1
->stream_id();
3967 SpdyStreamId stream_id2
= stream2
->stream_id();
3968 SpdyStreamId stream_id3
= stream3
->stream_id();
3970 // Close stream1 preemptively.
3971 session
->CloseActiveStream(stream_id1
, ERR_CONNECTION_CLOSED
);
3972 EXPECT_EQ(NULL
, stream1
.get());
3974 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
3975 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
3976 EXPECT_TRUE(session
->IsStreamActive(stream_id3
));
3978 // Unstall stream2, which should then close stream3.
3979 delegate2
.set_stream_to_close(stream3
);
3980 UnstallSessionSend(session
.get(), kBodyDataSize
);
3983 EXPECT_EQ(NULL
, stream3
.get());
3985 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
3986 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
3987 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
3988 EXPECT_FALSE(session
->IsStreamActive(stream_id3
));
3991 EXPECT_EQ(NULL
, stream2
.get());
3993 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
3994 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
3995 EXPECT_EQ(OK
, delegate3
.WaitForClose());
3997 EXPECT_TRUE(delegate1
.send_headers_completed());
3998 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4000 EXPECT_TRUE(delegate2
.send_headers_completed());
4001 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4002 EXPECT_EQ("HTTP/1.1", delegate2
.GetResponseHeaderValue(":version"));
4003 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4005 EXPECT_TRUE(delegate3
.send_headers_completed());
4006 EXPECT_EQ(std::string(), delegate3
.TakeReceivedData());
4008 EXPECT_TRUE(data
.at_write_eof());
4011 // Cause a stall by reducing the flow control send window to
4012 // 0. Unstalling the session should properly handle the session itself
4014 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedSession
) {
4015 if (GetParam() < kProtoSPDY31
)
4018 const char kStreamUrl
[] = "http://www.google.com/";
4019 GURL
url(kStreamUrl
);
4021 session_deps_
.host_resolver
->set_synchronous_mode(true);
4023 scoped_ptr
<SpdyFrame
> req1(
4024 spdy_util_
.ConstructSpdyPost(
4025 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4026 scoped_ptr
<SpdyFrame
> req2(
4027 spdy_util_
.ConstructSpdyPost(
4028 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, NULL
, 0));
4029 scoped_ptr
<SpdyFrame
> body1(
4030 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4031 MockWrite writes
[] = {
4032 CreateMockWrite(*req1
, 0),
4033 CreateMockWrite(*req2
, 1),
4036 MockRead reads
[] = {
4037 MockRead(ASYNC
, 0, 0, 2), // EOF
4040 DeterministicSocketData
data(reads
, arraysize(reads
),
4041 writes
, arraysize(writes
));
4042 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4043 data
.set_connect_data(connect_data
);
4045 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4047 CreateDeterministicNetworkSession();
4048 base::WeakPtr
<SpdySession
> session
=
4049 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4050 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4051 session
->flow_control_state());
4053 base::WeakPtr
<SpdyStream
> stream1
=
4054 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4055 session
, url
, LOWEST
, BoundNetLog());
4056 ASSERT_TRUE(stream1
.get() != NULL
);
4058 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4059 stream1
->SetDelegate(&delegate1
);
4061 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4063 base::WeakPtr
<SpdyStream
> stream2
=
4064 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4065 session
, url
, LOWEST
, BoundNetLog());
4066 ASSERT_TRUE(stream2
.get() != NULL
);
4068 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4069 stream2
->SetDelegate(&delegate2
);
4071 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4073 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4074 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4076 StallSessionSend(session
.get());
4078 scoped_ptr
<SpdyHeaderBlock
> headers1(
4079 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4080 EXPECT_EQ(ERR_IO_PENDING
,
4081 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4082 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4083 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4086 EXPECT_EQ(1u, stream1
->stream_id());
4087 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4089 scoped_ptr
<SpdyHeaderBlock
> headers2(
4090 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4091 EXPECT_EQ(ERR_IO_PENDING
,
4092 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4093 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4094 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4097 EXPECT_EQ(3u, stream2
->stream_id());
4098 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4100 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
4103 UnstallSessionSend(session
.get(), kBodyDataSize
);
4105 // Close the session (since we can't do it from within the delegate
4106 // method, since it's in the stream's loop).
4107 session
->CloseSessionOnError(ERR_CONNECTION_CLOSED
, "Closing session");
4108 EXPECT_TRUE(session
== NULL
);
4110 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
4112 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4113 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4115 EXPECT_TRUE(delegate1
.send_headers_completed());
4116 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4118 EXPECT_TRUE(delegate2
.send_headers_completed());
4119 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4121 EXPECT_TRUE(data
.at_write_eof());
4124 TEST(MapFramerErrorToProtocolError
, MapsValues
) {
4125 CHECK_EQ(SPDY_ERROR_INVALID_CONTROL_FRAME
,
4126 MapFramerErrorToProtocolError(
4127 SpdyFramer::SPDY_INVALID_CONTROL_FRAME
));
4128 CHECK_EQ(SPDY_ERROR_INVALID_DATA_FRAME_FLAGS
,
4129 MapFramerErrorToProtocolError(
4130 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS
));
4131 CHECK_EQ(SPDY_ERROR_GOAWAY_FRAME_CORRUPT
,
4132 MapFramerErrorToProtocolError(
4133 SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT
));
4134 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME
,
4135 MapFramerErrorToProtocolError(
4136 SpdyFramer::SPDY_UNEXPECTED_FRAME
));
4139 TEST(MapRstStreamStatusToProtocolError
, MapsValues
) {
4140 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR
,
4141 MapRstStreamStatusToProtocolError(
4142 RST_STREAM_PROTOCOL_ERROR
));
4143 CHECK_EQ(STATUS_CODE_FRAME_TOO_LARGE
,
4144 MapRstStreamStatusToProtocolError(
4145 RST_STREAM_FRAME_TOO_LARGE
));