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 TryCreateFakeSpdySessionExpectingFailure(
194 spdy_session_pool_
, key_
, ERR_FAILED
);
199 // A helper class that vends a callback that, when fired, destroys a
200 // given SpdyStreamRequest.
201 class StreamRequestDestroyingCallback
: public TestCompletionCallbackBase
{
203 StreamRequestDestroyingCallback() {}
205 virtual ~StreamRequestDestroyingCallback() {}
207 void SetRequestToDestroy(scoped_ptr
<SpdyStreamRequest
> request
) {
208 request_
= request
.Pass();
211 CompletionCallback
MakeCallback() {
212 return base::Bind(&StreamRequestDestroyingCallback::OnComplete
,
213 base::Unretained(this));
217 void OnComplete(int result
) {
222 scoped_ptr
<SpdyStreamRequest
> request_
;
227 // Request kInitialMaxConcurrentStreams streams. Request two more
228 // streams, but have the callback for one destroy the second stream
229 // request. Close the session. Nothing should blow up. This is a
230 // regression test for http://crbug.com/250841 .
231 TEST_P(SpdySessionTest
, PendingStreamCancellingAnother
) {
232 session_deps_
.host_resolver
->set_synchronous_mode(true);
234 MockRead reads
[] = {MockRead(ASYNC
, 0, 0), };
236 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
237 MockConnect
connect_data(SYNCHRONOUS
, OK
);
238 data
.set_connect_data(connect_data
);
239 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
241 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
242 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
244 CreateDeterministicNetworkSession();
246 base::WeakPtr
<SpdySession
> session
=
247 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
249 // Create the maximum number of concurrent streams.
250 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
251 base::WeakPtr
<SpdyStream
> spdy_stream
= CreateStreamSynchronously(
252 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
, BoundNetLog());
253 ASSERT_TRUE(spdy_stream
!= NULL
);
256 SpdyStreamRequest request1
;
257 scoped_ptr
<SpdyStreamRequest
> request2(new SpdyStreamRequest
);
259 StreamRequestDestroyingCallback callback1
;
260 ASSERT_EQ(ERR_IO_PENDING
,
261 request1
.StartRequest(SPDY_BIDIRECTIONAL_STREAM
,
266 callback1
.MakeCallback()));
268 // |callback2| is never called.
269 TestCompletionCallback callback2
;
270 ASSERT_EQ(ERR_IO_PENDING
,
271 request2
->StartRequest(SPDY_BIDIRECTIONAL_STREAM
,
276 callback2
.callback()));
278 callback1
.SetRequestToDestroy(request2
.Pass());
280 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
282 EXPECT_EQ(ERR_ABORTED
, callback1
.WaitForResult());
287 // A session receiving a GOAWAY frame with no active streams should
288 // immediately close.
289 TEST_P(SpdySessionTest
, GoAwayWithNoActiveStreams
) {
290 session_deps_
.host_resolver
->set_synchronous_mode(true);
292 MockConnect
connect_data(SYNCHRONOUS
, OK
);
293 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
295 CreateMockRead(*goaway
, 0),
297 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
298 data
.set_connect_data(connect_data
);
299 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
301 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
302 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
304 CreateDeterministicNetworkSession();
306 base::WeakPtr
<SpdySession
> session
=
307 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
309 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
311 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
313 // Read and process the GOAWAY frame.
316 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
318 EXPECT_TRUE(session
== NULL
);
321 // A session receiving a GOAWAY frame immediately with no active
322 // streams should then close.
323 TEST_P(SpdySessionTest
, GoAwayImmediatelyWithNoActiveStreams
) {
324 session_deps_
.host_resolver
->set_synchronous_mode(true);
326 MockConnect
connect_data(SYNCHRONOUS
, OK
);
327 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
329 CreateMockRead(*goaway
, 0, SYNCHRONOUS
),
331 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
332 data
.set_connect_data(connect_data
);
333 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
335 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
336 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
338 CreateDeterministicNetworkSession();
342 TryCreateInsecureSpdySessionExpectingFailure(
343 http_session_
, key_
, ERR_CONNECTION_CLOSED
, BoundNetLog());
345 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
348 // A session receiving a GOAWAY frame with active streams should close
349 // when the last active stream is closed.
350 TEST_P(SpdySessionTest
, GoAwayWithActiveStreams
) {
351 session_deps_
.host_resolver
->set_synchronous_mode(true);
353 MockConnect
connect_data(SYNCHRONOUS
, OK
);
354 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
356 CreateMockRead(*goaway
, 2),
357 MockRead(ASYNC
, 0, 3) // EOF
359 scoped_ptr
<SpdyFrame
> req1(
360 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
361 scoped_ptr
<SpdyFrame
> req2(
362 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
363 MockWrite writes
[] = {
364 CreateMockWrite(*req1
, 0),
365 CreateMockWrite(*req2
, 1),
367 DeterministicSocketData
data(reads
, arraysize(reads
),
368 writes
, arraysize(writes
));
369 data
.set_connect_data(connect_data
);
370 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
372 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
373 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
375 CreateDeterministicNetworkSession();
377 base::WeakPtr
<SpdySession
> session
=
378 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
380 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
382 GURL
url("http://www.google.com");
383 base::WeakPtr
<SpdyStream
> spdy_stream1
=
384 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
385 session
, url
, MEDIUM
, BoundNetLog());
386 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
387 spdy_stream1
->SetDelegate(&delegate1
);
389 base::WeakPtr
<SpdyStream
> spdy_stream2
=
390 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
391 session
, url
, MEDIUM
, BoundNetLog());
392 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
393 spdy_stream2
->SetDelegate(&delegate2
);
395 scoped_ptr
<SpdyHeaderBlock
> headers(
396 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
397 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
399 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
400 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
401 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
402 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
406 EXPECT_EQ(1u, spdy_stream1
->stream_id());
407 EXPECT_EQ(3u, spdy_stream2
->stream_id());
409 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
411 // Read and process the GOAWAY frame.
414 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
416 EXPECT_FALSE(session
->IsStreamActive(3));
417 EXPECT_EQ(NULL
, spdy_stream2
.get());
418 EXPECT_TRUE(session
->IsStreamActive(1));
420 EXPECT_FALSE(session
->IsClosed());
422 // Should close the session.
423 spdy_stream1
->Close();
424 EXPECT_EQ(NULL
, spdy_stream1
.get());
426 EXPECT_TRUE(session
== NULL
);
429 // Have a session receive two GOAWAY frames, with the last one causing
430 // the last active stream to be closed. The session should then be
431 // closed after the second GOAWAY frame.
432 TEST_P(SpdySessionTest
, GoAwayTwice
) {
433 session_deps_
.host_resolver
->set_synchronous_mode(true);
435 MockConnect
connect_data(SYNCHRONOUS
, OK
);
436 scoped_ptr
<SpdyFrame
> goaway1(spdy_util_
.ConstructSpdyGoAway(1));
437 scoped_ptr
<SpdyFrame
> goaway2(spdy_util_
.ConstructSpdyGoAway(0));
439 CreateMockRead(*goaway1
, 2),
440 CreateMockRead(*goaway2
, 3),
441 MockRead(ASYNC
, 0, 4) // EOF
443 scoped_ptr
<SpdyFrame
> req1(
444 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
445 scoped_ptr
<SpdyFrame
> req2(
446 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
447 MockWrite writes
[] = {
448 CreateMockWrite(*req1
, 0),
449 CreateMockWrite(*req2
, 1),
451 DeterministicSocketData
data(reads
, arraysize(reads
),
452 writes
, arraysize(writes
));
453 data
.set_connect_data(connect_data
);
454 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
456 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
457 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
459 CreateDeterministicNetworkSession();
461 base::WeakPtr
<SpdySession
> session
=
462 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
464 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
466 GURL
url("http://www.google.com");
467 base::WeakPtr
<SpdyStream
> spdy_stream1
=
468 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
469 session
, url
, MEDIUM
, BoundNetLog());
470 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
471 spdy_stream1
->SetDelegate(&delegate1
);
473 base::WeakPtr
<SpdyStream
> spdy_stream2
=
474 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
475 session
, url
, MEDIUM
, BoundNetLog());
476 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
477 spdy_stream2
->SetDelegate(&delegate2
);
479 scoped_ptr
<SpdyHeaderBlock
> headers(
480 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
481 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
483 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
484 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
485 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
486 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
490 EXPECT_EQ(1u, spdy_stream1
->stream_id());
491 EXPECT_EQ(3u, spdy_stream2
->stream_id());
493 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
495 // Read and process the first GOAWAY frame.
498 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
500 EXPECT_FALSE(session
->IsStreamActive(3));
501 EXPECT_EQ(NULL
, spdy_stream2
.get());
502 EXPECT_TRUE(session
->IsStreamActive(1));
504 EXPECT_FALSE(session
->IsClosed());
506 // Read and process the second GOAWAY frame, which should close the
510 EXPECT_TRUE(session
== NULL
);
513 // Have a session with active streams receive a GOAWAY frame and then
514 // close it. It should handle the close properly (i.e., not try to
515 // make itself unavailable in its pool twice).
516 TEST_P(SpdySessionTest
, GoAwayWithActiveStreamsThenClose
) {
517 session_deps_
.host_resolver
->set_synchronous_mode(true);
519 MockConnect
connect_data(SYNCHRONOUS
, OK
);
520 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
522 CreateMockRead(*goaway
, 2),
523 MockRead(ASYNC
, 0, 3) // EOF
525 scoped_ptr
<SpdyFrame
> req1(
526 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
527 scoped_ptr
<SpdyFrame
> req2(
528 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
529 MockWrite writes
[] = {
530 CreateMockWrite(*req1
, 0),
531 CreateMockWrite(*req2
, 1),
533 DeterministicSocketData
data(reads
, arraysize(reads
),
534 writes
, arraysize(writes
));
535 data
.set_connect_data(connect_data
);
536 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
538 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
539 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
541 CreateDeterministicNetworkSession();
543 base::WeakPtr
<SpdySession
> session
=
544 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
546 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
548 GURL
url("http://www.google.com");
549 base::WeakPtr
<SpdyStream
> spdy_stream1
=
550 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
551 session
, url
, MEDIUM
, BoundNetLog());
552 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
553 spdy_stream1
->SetDelegate(&delegate1
);
555 base::WeakPtr
<SpdyStream
> spdy_stream2
=
556 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
557 session
, url
, MEDIUM
, BoundNetLog());
558 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
559 spdy_stream2
->SetDelegate(&delegate2
);
561 scoped_ptr
<SpdyHeaderBlock
> headers(
562 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
563 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock(*headers
));
565 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
566 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
567 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
568 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
572 EXPECT_EQ(1u, spdy_stream1
->stream_id());
573 EXPECT_EQ(3u, spdy_stream2
->stream_id());
575 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
577 // Read and process the GOAWAY frame.
580 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
582 EXPECT_FALSE(session
->IsStreamActive(3));
583 EXPECT_EQ(NULL
, spdy_stream2
.get());
584 EXPECT_TRUE(session
->IsStreamActive(1));
586 EXPECT_FALSE(session
->IsClosed());
588 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting session");
590 EXPECT_EQ(NULL
, spdy_stream1
.get());
591 EXPECT_TRUE(session
== NULL
);
594 // Try to create a stream after receiving a GOAWAY frame. It should
596 TEST_P(SpdySessionTest
, CreateStreamAfterGoAway
) {
597 const char kStreamUrl
[] = "http://www.google.com";
598 session_deps_
.host_resolver
->set_synchronous_mode(true);
600 MockConnect
connect_data(SYNCHRONOUS
, OK
);
601 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
603 CreateMockRead(*goaway
, 1),
604 MockRead(ASYNC
, 0, 2) // EOF
606 scoped_ptr
<SpdyFrame
> req(
607 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
608 MockWrite writes
[] = {
609 CreateMockWrite(*req
, 0),
611 DeterministicSocketData
data(reads
, arraysize(reads
),
612 writes
, arraysize(writes
));
613 data
.set_connect_data(connect_data
);
614 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
616 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
617 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
619 CreateDeterministicNetworkSession();
621 base::WeakPtr
<SpdySession
> session
=
622 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
624 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
626 GURL
url(kStreamUrl
);
627 base::WeakPtr
<SpdyStream
> spdy_stream
=
628 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
629 session
, url
, MEDIUM
, BoundNetLog());
630 test::StreamDelegateDoNothing
delegate(spdy_stream
);
631 spdy_stream
->SetDelegate(&delegate
);
633 scoped_ptr
<SpdyHeaderBlock
> headers(
634 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
635 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
636 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
640 EXPECT_EQ(1u, spdy_stream
->stream_id());
642 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
644 // Read and process the GOAWAY frame.
647 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
648 EXPECT_TRUE(session
->IsStreamActive(1));
650 SpdyStreamRequest stream_request
;
651 int rv
= stream_request
.StartRequest(
652 SPDY_REQUEST_RESPONSE_STREAM
, session
, url
, MEDIUM
, BoundNetLog(),
653 CompletionCallback());
654 EXPECT_EQ(ERR_FAILED
, rv
);
656 // Read and process EOF.
659 EXPECT_TRUE(session
== NULL
);
662 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
663 // the stream being refused.
664 TEST_P(SpdySessionTest
, SynStreamAfterGoAway
) {
665 const char kStreamUrl
[] = "http://www.google.com";
666 session_deps_
.host_resolver
->set_synchronous_mode(true);
668 MockConnect
connect_data(SYNCHRONOUS
, OK
);
669 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway(1));
670 scoped_ptr
<SpdyFrame
>
671 push(spdy_util_
.ConstructSpdyPush(NULL
, 0, 2, 1, kStreamUrl
));
673 CreateMockRead(*goaway
, 1),
674 CreateMockRead(*push
, 2),
675 MockRead(ASYNC
, 0, 4) // EOF
677 scoped_ptr
<SpdyFrame
> req(
678 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
679 scoped_ptr
<SpdyFrame
> rst(
680 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
681 MockWrite writes
[] = {
682 CreateMockWrite(*req
, 0),
683 CreateMockWrite(*rst
, 3)
685 DeterministicSocketData
data(reads
, arraysize(reads
),
686 writes
, arraysize(writes
));
687 data
.set_connect_data(connect_data
);
688 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
690 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
691 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
693 CreateDeterministicNetworkSession();
695 base::WeakPtr
<SpdySession
> session
=
696 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
698 EXPECT_EQ(spdy_util_
.spdy_version(), session
->GetProtocolVersion());
700 GURL
url(kStreamUrl
);
701 base::WeakPtr
<SpdyStream
> spdy_stream
=
702 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
703 session
, url
, MEDIUM
, BoundNetLog());
704 test::StreamDelegateDoNothing
delegate(spdy_stream
);
705 spdy_stream
->SetDelegate(&delegate
);
707 scoped_ptr
<SpdyHeaderBlock
> headers(
708 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
709 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
710 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
714 EXPECT_EQ(1u, spdy_stream
->stream_id());
716 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
718 // Read and process the GOAWAY frame.
721 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
722 EXPECT_TRUE(session
->IsStreamActive(1));
724 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
728 EXPECT_TRUE(session
== NULL
);
731 TEST_P(SpdySessionTest
, ClientPing
) {
732 session_deps_
.enable_ping
= true;
733 session_deps_
.host_resolver
->set_synchronous_mode(true);
735 MockConnect
connect_data(SYNCHRONOUS
, OK
);
736 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(1));
738 CreateMockRead(*read_ping
, 1),
739 MockRead(ASYNC
, 0, 0, 2) // EOF
741 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1));
742 MockWrite writes
[] = {
743 CreateMockWrite(*write_ping
, 0),
745 DeterministicSocketData
data(
746 reads
, arraysize(reads
), writes
, arraysize(writes
));
747 data
.set_connect_data(connect_data
);
748 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
750 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
751 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
753 CreateDeterministicNetworkSession();
755 base::WeakPtr
<SpdySession
> session
=
756 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
758 base::WeakPtr
<SpdyStream
> spdy_stream1
=
759 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
760 session
, test_url_
, MEDIUM
, BoundNetLog());
761 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
762 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
763 spdy_stream1
->SetDelegate(&delegate
);
765 base::TimeTicks before_ping_time
= base::TimeTicks::Now();
767 session
->set_connection_at_risk_of_loss_time(
768 base::TimeDelta::FromSeconds(-1));
769 session
->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
771 session
->SendPrefacePingIfNoneInFlight();
775 session
->CheckPingStatus(before_ping_time
);
777 EXPECT_EQ(0, session
->pings_in_flight());
778 EXPECT_GE(session
->next_ping_id(), static_cast<uint32
>(1));
779 EXPECT_FALSE(session
->check_ping_status_pending());
780 EXPECT_GE(session
->last_activity_time(), before_ping_time
);
784 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
786 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
787 EXPECT_TRUE(session
== NULL
);
790 TEST_P(SpdySessionTest
, ServerPing
) {
791 session_deps_
.host_resolver
->set_synchronous_mode(true);
793 MockConnect
connect_data(SYNCHRONOUS
, OK
);
794 scoped_ptr
<SpdyFrame
> read_ping(spdy_util_
.ConstructSpdyPing(2));
796 CreateMockRead(*read_ping
),
797 MockRead(SYNCHRONOUS
, 0, 0) // EOF
799 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(2));
800 MockWrite writes
[] = {
801 CreateMockWrite(*write_ping
),
803 StaticSocketDataProvider
data(
804 reads
, arraysize(reads
), writes
, arraysize(writes
));
805 data
.set_connect_data(connect_data
);
806 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
808 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
809 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
811 CreateNetworkSession();
813 base::WeakPtr
<SpdySession
> session
=
814 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
816 base::WeakPtr
<SpdyStream
> spdy_stream1
=
817 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
818 session
, test_url_
, MEDIUM
, BoundNetLog());
819 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
820 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
821 spdy_stream1
->SetDelegate(&delegate
);
823 // Flush the read completion task.
824 base::MessageLoop::current()->RunUntilIdle();
826 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
828 EXPECT_TRUE(session
== NULL
);
829 EXPECT_EQ(NULL
, spdy_stream1
.get());
832 // Cause a ping to be sent out while producing a write. The write loop
833 // should handle this properly, i.e. another DoWriteLoop task should
834 // not be posted. This is a regression test for
835 // http://crbug.com/261043 .
836 TEST_P(SpdySessionTest
, PingAndWriteLoop
) {
837 session_deps_
.enable_ping
= true;
838 session_deps_
.time_func
= TheNearFuture
;
840 MockConnect
connect_data(SYNCHRONOUS
, OK
);
841 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1));
842 scoped_ptr
<SpdyFrame
> req(
843 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
844 MockWrite writes
[] = {
845 CreateMockWrite(*req
, 0),
846 CreateMockWrite(*write_ping
, 1),
850 MockRead(ASYNC
, 0, 2) // EOF
853 session_deps_
.host_resolver
->set_synchronous_mode(true);
855 DeterministicSocketData
data(reads
, arraysize(reads
),
856 writes
, arraysize(writes
));
857 data
.set_connect_data(connect_data
);
858 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
860 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
861 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
863 CreateDeterministicNetworkSession();
865 base::WeakPtr
<SpdySession
> session
=
866 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
868 GURL
url("http://www.google.com");
869 base::WeakPtr
<SpdyStream
> spdy_stream
=
870 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
871 session
, url
, LOWEST
, BoundNetLog());
872 test::StreamDelegateDoNothing
delegate(spdy_stream
);
873 spdy_stream
->SetDelegate(&delegate
);
875 scoped_ptr
<SpdyHeaderBlock
> headers(
876 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
877 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
879 // Shift time so that a ping will be sent out.
880 g_time_delta
= base::TimeDelta::FromSeconds(11);
884 session
->CloseSessionOnError(ERR_ABORTED
, "Aborting");
887 TEST_P(SpdySessionTest
, DeleteExpiredPushStreams
) {
888 session_deps_
.host_resolver
->set_synchronous_mode(true);
890 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
891 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
892 session_deps_
.time_func
= TheNearFuture
;
894 CreateNetworkSession();
896 base::WeakPtr
<SpdySession
> session
=
897 CreateFakeSpdySession(spdy_session_pool_
, key_
);
899 session
->buffered_spdy_framer_
.reset(
900 new BufferedSpdyFramer(spdy_util_
.spdy_version(), false));
902 // Create the associated stream and add to active streams.
903 scoped_ptr
<SpdyHeaderBlock
> request_headers(
904 spdy_util_
.ConstructGetHeaderBlock("http://www.google.com/"));
906 scoped_ptr
<SpdyStream
> stream(new SpdyStream(SPDY_REQUEST_RESPONSE_STREAM
,
910 kSpdyStreamInitialWindowSize
,
911 kSpdyStreamInitialWindowSize
,
913 stream
->SendRequestHeaders(request_headers
.Pass(), NO_MORE_DATA_TO_SEND
);
914 SpdyStream
* stream_ptr
= stream
.get();
915 session
->InsertCreatedStream(stream
.Pass());
916 stream
= session
->ActivateCreatedStream(stream_ptr
);
917 session
->InsertActivatedStream(stream
.Pass());
919 SpdyHeaderBlock headers
;
920 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/a.dat", &headers
);
922 // OnSynStream() expects |in_io_loop_| to be true.
923 session
->in_io_loop_
= true;
924 session
->OnSynStream(2, 1, 0, 0, true, false, headers
);
925 session
->in_io_loop_
= false;
927 // Verify that there is one unclaimed push stream.
928 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
929 SpdySession::PushedStreamMap::iterator iter
=
930 session
->unclaimed_pushed_streams_
.find(
931 GURL("http://www.google.com/a.dat"));
932 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
934 // Shift time to expire the push stream.
935 g_time_delta
= base::TimeDelta::FromSeconds(301);
937 spdy_util_
.AddUrlToHeaderBlock("http://www.google.com/b.dat", &headers
);
938 session
->in_io_loop_
= true;
939 session
->OnSynStream(4, 1, 0, 0, true, false, headers
);
940 session
->in_io_loop_
= false;
942 // Verify that the second pushed stream evicted the first pushed stream.
943 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
944 iter
= session
->unclaimed_pushed_streams_
.find(
945 GURL("http://www.google.com/b.dat"));
946 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
949 TEST_P(SpdySessionTest
, FailedPing
) {
950 session_deps_
.host_resolver
->set_synchronous_mode(true);
952 MockConnect
connect_data(SYNCHRONOUS
, OK
);
954 MockRead(ASYNC
, 0, 0, 0) // EOF
956 scoped_ptr
<SpdyFrame
> write_ping(spdy_util_
.ConstructSpdyPing(1));
957 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
958 data
.set_connect_data(connect_data
);
959 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
961 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
962 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
964 CreateDeterministicNetworkSession();
966 base::WeakPtr
<SpdySession
> session
=
967 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
969 base::WeakPtr
<SpdyStream
> spdy_stream1
=
970 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
971 session
, test_url_
, MEDIUM
, BoundNetLog());
972 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
973 test::StreamDelegateSendImmediate
delegate(spdy_stream1
, NULL
);
974 spdy_stream1
->SetDelegate(&delegate
);
976 session
->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
977 session
->set_hung_interval(base::TimeDelta::FromSeconds(0));
979 // Send a PING frame.
980 session
->WritePingFrame(1);
981 EXPECT_LT(0, session
->pings_in_flight());
982 EXPECT_GE(session
->next_ping_id(), static_cast<uint32
>(1));
983 EXPECT_TRUE(session
->check_ping_status_pending());
985 // Assert session is not closed.
986 EXPECT_FALSE(session
->IsClosed());
987 EXPECT_LT(0u, session
->num_active_streams() + session
->num_created_streams());
988 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
990 // We set last time we have received any data in 1 sec less than now.
991 // CheckPingStatus will trigger timeout because hung interval is zero.
992 base::TimeTicks now
= base::TimeTicks::Now();
993 session
->last_activity_time_
= now
- base::TimeDelta::FromSeconds(1);
994 session
->CheckPingStatus(now
);
996 EXPECT_TRUE(session
== NULL
);
997 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1000 EXPECT_EQ(NULL
, spdy_stream1
.get());
1003 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1004 // settings frame increasing the max concurrent streams by 1. Make
1005 // sure nothing blows up. This is a regression test for
1006 // http://crbug.com/57331 .
1007 TEST_P(SpdySessionTest
, OnSettings
) {
1008 session_deps_
.host_resolver
->set_synchronous_mode(true);
1010 const SpdySettingsIds kSpdySettingsIds
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1012 SettingsMap new_settings
;
1013 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1014 new_settings
[kSpdySettingsIds
] =
1015 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1016 scoped_ptr
<SpdyFrame
> settings_frame(
1017 spdy_util_
.ConstructSpdySettings(new_settings
));
1018 MockRead reads
[] = {
1019 CreateMockRead(*settings_frame
, 0),
1020 MockRead(ASYNC
, 0, 1),
1023 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
1024 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1025 data
.set_connect_data(connect_data
);
1026 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1028 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1029 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1031 CreateDeterministicNetworkSession();
1033 base::WeakPtr
<SpdySession
> session
=
1034 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1036 // Create the maximum number of concurrent streams.
1037 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1038 base::WeakPtr
<SpdyStream
> spdy_stream
=
1039 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1040 session
, test_url_
, MEDIUM
, BoundNetLog());
1041 ASSERT_TRUE(spdy_stream
!= NULL
);
1044 StreamReleaserCallback stream_releaser
;
1045 SpdyStreamRequest request
;
1046 ASSERT_EQ(ERR_IO_PENDING
,
1047 request
.StartRequest(
1048 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1050 stream_releaser
.MakeCallback(&request
)));
1054 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1057 EXPECT_TRUE(session
== NULL
);
1060 // Start with a persisted value for max concurrent streams. Receive a
1061 // settings frame increasing the max concurrent streams by 1 and which
1062 // also clears the persisted data. Verify that persisted data is
1064 TEST_P(SpdySessionTest
, ClearSettings
) {
1065 session_deps_
.host_resolver
->set_synchronous_mode(true);
1067 SettingsMap new_settings
;
1068 const uint32 max_concurrent_streams
= kInitialMaxConcurrentStreams
+ 1;
1069 new_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1070 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1071 scoped_ptr
<SpdyFrame
> settings_frame(
1072 spdy_util_
.ConstructSpdySettings(new_settings
));
1073 uint8 flags
= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
1074 test::SetFrameFlags(settings_frame
.get(), flags
, spdy_util_
.spdy_version());
1075 MockRead reads
[] = {
1076 CreateMockRead(*settings_frame
, 0),
1077 MockRead(ASYNC
, 0, 1),
1080 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
1081 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1082 data
.set_connect_data(connect_data
);
1083 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1085 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1086 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1088 CreateDeterministicNetworkSession();
1090 // Initialize the SpdySetting with the default.
1091 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1092 test_host_port_pair_
,
1093 SETTINGS_MAX_CONCURRENT_STREAMS
,
1094 SETTINGS_FLAG_PLEASE_PERSIST
,
1095 kInitialMaxConcurrentStreams
);
1098 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1099 test_host_port_pair_
).empty());
1101 base::WeakPtr
<SpdySession
> session
=
1102 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1104 // Create the maximum number of concurrent streams.
1105 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
; ++i
) {
1106 base::WeakPtr
<SpdyStream
> spdy_stream
=
1107 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1108 session
, test_url_
, MEDIUM
, BoundNetLog());
1109 ASSERT_TRUE(spdy_stream
!= NULL
);
1112 StreamReleaserCallback stream_releaser
;
1114 SpdyStreamRequest request
;
1115 ASSERT_EQ(ERR_IO_PENDING
,
1116 request
.StartRequest(
1117 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1119 stream_releaser
.MakeCallback(&request
)));
1123 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
1125 // Make sure that persisted data is cleared.
1127 spdy_session_pool_
->http_server_properties()->GetSpdySettings(
1128 test_host_port_pair_
).empty());
1130 // Make sure session's max_concurrent_streams is correct.
1131 EXPECT_EQ(kInitialMaxConcurrentStreams
+ 1,
1132 session
->max_concurrent_streams());
1135 EXPECT_TRUE(session
== NULL
);
1138 // Start with max concurrent streams set to 1. Request two streams.
1139 // When the first completes, have the callback close its stream, which
1140 // should trigger the second stream creation. Then cancel that one
1141 // immediately. Don't crash. This is a regression test for
1142 // http://crbug.com/63532 .
1143 TEST_P(SpdySessionTest
, CancelPendingCreateStream
) {
1144 session_deps_
.host_resolver
->set_synchronous_mode(true);
1146 MockRead reads
[] = {
1147 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1150 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1151 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1153 data
.set_connect_data(connect_data
);
1154 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1156 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1157 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
1159 CreateNetworkSession();
1161 // Initialize the SpdySetting with 1 max concurrent streams.
1162 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1163 test_host_port_pair_
,
1164 SETTINGS_MAX_CONCURRENT_STREAMS
,
1165 SETTINGS_FLAG_PLEASE_PERSIST
,
1168 base::WeakPtr
<SpdySession
> session
=
1169 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1171 // Leave room for only one more stream to be created.
1172 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
1173 base::WeakPtr
<SpdyStream
> spdy_stream
=
1174 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1175 session
, test_url_
, MEDIUM
, BoundNetLog());
1176 ASSERT_TRUE(spdy_stream
!= NULL
);
1179 // Create 2 more streams. First will succeed. Second will be pending.
1180 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1181 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1182 session
, test_url_
, MEDIUM
, BoundNetLog());
1183 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1185 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1186 // a valgrind error if the callback is invoked when it's not supposed to be.
1187 scoped_ptr
<TestCompletionCallback
> callback(new TestCompletionCallback
);
1189 SpdyStreamRequest request
;
1190 ASSERT_EQ(ERR_IO_PENDING
,
1191 request
.StartRequest(
1192 SPDY_BIDIRECTIONAL_STREAM
, session
, test_url_
, MEDIUM
,
1194 callback
->callback()));
1196 // Release the first one, this will allow the second to be created.
1197 spdy_stream1
->Cancel();
1198 EXPECT_EQ(NULL
, spdy_stream1
.get());
1200 request
.CancelRequest();
1203 // Should not crash when running the pending callback.
1204 base::MessageLoop::current()->RunUntilIdle();
1207 TEST_P(SpdySessionTest
, SendInitialDataOnNewSession
) {
1208 session_deps_
.host_resolver
->set_synchronous_mode(true);
1210 MockRead reads
[] = {
1211 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1214 SettingsMap settings
;
1215 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1216 const SpdySettingsIds kSpdySettingsIds2
= SETTINGS_INITIAL_WINDOW_SIZE
;
1217 const uint32 kInitialRecvWindowSize
= 10 * 1024 * 1024;
1218 settings
[kSpdySettingsIds1
] =
1219 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
1220 if (spdy_util_
.spdy_version() >= SPDY3
) {
1221 settings
[kSpdySettingsIds2
] =
1222 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kInitialRecvWindowSize
);
1224 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1225 scoped_ptr
<SpdyFrame
> settings_frame(
1226 spdy_util_
.ConstructSpdySettings(settings
));
1227 scoped_ptr
<SpdyFrame
> initial_window_update(
1228 spdy_util_
.ConstructSpdyWindowUpdate(
1229 kSessionFlowControlStreamId
,
1230 kDefaultInitialRecvWindowSize
- kSpdySessionInitialWindowSize
));
1231 std::vector
<MockWrite
> writes
;
1232 if (GetParam() == kProtoHTTP2Draft04
) {
1235 kHttp2ConnectionHeaderPrefix
,
1236 kHttp2ConnectionHeaderPrefixSize
));
1238 writes
.push_back(CreateMockWrite(*settings_frame
));
1239 if (GetParam() >= kProtoSPDY31
) {
1240 writes
.push_back(CreateMockWrite(*initial_window_update
));
1243 SettingsMap server_settings
;
1244 const uint32 initial_max_concurrent_streams
= 1;
1245 server_settings
[SETTINGS_MAX_CONCURRENT_STREAMS
] =
1246 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED
,
1247 initial_max_concurrent_streams
);
1248 scoped_ptr
<SpdyFrame
> server_settings_frame(
1249 spdy_util_
.ConstructSpdySettings(server_settings
));
1250 writes
.push_back(CreateMockWrite(*server_settings_frame
));
1252 session_deps_
.stream_initial_recv_window_size
= kInitialRecvWindowSize
;
1254 StaticSocketDataProvider
data(reads
, arraysize(reads
),
1255 vector_as_array(&writes
), writes
.size());
1256 data
.set_connect_data(connect_data
);
1257 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1259 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1260 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
1262 CreateNetworkSession();
1264 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1265 test_host_port_pair_
,
1266 SETTINGS_MAX_CONCURRENT_STREAMS
,
1267 SETTINGS_FLAG_PLEASE_PERSIST
,
1268 initial_max_concurrent_streams
);
1270 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
1271 pool_peer
.SetEnableSendingInitialData(true);
1273 base::WeakPtr
<SpdySession
> session
=
1274 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1276 base::MessageLoop::current()->RunUntilIdle();
1277 EXPECT_TRUE(data
.at_write_eof());
1280 TEST_P(SpdySessionTest
, ClearSettingsStorageOnIPAddressChanged
) {
1281 CreateNetworkSession();
1283 base::WeakPtr
<HttpServerProperties
> test_http_server_properties
=
1284 spdy_session_pool_
->http_server_properties();
1285 SettingsFlagsAndValue
flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST
, 2);
1286 test_http_server_properties
->SetSpdySetting(
1287 test_host_port_pair_
,
1288 SETTINGS_MAX_CONCURRENT_STREAMS
,
1289 SETTINGS_FLAG_PLEASE_PERSIST
,
1291 EXPECT_NE(0u, test_http_server_properties
->GetSpdySettings(
1292 test_host_port_pair_
).size());
1293 spdy_session_pool_
->OnIPAddressChanged();
1294 EXPECT_EQ(0u, test_http_server_properties
->GetSpdySettings(
1295 test_host_port_pair_
).size());
1298 TEST_P(SpdySessionTest
, Initialize
) {
1299 CapturingBoundNetLog log
;
1300 session_deps_
.net_log
= log
.bound().net_log();
1301 session_deps_
.host_resolver
->set_synchronous_mode(true);
1303 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1304 MockRead reads
[] = {
1305 MockRead(ASYNC
, 0, 0) // EOF
1308 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1309 data
.set_connect_data(connect_data
);
1310 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1312 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1313 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
1315 CreateNetworkSession();
1317 base::WeakPtr
<SpdySession
> session
=
1318 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1319 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1321 // Flush the read completion task.
1322 base::MessageLoop::current()->RunUntilIdle();
1324 net::CapturingNetLog::CapturedEntryList entries
;
1325 log
.GetEntries(&entries
);
1326 EXPECT_LT(0u, entries
.size());
1328 // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly.
1329 int pos
= net::ExpectLogContainsSomewhere(
1331 net::NetLog::TYPE_SPDY_SESSION_INITIALIZED
,
1332 net::NetLog::PHASE_NONE
);
1335 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1336 NetLog::Source socket_source
;
1337 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry
.params
.get(),
1339 EXPECT_TRUE(socket_source
.IsValid());
1340 EXPECT_NE(log
.bound().source().id
, socket_source
.id
);
1343 TEST_P(SpdySessionTest
, CloseSessionOnError
) {
1344 session_deps_
.host_resolver
->set_synchronous_mode(true);
1346 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1347 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
1348 MockRead reads
[] = {
1349 CreateMockRead(*goaway
),
1350 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1353 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1354 data
.set_connect_data(connect_data
);
1355 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1357 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1358 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
1360 CreateNetworkSession();
1362 CapturingBoundNetLog log
;
1363 base::WeakPtr
<SpdySession
> session
=
1364 CreateInsecureSpdySession(http_session_
, key_
, log
.bound());
1365 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
1367 // Flush the read completion task.
1368 base::MessageLoop::current()->RunUntilIdle();
1370 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
1371 EXPECT_TRUE(session
== NULL
);
1373 // Check that the NetLog was filled reasonably.
1374 net::CapturingNetLog::CapturedEntryList entries
;
1375 log
.GetEntries(&entries
);
1376 EXPECT_LT(0u, entries
.size());
1378 // Check that we logged SPDY_SESSION_CLOSE correctly.
1379 int pos
= net::ExpectLogContainsSomewhere(
1381 net::NetLog::TYPE_SPDY_SESSION_CLOSE
,
1382 net::NetLog::PHASE_NONE
);
1384 if (pos
< static_cast<int>(entries
.size())) {
1385 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
1387 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
1388 EXPECT_EQ(ERR_CONNECTION_CLOSED
, error_code
);
1394 // Queue up a low-priority SYN_STREAM followed by a high-priority
1395 // one. The high priority one should still send first and receive
1397 TEST_P(SpdySessionTest
, OutOfOrderSynStreams
) {
1398 // Construct the request.
1399 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1400 scoped_ptr
<SpdyFrame
> req_highest(
1401 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, HIGHEST
, true));
1402 scoped_ptr
<SpdyFrame
> req_lowest(
1403 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
1404 MockWrite writes
[] = {
1405 CreateMockWrite(*req_highest
, 0),
1406 CreateMockWrite(*req_lowest
, 1),
1409 scoped_ptr
<SpdyFrame
> resp_highest(
1410 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1411 scoped_ptr
<SpdyFrame
> body_highest(
1412 spdy_util_
.ConstructSpdyBodyFrame(1, true));
1413 scoped_ptr
<SpdyFrame
> resp_lowest(
1414 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
1415 scoped_ptr
<SpdyFrame
> body_lowest(
1416 spdy_util_
.ConstructSpdyBodyFrame(3, true));
1417 MockRead reads
[] = {
1418 CreateMockRead(*resp_highest
, 2),
1419 CreateMockRead(*body_highest
, 3),
1420 CreateMockRead(*resp_lowest
, 4),
1421 CreateMockRead(*body_lowest
, 5),
1422 MockRead(ASYNC
, 0, 6) // EOF
1425 session_deps_
.host_resolver
->set_synchronous_mode(true);
1427 DeterministicSocketData
data(reads
, arraysize(reads
),
1428 writes
, arraysize(writes
));
1429 data
.set_connect_data(connect_data
);
1430 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1432 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1433 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1435 CreateDeterministicNetworkSession();
1437 base::WeakPtr
<SpdySession
> session
=
1438 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1440 GURL
url("http://www.google.com");
1442 base::WeakPtr
<SpdyStream
> spdy_stream_lowest
=
1443 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1444 session
, url
, LOWEST
, BoundNetLog());
1445 ASSERT_TRUE(spdy_stream_lowest
);
1446 EXPECT_EQ(0u, spdy_stream_lowest
->stream_id());
1447 test::StreamDelegateDoNothing
delegate_lowest(spdy_stream_lowest
);
1448 spdy_stream_lowest
->SetDelegate(&delegate_lowest
);
1450 base::WeakPtr
<SpdyStream
> spdy_stream_highest
=
1451 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1452 session
, url
, HIGHEST
, BoundNetLog());
1453 ASSERT_TRUE(spdy_stream_highest
);
1454 EXPECT_EQ(0u, spdy_stream_highest
->stream_id());
1455 test::StreamDelegateDoNothing
delegate_highest(spdy_stream_highest
);
1456 spdy_stream_highest
->SetDelegate(&delegate_highest
);
1458 // Queue the lower priority one first.
1460 scoped_ptr
<SpdyHeaderBlock
> headers_lowest(
1461 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1462 spdy_stream_lowest
->SendRequestHeaders(
1463 headers_lowest
.Pass(), NO_MORE_DATA_TO_SEND
);
1464 EXPECT_TRUE(spdy_stream_lowest
->HasUrlFromHeaders());
1466 scoped_ptr
<SpdyHeaderBlock
> headers_highest(
1467 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1468 spdy_stream_highest
->SendRequestHeaders(
1469 headers_highest
.Pass(), NO_MORE_DATA_TO_SEND
);
1470 EXPECT_TRUE(spdy_stream_highest
->HasUrlFromHeaders());
1474 EXPECT_FALSE(spdy_stream_lowest
);
1475 EXPECT_FALSE(spdy_stream_highest
);
1476 EXPECT_EQ(3u, delegate_lowest
.stream_id());
1477 EXPECT_EQ(1u, delegate_highest
.stream_id());
1480 TEST_P(SpdySessionTest
, CancelStream
) {
1481 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1482 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1483 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1484 scoped_ptr
<SpdyFrame
> req2(
1485 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
1486 MockWrite writes
[] = {
1487 CreateMockWrite(*req2
, 0),
1490 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1491 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
1492 MockRead reads
[] = {
1493 CreateMockRead(*resp2
, 1),
1494 CreateMockRead(*body2
, 2),
1495 MockRead(ASYNC
, 0, 3) // EOF
1498 session_deps_
.host_resolver
->set_synchronous_mode(true);
1500 DeterministicSocketData
data(reads
, arraysize(reads
),
1501 writes
, arraysize(writes
));
1502 data
.set_connect_data(connect_data
);
1503 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1505 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1506 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1508 CreateDeterministicNetworkSession();
1510 base::WeakPtr
<SpdySession
> session
=
1511 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1513 GURL
url1("http://www.google.com");
1514 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1515 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1516 session
, url1
, HIGHEST
, BoundNetLog());
1517 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1518 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1519 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
1520 spdy_stream1
->SetDelegate(&delegate1
);
1522 GURL
url2("http://www.google.com");
1523 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1524 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1525 session
, url2
, LOWEST
, BoundNetLog());
1526 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1527 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1528 test::StreamDelegateDoNothing
delegate2(spdy_stream2
);
1529 spdy_stream2
->SetDelegate(&delegate2
);
1531 scoped_ptr
<SpdyHeaderBlock
> headers(
1532 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1533 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1534 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1536 scoped_ptr
<SpdyHeaderBlock
> headers2(
1537 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1538 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1539 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1541 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1543 spdy_stream1
->Cancel();
1544 EXPECT_EQ(NULL
, spdy_stream1
.get());
1546 EXPECT_EQ(0u, delegate1
.stream_id());
1550 EXPECT_EQ(0u, delegate1
.stream_id());
1551 EXPECT_EQ(1u, delegate2
.stream_id());
1553 spdy_stream2
->Cancel();
1554 EXPECT_EQ(NULL
, spdy_stream2
.get());
1557 // Create two streams that are set to re-close themselves on close,
1558 // and then close the session. Nothing should blow up. Also a
1559 // regression test for http://crbug.com/139518 .
1560 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedSelfClosingStreams
) {
1561 session_deps_
.host_resolver
->set_synchronous_mode(true);
1563 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1565 // No actual data will be sent.
1566 MockWrite writes
[] = {
1567 MockWrite(ASYNC
, 0, 1) // EOF
1570 MockRead reads
[] = {
1571 MockRead(ASYNC
, 0, 0) // EOF
1573 DeterministicSocketData
data(reads
, arraysize(reads
),
1574 writes
, arraysize(writes
));
1575 data
.set_connect_data(connect_data
);
1576 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1578 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1579 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1581 CreateDeterministicNetworkSession();
1583 base::WeakPtr
<SpdySession
> session
=
1584 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1586 GURL
url1("http://www.google.com");
1587 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1588 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1589 session
, url1
, HIGHEST
, BoundNetLog());
1590 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1591 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1593 GURL
url2("http://www.google.com");
1594 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1595 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1596 session
, url2
, LOWEST
, BoundNetLog());
1597 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1598 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1600 test::ClosingDelegate
delegate1(spdy_stream1
);
1601 spdy_stream1
->SetDelegate(&delegate1
);
1603 test::ClosingDelegate
delegate2(spdy_stream2
);
1604 spdy_stream2
->SetDelegate(&delegate2
);
1606 scoped_ptr
<SpdyHeaderBlock
> headers(
1607 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1608 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1609 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1611 scoped_ptr
<SpdyHeaderBlock
> headers2(
1612 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1613 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1614 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1616 // Ensure that the streams have not yet been activated and assigned an id.
1617 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1618 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1620 // Ensure we don't crash while closing the session.
1621 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
1623 EXPECT_EQ(NULL
, spdy_stream1
.get());
1624 EXPECT_EQ(NULL
, spdy_stream2
.get());
1626 EXPECT_TRUE(delegate1
.StreamIsClosed());
1627 EXPECT_TRUE(delegate2
.StreamIsClosed());
1629 EXPECT_TRUE(session
== NULL
);
1632 // Create two streams that are set to close each other on close, and
1633 // then close the session. Nothing should blow up.
1634 TEST_P(SpdySessionTest
, CloseSessionWithTwoCreatedMutuallyClosingStreams
) {
1635 session_deps_
.host_resolver
->set_synchronous_mode(true);
1637 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1639 // No actual data will be sent.
1640 MockWrite writes
[] = {
1641 MockWrite(ASYNC
, 0, 1) // EOF
1644 MockRead reads
[] = {
1645 MockRead(ASYNC
, 0, 0) // EOF
1647 DeterministicSocketData
data(reads
, arraysize(reads
),
1648 writes
, arraysize(writes
));
1649 data
.set_connect_data(connect_data
);
1650 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1652 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1653 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1655 CreateDeterministicNetworkSession();
1657 base::WeakPtr
<SpdySession
> session
=
1658 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1660 GURL
url1("http://www.google.com");
1661 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1662 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1663 session
, url1
, HIGHEST
, BoundNetLog());
1664 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1665 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1667 GURL
url2("http://www.google.com");
1668 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1669 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
1670 session
, url2
, LOWEST
, BoundNetLog());
1671 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1672 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1674 // Make |spdy_stream1| close |spdy_stream2|.
1675 test::ClosingDelegate
delegate1(spdy_stream2
);
1676 spdy_stream1
->SetDelegate(&delegate1
);
1678 // Make |spdy_stream2| close |spdy_stream1|.
1679 test::ClosingDelegate
delegate2(spdy_stream1
);
1680 spdy_stream2
->SetDelegate(&delegate2
);
1682 scoped_ptr
<SpdyHeaderBlock
> headers(
1683 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1684 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1685 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1687 scoped_ptr
<SpdyHeaderBlock
> headers2(
1688 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1689 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1690 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1692 // Ensure that the streams have not yet been activated and assigned an id.
1693 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1694 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1696 // Ensure we don't crash while closing the session.
1697 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
1699 EXPECT_EQ(NULL
, spdy_stream1
.get());
1700 EXPECT_EQ(NULL
, spdy_stream2
.get());
1702 EXPECT_TRUE(delegate1
.StreamIsClosed());
1703 EXPECT_TRUE(delegate2
.StreamIsClosed());
1705 EXPECT_TRUE(session
== NULL
);
1708 // Create two streams that are set to re-close themselves on close,
1709 // activate them, and then close the session. Nothing should blow up.
1710 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedSelfClosingStreams
) {
1711 session_deps_
.host_resolver
->set_synchronous_mode(true);
1713 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1715 scoped_ptr
<SpdyFrame
> req1(
1716 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
1717 scoped_ptr
<SpdyFrame
> req2(
1718 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
1719 MockWrite writes
[] = {
1720 CreateMockWrite(*req1
, 0),
1721 CreateMockWrite(*req2
, 1),
1724 MockRead reads
[] = {
1725 MockRead(ASYNC
, 0, 2) // EOF
1728 DeterministicSocketData
data(reads
, arraysize(reads
),
1729 writes
, arraysize(writes
));
1730 data
.set_connect_data(connect_data
);
1731 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1733 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1734 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1736 CreateDeterministicNetworkSession();
1738 base::WeakPtr
<SpdySession
> session
=
1739 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1741 GURL
url1("http://www.google.com");
1742 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1743 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1744 session
, url1
, MEDIUM
, BoundNetLog());
1745 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1746 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1748 GURL
url2("http://www.google.com");
1749 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1750 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1751 session
, url2
, MEDIUM
, BoundNetLog());
1752 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1753 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1755 test::ClosingDelegate
delegate1(spdy_stream1
);
1756 spdy_stream1
->SetDelegate(&delegate1
);
1758 test::ClosingDelegate
delegate2(spdy_stream2
);
1759 spdy_stream2
->SetDelegate(&delegate2
);
1761 scoped_ptr
<SpdyHeaderBlock
> headers(
1762 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1763 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1764 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1766 scoped_ptr
<SpdyHeaderBlock
> headers2(
1767 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1768 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1769 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1771 // Ensure that the streams have not yet been activated and assigned an id.
1772 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1773 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1777 EXPECT_EQ(1u, spdy_stream1
->stream_id());
1778 EXPECT_EQ(3u, spdy_stream2
->stream_id());
1780 // Ensure we don't crash while closing the session.
1781 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
1783 EXPECT_EQ(NULL
, spdy_stream1
.get());
1784 EXPECT_EQ(NULL
, spdy_stream2
.get());
1786 EXPECT_TRUE(delegate1
.StreamIsClosed());
1787 EXPECT_TRUE(delegate2
.StreamIsClosed());
1789 EXPECT_TRUE(session
== NULL
);
1792 // Create two streams that are set to close each other on close,
1793 // activate them, and then close the session. Nothing should blow up.
1794 TEST_P(SpdySessionTest
, CloseSessionWithTwoActivatedMutuallyClosingStreams
) {
1795 session_deps_
.host_resolver
->set_synchronous_mode(true);
1797 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1799 scoped_ptr
<SpdyFrame
> req1(
1800 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
1801 scoped_ptr
<SpdyFrame
> req2(
1802 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
, true));
1803 MockWrite writes
[] = {
1804 CreateMockWrite(*req1
, 0),
1805 CreateMockWrite(*req2
, 1),
1808 MockRead reads
[] = {
1809 MockRead(ASYNC
, 0, 2) // EOF
1812 DeterministicSocketData
data(reads
, arraysize(reads
),
1813 writes
, arraysize(writes
));
1814 data
.set_connect_data(connect_data
);
1815 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1817 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1818 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1820 CreateDeterministicNetworkSession();
1822 base::WeakPtr
<SpdySession
> session
=
1823 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1825 GURL
url1("http://www.google.com");
1826 base::WeakPtr
<SpdyStream
> spdy_stream1
=
1827 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1828 session
, url1
, MEDIUM
, BoundNetLog());
1829 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1830 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1832 GURL
url2("http://www.google.com");
1833 base::WeakPtr
<SpdyStream
> spdy_stream2
=
1834 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1835 session
, url2
, MEDIUM
, BoundNetLog());
1836 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1837 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1839 // Make |spdy_stream1| close |spdy_stream2|.
1840 test::ClosingDelegate
delegate1(spdy_stream2
);
1841 spdy_stream1
->SetDelegate(&delegate1
);
1843 // Make |spdy_stream2| close |spdy_stream1|.
1844 test::ClosingDelegate
delegate2(spdy_stream1
);
1845 spdy_stream2
->SetDelegate(&delegate2
);
1847 scoped_ptr
<SpdyHeaderBlock
> headers(
1848 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
1849 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1850 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
1852 scoped_ptr
<SpdyHeaderBlock
> headers2(
1853 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
1854 spdy_stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
1855 EXPECT_TRUE(spdy_stream2
->HasUrlFromHeaders());
1857 // Ensure that the streams have not yet been activated and assigned an id.
1858 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1859 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1863 EXPECT_EQ(1u, spdy_stream1
->stream_id());
1864 EXPECT_EQ(3u, spdy_stream2
->stream_id());
1866 // Ensure we don't crash while closing the session.
1867 session
->CloseSessionOnError(ERR_ABORTED
, std::string());
1869 EXPECT_EQ(NULL
, spdy_stream1
.get());
1870 EXPECT_EQ(NULL
, spdy_stream2
.get());
1872 EXPECT_TRUE(delegate1
.StreamIsClosed());
1873 EXPECT_TRUE(delegate2
.StreamIsClosed());
1875 EXPECT_TRUE(session
== NULL
);
1878 // Delegate that closes a given session when the stream is closed.
1879 class SessionClosingDelegate
: public test::StreamDelegateDoNothing
{
1881 SessionClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
1882 const base::WeakPtr
<SpdySession
>& session_to_close
)
1883 : StreamDelegateDoNothing(stream
),
1884 session_to_close_(session_to_close
) {}
1886 virtual ~SessionClosingDelegate() {}
1888 virtual void OnClose(int status
) OVERRIDE
{
1889 session_to_close_
->CloseSessionOnError(ERR_ABORTED
, "Aborted");
1893 base::WeakPtr
<SpdySession
> session_to_close_
;
1896 // Close an activated stream that closes its session. Nothing should
1897 // blow up. This is a regression test for http://crbug.com/263691 .
1898 TEST_P(SpdySessionTest
, CloseActivatedStreamThatClosesSession
) {
1899 session_deps_
.host_resolver
->set_synchronous_mode(true);
1901 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1903 scoped_ptr
<SpdyFrame
> req(
1904 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
1905 MockWrite writes
[] = {
1906 CreateMockWrite(*req
, 0),
1909 MockRead reads
[] = {
1910 MockRead(ASYNC
, 0, 1) // EOF
1912 DeterministicSocketData
data(reads
, arraysize(reads
),
1913 writes
, arraysize(writes
));
1914 data
.set_connect_data(connect_data
);
1915 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1917 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1918 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1920 CreateDeterministicNetworkSession();
1922 base::WeakPtr
<SpdySession
> session
=
1923 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
1925 GURL
url("http://www.google.com");
1926 base::WeakPtr
<SpdyStream
> spdy_stream
=
1927 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
1928 session
, url
, MEDIUM
, BoundNetLog());
1929 ASSERT_TRUE(spdy_stream
.get() != NULL
);
1930 EXPECT_EQ(0u, spdy_stream
->stream_id());
1932 SessionClosingDelegate
delegate(spdy_stream
, session
);
1933 spdy_stream
->SetDelegate(&delegate
);
1935 scoped_ptr
<SpdyHeaderBlock
> headers(
1936 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
1937 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
1938 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
1940 EXPECT_EQ(0u, spdy_stream
->stream_id());
1944 EXPECT_EQ(1u, spdy_stream
->stream_id());
1946 // Ensure we don't crash while closing the stream (which closes the
1948 spdy_stream
->Cancel();
1950 EXPECT_EQ(NULL
, spdy_stream
.get());
1951 EXPECT_TRUE(delegate
.StreamIsClosed());
1952 EXPECT_TRUE(session
== NULL
);
1955 TEST_P(SpdySessionTest
, VerifyDomainAuthentication
) {
1956 session_deps_
.host_resolver
->set_synchronous_mode(true);
1958 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1960 // No actual data will be sent.
1961 MockWrite writes
[] = {
1962 MockWrite(ASYNC
, 0, 1) // EOF
1965 MockRead reads
[] = {
1966 MockRead(ASYNC
, 0, 0) // EOF
1968 DeterministicSocketData
data(reads
, arraysize(reads
),
1969 writes
, arraysize(writes
));
1970 data
.set_connect_data(connect_data
);
1971 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1973 // Load a cert that is valid for:
1977 base::FilePath certs_dir
= GetTestCertsDirectory();
1978 scoped_refptr
<X509Certificate
> test_cert(
1979 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
1980 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
);
1982 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1983 ssl
.cert
= test_cert
;
1984 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1986 CreateDeterministicNetworkSession();
1988 base::WeakPtr
<SpdySession
> session
=
1989 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
1991 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
1992 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
1993 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.com"));
1994 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
1997 TEST_P(SpdySessionTest
, ConnectionPooledWithTlsChannelId
) {
1998 session_deps_
.host_resolver
->set_synchronous_mode(true);
2000 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2002 // No actual data will be sent.
2003 MockWrite writes
[] = {
2004 MockWrite(ASYNC
, 0, 1) // EOF
2007 MockRead reads
[] = {
2008 MockRead(ASYNC
, 0, 0) // EOF
2010 DeterministicSocketData
data(reads
, arraysize(reads
),
2011 writes
, arraysize(writes
));
2012 data
.set_connect_data(connect_data
);
2013 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2015 // Load a cert that is valid for:
2019 base::FilePath certs_dir
= GetTestCertsDirectory();
2020 scoped_refptr
<X509Certificate
> test_cert(
2021 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
2022 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
);
2024 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2025 ssl
.channel_id_sent
= true;
2026 ssl
.cert
= test_cert
;
2027 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2029 CreateDeterministicNetworkSession();
2031 base::WeakPtr
<SpdySession
> session
=
2032 CreateSecureSpdySession(http_session_
, key_
, BoundNetLog());
2034 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
2035 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
2036 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.example.com"));
2037 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
2040 TEST_P(SpdySessionTest
, CloseTwoStalledCreateStream
) {
2041 // TODO(rtenneti): Define a helper class/methods and move the common code in
2043 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2045 SettingsMap new_settings
;
2046 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
2047 const uint32 max_concurrent_streams
= 1;
2048 new_settings
[kSpdySettingsIds1
] =
2049 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
2051 scoped_ptr
<SpdyFrame
> req1(
2052 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2053 scoped_ptr
<SpdyFrame
> req2(
2054 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
2055 scoped_ptr
<SpdyFrame
> req3(
2056 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
, true));
2057 MockWrite writes
[] = {
2058 CreateMockWrite(*req1
, 1),
2059 CreateMockWrite(*req2
, 4),
2060 CreateMockWrite(*req3
, 7),
2063 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2065 scoped_ptr
<SpdyFrame
> settings_frame(
2066 spdy_util_
.ConstructSpdySettings(new_settings
));
2068 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2069 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2071 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
2072 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
2074 scoped_ptr
<SpdyFrame
> resp3(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 5));
2075 scoped_ptr
<SpdyFrame
> body3(spdy_util_
.ConstructSpdyBodyFrame(5, true));
2077 MockRead reads
[] = {
2078 CreateMockRead(*settings_frame
),
2079 CreateMockRead(*resp1
, 2),
2080 CreateMockRead(*body1
, 3),
2081 CreateMockRead(*resp2
, 5),
2082 CreateMockRead(*body2
, 6),
2083 CreateMockRead(*resp3
, 8),
2084 CreateMockRead(*body3
, 9),
2085 MockRead(ASYNC
, 0, 10) // EOF
2088 DeterministicSocketData
data(reads
, arraysize(reads
),
2089 writes
, arraysize(writes
));
2090 data
.set_connect_data(connect_data
);
2091 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2093 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2094 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2096 CreateDeterministicNetworkSession();
2098 base::WeakPtr
<SpdySession
> session
=
2099 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2101 // Read the settings frame.
2104 GURL
url1("http://www.google.com");
2105 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2106 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2107 session
, url1
, LOWEST
, BoundNetLog());
2108 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2109 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2110 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2111 spdy_stream1
->SetDelegate(&delegate1
);
2113 TestCompletionCallback callback2
;
2114 GURL
url2("http://www.google.com");
2115 SpdyStreamRequest request2
;
2116 ASSERT_EQ(ERR_IO_PENDING
,
2117 request2
.StartRequest(
2118 SPDY_REQUEST_RESPONSE_STREAM
,
2119 session
, url2
, LOWEST
, BoundNetLog(), callback2
.callback()));
2121 TestCompletionCallback callback3
;
2122 GURL
url3("http://www.google.com");
2123 SpdyStreamRequest request3
;
2124 ASSERT_EQ(ERR_IO_PENDING
,
2125 request3
.StartRequest(
2126 SPDY_REQUEST_RESPONSE_STREAM
,
2127 session
, url3
, LOWEST
, BoundNetLog(), callback3
.callback()));
2129 EXPECT_EQ(0u, session
->num_active_streams());
2130 EXPECT_EQ(1u, session
->num_created_streams());
2131 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2133 scoped_ptr
<SpdyHeaderBlock
> headers(
2134 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2135 spdy_stream1
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
2136 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2138 // Run until 1st stream is activated and then closed.
2139 EXPECT_EQ(0u, delegate1
.stream_id());
2141 EXPECT_EQ(NULL
, spdy_stream1
.get());
2142 EXPECT_EQ(1u, delegate1
.stream_id());
2144 EXPECT_EQ(0u, session
->num_active_streams());
2145 EXPECT_EQ(0u, session
->num_created_streams());
2146 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2148 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2149 // create the 2nd stream.
2150 base::MessageLoop::current()->RunUntilIdle();
2152 EXPECT_EQ(0u, session
->num_active_streams());
2153 EXPECT_EQ(1u, session
->num_created_streams());
2154 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2156 base::WeakPtr
<SpdyStream
> stream2
= request2
.ReleaseStream();
2157 test::StreamDelegateDoNothing
delegate2(stream2
);
2158 stream2
->SetDelegate(&delegate2
);
2159 scoped_ptr
<SpdyHeaderBlock
> headers2(
2160 spdy_util_
.ConstructGetHeaderBlock(url2
.spec()));
2161 stream2
->SendRequestHeaders(headers2
.Pass(), NO_MORE_DATA_TO_SEND
);
2162 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
2164 // Run until 2nd stream is activated and then closed.
2165 EXPECT_EQ(0u, delegate2
.stream_id());
2167 EXPECT_EQ(NULL
, stream2
.get());
2168 EXPECT_EQ(3u, delegate2
.stream_id());
2170 EXPECT_EQ(0u, session
->num_active_streams());
2171 EXPECT_EQ(0u, session
->num_created_streams());
2172 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2174 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2175 // create the 3rd stream.
2176 base::MessageLoop::current()->RunUntilIdle();
2178 EXPECT_EQ(0u, session
->num_active_streams());
2179 EXPECT_EQ(1u, session
->num_created_streams());
2180 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2182 base::WeakPtr
<SpdyStream
> stream3
= request3
.ReleaseStream();
2183 test::StreamDelegateDoNothing
delegate3(stream3
);
2184 stream3
->SetDelegate(&delegate3
);
2185 scoped_ptr
<SpdyHeaderBlock
> headers3(
2186 spdy_util_
.ConstructGetHeaderBlock(url3
.spec()));
2187 stream3
->SendRequestHeaders(headers3
.Pass(), NO_MORE_DATA_TO_SEND
);
2188 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
2190 // Run until 2nd stream is activated and then closed.
2191 EXPECT_EQ(0u, delegate3
.stream_id());
2193 EXPECT_EQ(NULL
, stream3
.get());
2194 EXPECT_EQ(5u, delegate3
.stream_id());
2196 EXPECT_EQ(0u, session
->num_active_streams());
2197 EXPECT_EQ(0u, session
->num_created_streams());
2198 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2203 TEST_P(SpdySessionTest
, CancelTwoStalledCreateStream
) {
2204 session_deps_
.host_resolver
->set_synchronous_mode(true);
2206 MockRead reads
[] = {
2207 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2210 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
2211 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2213 data
.set_connect_data(connect_data
);
2214 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2216 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2217 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2219 CreateNetworkSession();
2221 base::WeakPtr
<SpdySession
> session
=
2222 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2224 // Leave room for only one more stream to be created.
2225 for (size_t i
= 0; i
< kInitialMaxConcurrentStreams
- 1; ++i
) {
2226 base::WeakPtr
<SpdyStream
> spdy_stream
=
2227 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2228 session
, test_url_
, MEDIUM
, BoundNetLog());
2229 ASSERT_TRUE(spdy_stream
!= NULL
);
2232 GURL
url1("http://www.google.com");
2233 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2234 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
2235 session
, url1
, LOWEST
, BoundNetLog());
2236 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2237 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2239 TestCompletionCallback callback2
;
2240 GURL
url2("http://www.google.com");
2241 SpdyStreamRequest request2
;
2242 ASSERT_EQ(ERR_IO_PENDING
,
2243 request2
.StartRequest(
2244 SPDY_BIDIRECTIONAL_STREAM
, session
, url2
, LOWEST
, BoundNetLog(),
2245 callback2
.callback()));
2247 TestCompletionCallback callback3
;
2248 GURL
url3("http://www.google.com");
2249 SpdyStreamRequest request3
;
2250 ASSERT_EQ(ERR_IO_PENDING
,
2251 request3
.StartRequest(
2252 SPDY_BIDIRECTIONAL_STREAM
, session
, url3
, LOWEST
, BoundNetLog(),
2253 callback3
.callback()));
2255 EXPECT_EQ(0u, session
->num_active_streams());
2256 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2257 EXPECT_EQ(2u, session
->pending_create_stream_queue_size(LOWEST
));
2259 // Cancel the first stream; this will allow the second stream to be created.
2260 EXPECT_TRUE(spdy_stream1
.get() != NULL
);
2261 spdy_stream1
->Cancel();
2262 EXPECT_EQ(NULL
, spdy_stream1
.get());
2264 EXPECT_EQ(OK
, callback2
.WaitForResult());
2265 EXPECT_EQ(0u, session
->num_active_streams());
2266 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2267 EXPECT_EQ(1u, session
->pending_create_stream_queue_size(LOWEST
));
2269 // Cancel the second stream; this will allow the third stream to be created.
2270 base::WeakPtr
<SpdyStream
> spdy_stream2
= request2
.ReleaseStream();
2271 spdy_stream2
->Cancel();
2272 EXPECT_EQ(NULL
, spdy_stream2
.get());
2274 EXPECT_EQ(OK
, callback3
.WaitForResult());
2275 EXPECT_EQ(0u, session
->num_active_streams());
2276 EXPECT_EQ(kInitialMaxConcurrentStreams
, session
->num_created_streams());
2277 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2279 // Cancel the third stream.
2280 base::WeakPtr
<SpdyStream
> spdy_stream3
= request3
.ReleaseStream();
2281 spdy_stream3
->Cancel();
2282 EXPECT_EQ(NULL
, spdy_stream3
.get());
2283 EXPECT_EQ(0u, session
->num_active_streams());
2284 EXPECT_EQ(kInitialMaxConcurrentStreams
- 1, session
->num_created_streams());
2285 EXPECT_EQ(0u, session
->pending_create_stream_queue_size(LOWEST
));
2288 // Test that SpdySession::DoReadLoop reads data from the socket
2289 // without yielding. This test makes 32k - 1 bytes of data available
2290 // on the socket for reading. It then verifies that it has read all
2291 // the available data without yielding.
2292 TEST_P(SpdySessionTest
, ReadDataWithoutYielding
) {
2293 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2294 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2296 scoped_ptr
<SpdyFrame
> req1(
2297 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2298 MockWrite writes
[] = {
2299 CreateMockWrite(*req1
, 0),
2302 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2303 // (-spdy_data_frame_size).
2304 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2305 const int kPayloadSize
=
2306 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2307 TestDataStream test_stream
;
2308 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
2309 char* payload_data
= payload
->data();
2310 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2312 scoped_ptr
<SpdyFrame
> partial_data_frame(
2313 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2314 scoped_ptr
<SpdyFrame
> finish_data_frame(
2315 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
- 1, DATA_FLAG_FIN
));
2317 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2319 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2321 MockRead reads
[] = {
2322 CreateMockRead(*resp1
, 1),
2323 CreateMockRead(*partial_data_frame
, 2),
2324 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2325 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2326 CreateMockRead(*finish_data_frame
, 5, SYNCHRONOUS
),
2327 MockRead(ASYNC
, 0, 6) // EOF
2330 // Create SpdySession and SpdyStream and send the request.
2331 DeterministicSocketData
data(reads
, arraysize(reads
),
2332 writes
, arraysize(writes
));
2333 data
.set_connect_data(connect_data
);
2334 session_deps_
.host_resolver
->set_synchronous_mode(true);
2335 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2337 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2338 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2340 CreateDeterministicNetworkSession();
2342 base::WeakPtr
<SpdySession
> session
=
2343 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2345 GURL
url1("http://www.google.com");
2346 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2347 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2348 session
, url1
, MEDIUM
, BoundNetLog());
2349 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2350 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2351 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2352 spdy_stream1
->SetDelegate(&delegate1
);
2354 scoped_ptr
<SpdyHeaderBlock
> headers1(
2355 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2356 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2357 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2359 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2361 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2363 // Run until 1st read.
2364 EXPECT_EQ(0u, delegate1
.stream_id());
2366 EXPECT_EQ(1u, delegate1
.stream_id());
2367 EXPECT_EQ(0u, observer
.executed_count());
2369 // Read all the data and verify SpdySession::DoReadLoop has not
2372 EXPECT_EQ(NULL
, spdy_stream1
.get());
2374 // Verify task observer's executed_count is zero, which indicates DoRead read
2375 // all the available data.
2376 EXPECT_EQ(0u, observer
.executed_count());
2377 EXPECT_TRUE(data
.at_write_eof());
2378 EXPECT_TRUE(data
.at_read_eof());
2381 // Test that SpdySession::DoReadLoop yields while reading the
2382 // data. This test makes 32k + 1 bytes of data available on the socket
2383 // for reading. It then verifies that DoRead has yielded even though
2384 // there is data available for it to read (i.e, socket()->Read didn't
2385 // return ERR_IO_PENDING during socket reads).
2386 TEST_P(SpdySessionTest
, TestYieldingDuringReadData
) {
2387 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2388 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2390 scoped_ptr
<SpdyFrame
> req1(
2391 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2392 MockWrite writes
[] = {
2393 CreateMockWrite(*req1
, 0),
2396 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2397 // (-spdy_data_frame_size).
2398 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2399 const int kPayloadSize
=
2400 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2401 TestDataStream test_stream
;
2402 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
2403 char* payload_data
= payload
->data();
2404 test_stream
.GetBytes(payload_data
, kPayloadSize
);
2406 scoped_ptr
<SpdyFrame
> partial_data_frame(
2407 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
2408 scoped_ptr
<SpdyFrame
> finish_data_frame(
2409 framer
.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN
));
2411 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2413 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2414 MockRead reads
[] = {
2415 CreateMockRead(*resp1
, 1),
2416 CreateMockRead(*partial_data_frame
, 2),
2417 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
2418 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
2419 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
2420 CreateMockRead(*finish_data_frame
, 6, SYNCHRONOUS
),
2421 MockRead(ASYNC
, 0, 7) // EOF
2424 // Create SpdySession and SpdyStream and send the request.
2425 DeterministicSocketData
data(reads
, arraysize(reads
),
2426 writes
, arraysize(writes
));
2427 data
.set_connect_data(connect_data
);
2428 session_deps_
.host_resolver
->set_synchronous_mode(true);
2429 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2431 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2432 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2434 CreateDeterministicNetworkSession();
2436 base::WeakPtr
<SpdySession
> session
=
2437 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2439 GURL
url1("http://www.google.com");
2440 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2441 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2442 session
, url1
, MEDIUM
, BoundNetLog());
2443 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2444 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2445 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2446 spdy_stream1
->SetDelegate(&delegate1
);
2448 scoped_ptr
<SpdyHeaderBlock
> headers1(
2449 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2450 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2451 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2453 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2455 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2457 // Run until 1st read.
2458 EXPECT_EQ(0u, delegate1
.stream_id());
2460 EXPECT_EQ(1u, delegate1
.stream_id());
2461 EXPECT_EQ(0u, observer
.executed_count());
2463 // Read all the data and verify SpdySession::DoReadLoop has posted a
2466 EXPECT_EQ(NULL
, spdy_stream1
.get());
2468 // Verify task observer's executed_count is 1, which indicates DoRead has
2469 // posted only one task and thus yielded though there is data available for it
2471 EXPECT_EQ(1u, observer
.executed_count());
2472 EXPECT_TRUE(data
.at_write_eof());
2473 EXPECT_TRUE(data
.at_read_eof());
2476 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2477 // + async, by doing the following MockReads.
2479 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2480 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2482 // The above reads 26K synchronously. Since that is less that 32K, we
2483 // will attempt to read again. However, that DoRead() will return
2484 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2485 // yield. When we come back, DoRead() will read the results from the
2486 // async read, and rest of the data synchronously.
2487 TEST_P(SpdySessionTest
, TestYieldingDuringAsyncReadData
) {
2488 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2489 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2491 scoped_ptr
<SpdyFrame
> req1(
2492 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2493 MockWrite writes
[] = {
2494 CreateMockWrite(*req1
, 0),
2497 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2498 // (-spdy_data_frame_size).
2499 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding
);
2500 TestDataStream test_stream
;
2501 const int kEightKPayloadSize
=
2502 kMaxReadBytesWithoutYielding
/ 4 - framer
.GetControlFrameHeaderSize();
2503 scoped_refptr
<net::IOBuffer
> eightk_payload(
2504 new net::IOBuffer(kEightKPayloadSize
));
2505 char* eightk_payload_data
= eightk_payload
->data();
2506 test_stream
.GetBytes(eightk_payload_data
, kEightKPayloadSize
);
2508 // Build buffer of 2k size.
2509 TestDataStream test_stream2
;
2510 const int kTwoKPayloadSize
= kEightKPayloadSize
- 6 * 1024;
2511 scoped_refptr
<net::IOBuffer
> twok_payload(
2512 new net::IOBuffer(kTwoKPayloadSize
));
2513 char* twok_payload_data
= twok_payload
->data();
2514 test_stream2
.GetBytes(twok_payload_data
, kTwoKPayloadSize
);
2516 scoped_ptr
<SpdyFrame
> eightk_data_frame(framer
.CreateDataFrame(
2517 1, eightk_payload_data
, kEightKPayloadSize
, DATA_FLAG_NONE
));
2518 scoped_ptr
<SpdyFrame
> twok_data_frame(framer
.CreateDataFrame(
2519 1, twok_payload_data
, kTwoKPayloadSize
, DATA_FLAG_NONE
));
2520 scoped_ptr
<SpdyFrame
> finish_data_frame(framer
.CreateDataFrame(
2521 1, "h", 1, DATA_FLAG_FIN
));
2523 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2525 MockRead reads
[] = {
2526 CreateMockRead(*resp1
, 1),
2527 CreateMockRead(*eightk_data_frame
, 2),
2528 CreateMockRead(*eightk_data_frame
, 3, SYNCHRONOUS
),
2529 CreateMockRead(*eightk_data_frame
, 4, SYNCHRONOUS
),
2530 CreateMockRead(*twok_data_frame
, 5, SYNCHRONOUS
),
2531 CreateMockRead(*eightk_data_frame
, 6, ASYNC
),
2532 CreateMockRead(*eightk_data_frame
, 7, SYNCHRONOUS
),
2533 CreateMockRead(*eightk_data_frame
, 8, SYNCHRONOUS
),
2534 CreateMockRead(*eightk_data_frame
, 9, SYNCHRONOUS
),
2535 CreateMockRead(*twok_data_frame
, 10, SYNCHRONOUS
),
2536 CreateMockRead(*finish_data_frame
, 11, SYNCHRONOUS
),
2537 MockRead(ASYNC
, 0, 12) // EOF
2540 // Create SpdySession and SpdyStream and send the request.
2541 DeterministicSocketData
data(reads
, arraysize(reads
),
2542 writes
, arraysize(writes
));
2543 data
.set_connect_data(connect_data
);
2544 session_deps_
.host_resolver
->set_synchronous_mode(true);
2545 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2547 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2548 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2550 CreateDeterministicNetworkSession();
2552 base::WeakPtr
<SpdySession
> session
=
2553 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2555 GURL
url1("http://www.google.com");
2556 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2557 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2558 session
, url1
, MEDIUM
, BoundNetLog());
2559 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2560 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2561 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2562 spdy_stream1
->SetDelegate(&delegate1
);
2564 scoped_ptr
<SpdyHeaderBlock
> headers1(
2565 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2566 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2567 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2569 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2570 // posting of tasks.
2571 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoReadLoop");
2573 // Run until 1st read.
2574 EXPECT_EQ(0u, delegate1
.stream_id());
2576 EXPECT_EQ(1u, delegate1
.stream_id());
2577 EXPECT_EQ(0u, observer
.executed_count());
2579 // Read all the data and verify SpdySession::DoReadLoop has posted a
2582 EXPECT_EQ(NULL
, spdy_stream1
.get());
2584 // Verify task observer's executed_count is 1, which indicates DoRead has
2585 // posted only one task and thus yielded though there is data available for
2587 EXPECT_EQ(1u, observer
.executed_count());
2588 EXPECT_TRUE(data
.at_write_eof());
2589 EXPECT_TRUE(data
.at_read_eof());
2592 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2593 // nothing blows up.
2594 TEST_P(SpdySessionTest
, GoAwayWhileInDoReadLoop
) {
2595 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2596 BufferedSpdyFramer
framer(spdy_util_
.spdy_version(), false);
2598 scoped_ptr
<SpdyFrame
> req1(
2599 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2600 MockWrite writes
[] = {
2601 CreateMockWrite(*req1
, 0),
2604 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2605 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2606 scoped_ptr
<SpdyFrame
> goaway(spdy_util_
.ConstructSpdyGoAway());
2608 MockRead reads
[] = {
2609 CreateMockRead(*resp1
, 1),
2610 CreateMockRead(*body1
, 2),
2611 CreateMockRead(*goaway
, 3),
2614 // Create SpdySession and SpdyStream and send the request.
2615 DeterministicSocketData
data(reads
, arraysize(reads
),
2616 writes
, arraysize(writes
));
2617 data
.set_connect_data(connect_data
);
2618 session_deps_
.host_resolver
->set_synchronous_mode(true);
2619 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
2621 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
2622 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
2624 CreateDeterministicNetworkSession();
2626 base::WeakPtr
<SpdySession
> session
=
2627 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
2629 GURL
url1("http://www.google.com");
2630 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2631 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2632 session
, url1
, MEDIUM
, BoundNetLog());
2633 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2634 spdy_stream1
->SetDelegate(&delegate1
);
2635 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
2636 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2638 scoped_ptr
<SpdyHeaderBlock
> headers1(
2639 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2640 spdy_stream1
->SendRequestHeaders(headers1
.Pass(), NO_MORE_DATA_TO_SEND
);
2641 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2643 // Run until 1st read.
2644 EXPECT_EQ(0u, spdy_stream1
->stream_id());
2646 EXPECT_EQ(1u, spdy_stream1
->stream_id());
2648 // Run until GoAway.
2650 EXPECT_EQ(NULL
, spdy_stream1
.get());
2651 EXPECT_TRUE(data
.at_write_eof());
2652 EXPECT_TRUE(data
.at_read_eof());
2653 EXPECT_TRUE(session
== NULL
);
2656 // Within this framework, a SpdySession should be initialized with
2657 // flow control disabled for protocol version 2, with flow control
2658 // enabled only for streams for protocol version 3, and with flow
2659 // control enabled for streams and sessions for higher versions.
2660 TEST_P(SpdySessionTest
, ProtocolNegotiation
) {
2661 session_deps_
.host_resolver
->set_synchronous_mode(true);
2663 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2664 MockRead reads
[] = {
2665 MockRead(SYNCHRONOUS
, 0, 0) // EOF
2667 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
2668 data
.set_connect_data(connect_data
);
2669 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2671 CreateNetworkSession();
2672 base::WeakPtr
<SpdySession
> session
=
2673 CreateFakeSpdySession(spdy_session_pool_
, key_
);
2675 EXPECT_EQ(spdy_util_
.spdy_version(),
2676 session
->buffered_spdy_framer_
->protocol_version());
2677 if (GetParam() == kProtoDeprecatedSPDY2
) {
2678 EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE
, session
->flow_control_state());
2679 EXPECT_EQ(0, session
->session_send_window_size_
);
2680 EXPECT_EQ(0, session
->session_recv_window_size_
);
2681 } else if (GetParam() == kProtoSPDY3
) {
2682 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM
, session
->flow_control_state());
2683 EXPECT_EQ(0, session
->session_send_window_size_
);
2684 EXPECT_EQ(0, session
->session_recv_window_size_
);
2686 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
2687 session
->flow_control_state());
2688 EXPECT_EQ(kSpdySessionInitialWindowSize
,
2689 session
->session_send_window_size_
);
2690 EXPECT_EQ(kSpdySessionInitialWindowSize
,
2691 session
->session_recv_window_size_
);
2693 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
2696 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2697 // pointers to the idle session are currently held.
2698 TEST_P(SpdySessionTest
, CloseOneIdleConnection
) {
2699 ClientSocketPoolManager::set_max_sockets_per_group(
2700 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2701 ClientSocketPoolManager::set_max_sockets_per_pool(
2702 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2704 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2705 MockRead reads
[] = {
2706 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2708 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
2709 data
.set_connect_data(connect_data
);
2710 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2711 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2713 CreateNetworkSession();
2715 TransportClientSocketPool
* pool
=
2716 http_session_
->GetTransportSocketPool(
2717 HttpNetworkSession::NORMAL_SOCKET_POOL
);
2719 // Create an idle SPDY session.
2720 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2721 kPrivacyModeDisabled
);
2722 base::WeakPtr
<SpdySession
> session1
=
2723 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
2724 EXPECT_FALSE(pool
->IsStalled());
2726 // Trying to create a new connection should cause the pool to be stalled, and
2727 // post a task asynchronously to try and close the session.
2728 TestCompletionCallback callback2
;
2729 HostPortPair
host_port2("2.com", 80);
2730 scoped_refptr
<TransportSocketParams
> params2(
2731 new TransportSocketParams(host_port2
, false, false,
2732 OnHostResolutionCallback()));
2733 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
2734 EXPECT_EQ(ERR_IO_PENDING
,
2735 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
2736 callback2
.callback(), pool
, BoundNetLog()));
2737 EXPECT_TRUE(pool
->IsStalled());
2739 // The socket pool should close the connection asynchronously and establish a
2741 EXPECT_EQ(OK
, callback2
.WaitForResult());
2742 EXPECT_FALSE(pool
->IsStalled());
2743 EXPECT_TRUE(session1
== NULL
);
2746 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2747 // pointers to the idle session are currently held, in the case the SPDY session
2749 TEST_P(SpdySessionTest
, CloseOneIdleConnectionWithAlias
) {
2750 ClientSocketPoolManager::set_max_sockets_per_group(
2751 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2752 ClientSocketPoolManager::set_max_sockets_per_pool(
2753 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2755 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2756 MockRead reads
[] = {
2757 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2759 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
2760 data
.set_connect_data(connect_data
);
2761 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2762 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2764 session_deps_
.host_resolver
->set_synchronous_mode(true);
2765 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
2766 "1.com", "192.168.0.2", std::string());
2767 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
2768 "2.com", "192.168.0.2", std::string());
2769 // Not strictly needed.
2770 session_deps_
.host_resolver
->rules()->AddIPLiteralRule(
2771 "3.com", "192.168.0.3", std::string());
2773 CreateNetworkSession();
2775 TransportClientSocketPool
* pool
=
2776 http_session_
->GetTransportSocketPool(
2777 HttpNetworkSession::NORMAL_SOCKET_POOL
);
2779 // Create an idle SPDY session.
2780 SpdySessionKey
key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2781 kPrivacyModeDisabled
);
2782 base::WeakPtr
<SpdySession
> session1
=
2783 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
2784 EXPECT_FALSE(pool
->IsStalled());
2786 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
2787 SpdySessionKey
key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
2788 kPrivacyModeDisabled
);
2789 HostResolver::RequestInfo
info(key2
.host_port_pair());
2790 AddressList addresses
;
2791 // Pre-populate the DNS cache, since a synchronous resolution is required in
2792 // order to create the alias.
2793 session_deps_
.host_resolver
->Resolve(info
,
2796 CompletionCallback(),
2799 // Get a session for |key2|, which should return the session created earlier.
2800 base::WeakPtr
<SpdySession
> session2
=
2801 spdy_session_pool_
->FindAvailableSession(key2
, BoundNetLog());
2802 ASSERT_EQ(session1
.get(), session2
.get());
2803 EXPECT_FALSE(pool
->IsStalled());
2805 // Trying to create a new connection should cause the pool to be stalled, and
2806 // post a task asynchronously to try and close the session.
2807 TestCompletionCallback callback3
;
2808 HostPortPair
host_port3("3.com", 80);
2809 scoped_refptr
<TransportSocketParams
> params3(
2810 new TransportSocketParams(host_port3
, false, false,
2811 OnHostResolutionCallback()));
2812 scoped_ptr
<ClientSocketHandle
> connection3(new ClientSocketHandle
);
2813 EXPECT_EQ(ERR_IO_PENDING
,
2814 connection3
->Init(host_port3
.ToString(), params3
, DEFAULT_PRIORITY
,
2815 callback3
.callback(), pool
, BoundNetLog()));
2816 EXPECT_TRUE(pool
->IsStalled());
2818 // The socket pool should close the connection asynchronously and establish a
2820 EXPECT_EQ(OK
, callback3
.WaitForResult());
2821 EXPECT_FALSE(pool
->IsStalled());
2822 EXPECT_TRUE(session1
== NULL
);
2823 EXPECT_TRUE(session2
== NULL
);
2826 // Tests that when a SPDY session becomes idle, it closes itself if there is
2827 // a lower layer pool stalled on the per-pool socket limit.
2828 TEST_P(SpdySessionTest
, CloseSessionOnIdleWhenPoolStalled
) {
2829 ClientSocketPoolManager::set_max_sockets_per_group(
2830 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2831 ClientSocketPoolManager::set_max_sockets_per_pool(
2832 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
2834 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2835 MockRead reads
[] = {
2836 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2838 scoped_ptr
<SpdyFrame
> req1(
2839 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
2840 scoped_ptr
<SpdyFrame
> cancel1(
2841 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
2842 MockWrite writes
[] = {
2843 CreateMockWrite(*req1
, 1),
2844 CreateMockWrite(*cancel1
, 1),
2846 StaticSocketDataProvider
data(reads
, arraysize(reads
),
2847 writes
, arraysize(writes
));
2848 data
.set_connect_data(connect_data
);
2849 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2851 MockRead http_reads
[] = {
2852 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
2854 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
2856 http_data
.set_connect_data(connect_data
);
2857 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
2860 CreateNetworkSession();
2862 TransportClientSocketPool
* pool
=
2863 http_session_
->GetTransportSocketPool(
2864 HttpNetworkSession::NORMAL_SOCKET_POOL
);
2866 // Create a SPDY session.
2867 GURL
url1("http://www.google.com");
2868 SpdySessionKey
key1(HostPortPair(url1
.host(), 80),
2869 ProxyServer::Direct(), kPrivacyModeDisabled
);
2870 base::WeakPtr
<SpdySession
> session1
=
2871 CreateInsecureSpdySession(http_session_
, key1
, BoundNetLog());
2872 EXPECT_FALSE(pool
->IsStalled());
2874 // Create a stream using the session, and send a request.
2876 TestCompletionCallback callback1
;
2877 base::WeakPtr
<SpdyStream
> spdy_stream1
=
2878 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2879 session1
, url1
, DEFAULT_PRIORITY
,
2881 ASSERT_TRUE(spdy_stream1
.get());
2882 test::StreamDelegateDoNothing
delegate1(spdy_stream1
);
2883 spdy_stream1
->SetDelegate(&delegate1
);
2885 scoped_ptr
<SpdyHeaderBlock
> headers1(
2886 spdy_util_
.ConstructGetHeaderBlock(url1
.spec()));
2887 EXPECT_EQ(ERR_IO_PENDING
,
2888 spdy_stream1
->SendRequestHeaders(
2889 headers1
.Pass(), NO_MORE_DATA_TO_SEND
));
2890 EXPECT_TRUE(spdy_stream1
->HasUrlFromHeaders());
2892 base::MessageLoop::current()->RunUntilIdle();
2894 // Trying to create a new connection should cause the pool to be stalled, and
2895 // post a task asynchronously to try and close the session.
2896 TestCompletionCallback callback2
;
2897 HostPortPair
host_port2("2.com", 80);
2898 scoped_refptr
<TransportSocketParams
> params2(
2899 new TransportSocketParams(host_port2
, false, false,
2900 OnHostResolutionCallback()));
2901 scoped_ptr
<ClientSocketHandle
> connection2(new ClientSocketHandle
);
2902 EXPECT_EQ(ERR_IO_PENDING
,
2903 connection2
->Init(host_port2
.ToString(), params2
, DEFAULT_PRIORITY
,
2904 callback2
.callback(), pool
, BoundNetLog()));
2905 EXPECT_TRUE(pool
->IsStalled());
2907 // Running the message loop should cause the socket pool to ask the SPDY
2908 // session to close an idle socket, but since the socket is in use, nothing
2910 base::RunLoop().RunUntilIdle();
2911 EXPECT_TRUE(pool
->IsStalled());
2912 EXPECT_FALSE(callback2
.have_result());
2914 // Cancelling the request should result in the session's socket being
2915 // closed, since the pool is stalled.
2916 ASSERT_TRUE(spdy_stream1
.get());
2917 spdy_stream1
->Cancel();
2918 base::RunLoop().RunUntilIdle();
2919 ASSERT_FALSE(pool
->IsStalled());
2920 EXPECT_EQ(OK
, callback2
.WaitForResult());
2923 // Verify that SpdySessionKey and therefore SpdySession is different when
2924 // privacy mode is enabled or disabled.
2925 TEST_P(SpdySessionTest
, SpdySessionKeyPrivacyMode
) {
2926 CreateDeterministicNetworkSession();
2928 HostPortPair
host_port_pair("www.google.com", 443);
2929 SpdySessionKey
key_privacy_enabled(host_port_pair
, ProxyServer::Direct(),
2930 kPrivacyModeEnabled
);
2931 SpdySessionKey
key_privacy_disabled(host_port_pair
, ProxyServer::Direct(),
2932 kPrivacyModeDisabled
);
2934 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
2935 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
2937 // Add SpdySession with PrivacyMode Enabled to the pool.
2938 base::WeakPtr
<SpdySession
> session_privacy_enabled
=
2939 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_enabled
);
2941 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
2942 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
2944 // Add SpdySession with PrivacyMode Disabled to the pool.
2945 base::WeakPtr
<SpdySession
> session_privacy_disabled
=
2946 CreateFakeSpdySession(spdy_session_pool_
, key_privacy_disabled
);
2948 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
2949 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
2951 session_privacy_enabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
2952 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
2953 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
2955 session_privacy_disabled
->CloseSessionOnError(ERR_ABORTED
, std::string());
2956 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_enabled
));
2957 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_privacy_disabled
));
2960 // Delegate that creates another stream when its stream is closed.
2961 class StreamCreatingDelegate
: public test::StreamDelegateDoNothing
{
2963 StreamCreatingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
2964 const base::WeakPtr
<SpdySession
>& session
)
2965 : StreamDelegateDoNothing(stream
),
2966 session_(session
) {}
2968 virtual ~StreamCreatingDelegate() {}
2970 virtual void OnClose(int status
) OVERRIDE
{
2971 GURL
url("http://www.google.com");
2973 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
2974 session_
, url
, MEDIUM
, BoundNetLog()));
2978 const base::WeakPtr
<SpdySession
> session_
;
2981 // Create another stream in response to a stream being reset. Nothing
2982 // should blow up. This is a regression test for
2983 // http://crbug.com/263690 .
2984 TEST_P(SpdySessionTest
, CreateStreamOnStreamReset
) {
2985 session_deps_
.host_resolver
->set_synchronous_mode(true);
2987 MockConnect
connect_data(SYNCHRONOUS
, OK
);
2989 scoped_ptr
<SpdyFrame
> req(
2990 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
, true));
2991 MockWrite writes
[] = {
2992 CreateMockWrite(*req
, 0),
2995 scoped_ptr
<SpdyFrame
> rst(
2996 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM
));
2997 MockRead reads
[] = {
2998 CreateMockRead(*rst
, 1),
2999 MockRead(ASYNC
, 0, 2) // EOF
3001 DeterministicSocketData
data(reads
, arraysize(reads
),
3002 writes
, arraysize(writes
));
3003 data
.set_connect_data(connect_data
);
3004 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3006 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
3007 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3009 CreateDeterministicNetworkSession();
3011 base::WeakPtr
<SpdySession
> session
=
3012 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3014 GURL
url("http://www.google.com");
3015 base::WeakPtr
<SpdyStream
> spdy_stream
=
3016 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3017 session
, url
, MEDIUM
, BoundNetLog());
3018 ASSERT_TRUE(spdy_stream
.get() != NULL
);
3019 EXPECT_EQ(0u, spdy_stream
->stream_id());
3021 StreamCreatingDelegate
delegate(spdy_stream
, session
);
3022 spdy_stream
->SetDelegate(&delegate
);
3024 scoped_ptr
<SpdyHeaderBlock
> headers(
3025 spdy_util_
.ConstructGetHeaderBlock(url
.spec()));
3026 spdy_stream
->SendRequestHeaders(headers
.Pass(), NO_MORE_DATA_TO_SEND
);
3027 EXPECT_TRUE(spdy_stream
->HasUrlFromHeaders());
3029 EXPECT_EQ(0u, spdy_stream
->stream_id());
3033 EXPECT_EQ(1u, spdy_stream
->stream_id());
3035 // Cause the stream to be reset, which should cause another stream
3039 EXPECT_EQ(NULL
, spdy_stream
.get());
3040 EXPECT_TRUE(delegate
.StreamIsClosed());
3041 EXPECT_EQ(0u, session
->num_active_streams());
3042 EXPECT_EQ(1u, session
->num_created_streams());
3045 // The tests below are only for SPDY/3 and above.
3047 TEST_P(SpdySessionTest
, UpdateStreamsSendWindowSize
) {
3048 if (GetParam() < kProtoSPDY3
)
3051 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3053 SettingsMap new_settings
;
3054 int32 window_size
= 1;
3055 new_settings
[SETTINGS_INITIAL_WINDOW_SIZE
] =
3056 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, window_size
);
3058 // Set up the socket so we read a SETTINGS frame that sets
3059 // INITIAL_WINDOW_SIZE.
3060 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3061 scoped_ptr
<SpdyFrame
> settings_frame(
3062 spdy_util_
.ConstructSpdySettings(new_settings
));
3063 MockRead reads
[] = {
3064 CreateMockRead(*settings_frame
, 0),
3065 MockRead(ASYNC
, 0, 1) // EOF
3068 session_deps_
.host_resolver
->set_synchronous_mode(true);
3070 scoped_ptr
<DeterministicSocketData
> data(
3071 new DeterministicSocketData(reads
, arraysize(reads
), NULL
, 0));
3072 data
->set_connect_data(connect_data
);
3073 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(data
.get());
3075 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
3076 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3078 CreateDeterministicNetworkSession();
3080 base::WeakPtr
<SpdySession
> session
=
3081 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3082 base::WeakPtr
<SpdyStream
> spdy_stream1
=
3083 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3084 session
, test_url_
, MEDIUM
, BoundNetLog());
3085 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
3086 TestCompletionCallback callback1
;
3087 EXPECT_NE(spdy_stream1
->send_window_size(), window_size
);
3089 data
->RunFor(1); // Process the SETTINGS frame, but not the EOF
3090 base::MessageLoop::current()->RunUntilIdle();
3091 EXPECT_EQ(session
->stream_initial_send_window_size(), window_size
);
3092 EXPECT_EQ(spdy_stream1
->send_window_size(), window_size
);
3094 // Release the first one, this will allow the second to be created.
3095 spdy_stream1
->Cancel();
3096 EXPECT_EQ(NULL
, spdy_stream1
.get());
3098 base::WeakPtr
<SpdyStream
> spdy_stream2
=
3099 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3100 session
, test_url_
, MEDIUM
, BoundNetLog());
3101 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
3102 EXPECT_EQ(spdy_stream2
->send_window_size(), window_size
);
3103 spdy_stream2
->Cancel();
3104 EXPECT_EQ(NULL
, spdy_stream2
.get());
3107 // The tests below are only for SPDY/3.1 and above.
3109 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3110 // adjust the session receive window size for SPDY 3.1 and higher. In
3111 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3112 // sending a WINDOW_UPDATE frame for a large enough delta.
3113 TEST_P(SpdySessionTest
, AdjustRecvWindowSize
) {
3114 if (GetParam() < kProtoSPDY31
)
3117 session_deps_
.host_resolver
->set_synchronous_mode(true);
3119 const int32 delta_window_size
= 100;
3121 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3122 MockRead reads
[] = {
3123 MockRead(ASYNC
, 0, 1) // EOF
3125 scoped_ptr
<SpdyFrame
> window_update(
3126 spdy_util_
.ConstructSpdyWindowUpdate(
3127 kSessionFlowControlStreamId
,
3128 kSpdySessionInitialWindowSize
+ delta_window_size
));
3129 MockWrite writes
[] = {
3130 CreateMockWrite(*window_update
, 0),
3132 DeterministicSocketData
data(reads
, arraysize(reads
),
3133 writes
, arraysize(writes
));
3134 data
.set_connect_data(connect_data
);
3135 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3137 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
3138 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3140 CreateDeterministicNetworkSession();
3141 base::WeakPtr
<SpdySession
> session
=
3142 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3143 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3144 session
->flow_control_state());
3146 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3147 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3149 session
->IncreaseRecvWindowSize(delta_window_size
);
3150 EXPECT_EQ(kSpdySessionInitialWindowSize
+ delta_window_size
,
3151 session
->session_recv_window_size_
);
3152 EXPECT_EQ(delta_window_size
, session
->session_unacked_recv_window_bytes_
);
3154 // Should trigger sending a WINDOW_UPDATE frame.
3155 session
->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize
);
3156 EXPECT_EQ(kSpdySessionInitialWindowSize
+ delta_window_size
+
3157 kSpdySessionInitialWindowSize
,
3158 session
->session_recv_window_size_
);
3159 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3163 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3164 session
->in_io_loop_
= true;
3165 session
->DecreaseRecvWindowSize(
3166 kSpdySessionInitialWindowSize
+ delta_window_size
+
3167 kSpdySessionInitialWindowSize
);
3168 session
->in_io_loop_
= false;
3169 EXPECT_EQ(0, session
->session_recv_window_size_
);
3170 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3173 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3174 // adjust the session send window size when the "enable_spdy_31" flag
3176 TEST_P(SpdySessionTest
, AdjustSendWindowSize
) {
3177 if (GetParam() < kProtoSPDY31
)
3180 session_deps_
.host_resolver
->set_synchronous_mode(true);
3182 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3183 MockRead reads
[] = {
3184 MockRead(SYNCHRONOUS
, 0, 0) // EOF
3186 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
3187 data
.set_connect_data(connect_data
);
3188 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3190 CreateNetworkSession();
3191 base::WeakPtr
<SpdySession
> session
=
3192 CreateFakeSpdySession(spdy_session_pool_
, key_
);
3193 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3194 session
->flow_control_state());
3196 const int32 delta_window_size
= 100;
3198 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3200 session
->IncreaseSendWindowSize(delta_window_size
);
3201 EXPECT_EQ(kSpdySessionInitialWindowSize
+ delta_window_size
,
3202 session
->session_send_window_size_
);
3204 session
->DecreaseSendWindowSize(delta_window_size
);
3205 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3208 // Incoming data for an inactive stream should not cause the session
3209 // receive window size to decrease, but it should cause the unacked
3210 // bytes to increase.
3211 TEST_P(SpdySessionTest
, SessionFlowControlInactiveStream
) {
3212 if (GetParam() < kProtoSPDY31
)
3215 session_deps_
.host_resolver
->set_synchronous_mode(true);
3217 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3218 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyBodyFrame(1, false));
3219 MockRead reads
[] = {
3220 CreateMockRead(*resp
, 0),
3221 MockRead(ASYNC
, 0, 1) // EOF
3223 DeterministicSocketData
data(reads
, arraysize(reads
), NULL
, 0);
3224 data
.set_connect_data(connect_data
);
3225 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3227 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
3228 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3230 CreateDeterministicNetworkSession();
3231 base::WeakPtr
<SpdySession
> session
=
3232 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3233 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3234 session
->flow_control_state());
3236 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3237 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3241 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3242 EXPECT_EQ(kUploadDataSize
, session
->session_unacked_recv_window_bytes_
);
3247 // A delegate that drops any received data.
3248 class DropReceivedDataDelegate
: public test::StreamDelegateSendImmediate
{
3250 DropReceivedDataDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3251 base::StringPiece data
)
3252 : StreamDelegateSendImmediate(stream
, data
) {}
3254 virtual ~DropReceivedDataDelegate() {}
3256 // Drop any received data.
3257 virtual void OnDataReceived(scoped_ptr
<SpdyBuffer
> buffer
) OVERRIDE
{}
3260 // Send data back and forth but use a delegate that drops its received
3261 // data. The receive window should still increase to its original
3262 // value, i.e. we shouldn't "leak" receive window bytes.
3263 TEST_P(SpdySessionTest
, SessionFlowControlNoReceiveLeaks
) {
3264 if (GetParam() < kProtoSPDY31
)
3267 const char kStreamUrl
[] = "http://www.google.com/";
3269 const int32 msg_data_size
= 100;
3270 const std::string
msg_data(msg_data_size
, 'a');
3272 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3274 scoped_ptr
<SpdyFrame
> req(
3275 spdy_util_
.ConstructSpdyPost(
3276 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3277 scoped_ptr
<SpdyFrame
> msg(
3278 spdy_util_
.ConstructSpdyBodyFrame(
3279 1, msg_data
.data(), msg_data_size
, false));
3280 MockWrite writes
[] = {
3281 CreateMockWrite(*req
, 0),
3282 CreateMockWrite(*msg
, 2),
3285 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3286 scoped_ptr
<SpdyFrame
> echo(
3287 spdy_util_
.ConstructSpdyBodyFrame(
3288 1, msg_data
.data(), msg_data_size
, false));
3289 scoped_ptr
<SpdyFrame
> window_update(
3290 spdy_util_
.ConstructSpdyWindowUpdate(
3291 kSessionFlowControlStreamId
, msg_data_size
));
3292 MockRead reads
[] = {
3293 CreateMockRead(*resp
, 1),
3294 CreateMockRead(*echo
, 3),
3295 MockRead(ASYNC
, 0, 4) // EOF
3298 // Create SpdySession and SpdyStream and send the request.
3299 DeterministicSocketData
data(reads
, arraysize(reads
),
3300 writes
, arraysize(writes
));
3301 data
.set_connect_data(connect_data
);
3302 session_deps_
.host_resolver
->set_synchronous_mode(true);
3303 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3305 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
3306 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3308 CreateDeterministicNetworkSession();
3310 base::WeakPtr
<SpdySession
> session
=
3311 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3313 GURL
url(kStreamUrl
);
3314 base::WeakPtr
<SpdyStream
> stream
=
3315 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3316 session
, url
, MEDIUM
, BoundNetLog());
3317 ASSERT_TRUE(stream
.get() != NULL
);
3318 EXPECT_EQ(0u, stream
->stream_id());
3320 DropReceivedDataDelegate
delegate(stream
, msg_data
);
3321 stream
->SetDelegate(&delegate
);
3323 scoped_ptr
<SpdyHeaderBlock
> headers(
3324 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3325 EXPECT_EQ(ERR_IO_PENDING
,
3326 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3327 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3329 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3330 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3334 EXPECT_TRUE(data
.at_write_eof());
3335 EXPECT_TRUE(data
.at_read_eof());
3337 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3338 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3341 EXPECT_EQ(NULL
, stream
.get());
3343 EXPECT_EQ(OK
, delegate
.WaitForClose());
3345 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3346 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3349 // Send data back and forth but close the stream before its data frame
3350 // can be written to the socket. The send window should then increase
3351 // to its original value, i.e. we shouldn't "leak" send window bytes.
3352 TEST_P(SpdySessionTest
, SessionFlowControlNoSendLeaks
) {
3353 if (GetParam() < kProtoSPDY31
)
3356 const char kStreamUrl
[] = "http://www.google.com/";
3358 const int32 msg_data_size
= 100;
3359 const std::string
msg_data(msg_data_size
, 'a');
3361 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3363 scoped_ptr
<SpdyFrame
> req(
3364 spdy_util_
.ConstructSpdyPost(
3365 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3366 MockWrite writes
[] = {
3367 CreateMockWrite(*req
, 0),
3370 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3371 MockRead reads
[] = {
3372 CreateMockRead(*resp
, 1),
3373 MockRead(ASYNC
, 0, 2) // EOF
3376 // Create SpdySession and SpdyStream and send the request.
3377 DeterministicSocketData
data(reads
, arraysize(reads
),
3378 writes
, arraysize(writes
));
3379 data
.set_connect_data(connect_data
);
3380 session_deps_
.host_resolver
->set_synchronous_mode(true);
3381 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3383 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
3384 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3386 CreateDeterministicNetworkSession();
3388 base::WeakPtr
<SpdySession
> session
=
3389 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3391 GURL
url(kStreamUrl
);
3392 base::WeakPtr
<SpdyStream
> stream
=
3393 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3394 session
, url
, MEDIUM
, BoundNetLog());
3395 ASSERT_TRUE(stream
.get() != NULL
);
3396 EXPECT_EQ(0u, stream
->stream_id());
3398 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3399 stream
->SetDelegate(&delegate
);
3401 scoped_ptr
<SpdyHeaderBlock
> headers(
3402 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3403 EXPECT_EQ(ERR_IO_PENDING
,
3404 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3405 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3407 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3411 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3415 EXPECT_TRUE(data
.at_write_eof());
3416 EXPECT_TRUE(data
.at_read_eof());
3418 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3419 session
->session_send_window_size_
);
3421 // Closing the stream should increase the session's send window.
3423 EXPECT_EQ(NULL
, stream
.get());
3425 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3427 EXPECT_EQ(OK
, delegate
.WaitForClose());
3430 // Send data back and forth; the send and receive windows should
3431 // change appropriately.
3432 TEST_P(SpdySessionTest
, SessionFlowControlEndToEnd
) {
3433 if (GetParam() < kProtoSPDY31
)
3436 const char kStreamUrl
[] = "http://www.google.com/";
3438 const int32 msg_data_size
= 100;
3439 const std::string
msg_data(msg_data_size
, 'a');
3441 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3443 scoped_ptr
<SpdyFrame
> req(
3444 spdy_util_
.ConstructSpdyPost(
3445 kStreamUrl
, 1, msg_data_size
, MEDIUM
, NULL
, 0));
3446 scoped_ptr
<SpdyFrame
> msg(
3447 spdy_util_
.ConstructSpdyBodyFrame(
3448 1, msg_data
.data(), msg_data_size
, false));
3449 MockWrite writes
[] = {
3450 CreateMockWrite(*req
, 0),
3451 CreateMockWrite(*msg
, 2),
3454 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3455 scoped_ptr
<SpdyFrame
> echo(
3456 spdy_util_
.ConstructSpdyBodyFrame(
3457 1, msg_data
.data(), msg_data_size
, false));
3458 scoped_ptr
<SpdyFrame
> window_update(
3459 spdy_util_
.ConstructSpdyWindowUpdate(
3460 kSessionFlowControlStreamId
, msg_data_size
));
3461 MockRead reads
[] = {
3462 CreateMockRead(*resp
, 1),
3463 CreateMockRead(*echo
, 3),
3464 CreateMockRead(*window_update
, 4),
3465 MockRead(ASYNC
, 0, 5) // EOF
3468 // Create SpdySession and SpdyStream and send the request.
3469 DeterministicSocketData
data(reads
, arraysize(reads
),
3470 writes
, arraysize(writes
));
3471 data
.set_connect_data(connect_data
);
3472 session_deps_
.host_resolver
->set_synchronous_mode(true);
3473 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3475 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
3476 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3478 CreateDeterministicNetworkSession();
3480 base::WeakPtr
<SpdySession
> session
=
3481 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3483 GURL
url(kStreamUrl
);
3484 base::WeakPtr
<SpdyStream
> stream
=
3485 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM
,
3486 session
, url
, MEDIUM
, BoundNetLog());
3487 ASSERT_TRUE(stream
.get() != NULL
);
3488 EXPECT_EQ(0u, stream
->stream_id());
3490 test::StreamDelegateSendImmediate
delegate(stream
, msg_data
);
3491 stream
->SetDelegate(&delegate
);
3493 scoped_ptr
<SpdyHeaderBlock
> headers(
3494 spdy_util_
.ConstructPostHeaderBlock(url
.spec(), msg_data_size
));
3495 EXPECT_EQ(ERR_IO_PENDING
,
3496 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3497 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3499 EXPECT_EQ(kSpdySessionInitialWindowSize
, 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
, session
->session_send_window_size_
);
3506 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3507 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3511 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3512 session
->session_send_window_size_
);
3513 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3514 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3518 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3519 session
->session_send_window_size_
);
3520 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3521 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3525 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3526 session
->session_send_window_size_
);
3527 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3528 session
->session_recv_window_size_
);
3529 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3533 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3534 EXPECT_EQ(kSpdySessionInitialWindowSize
- msg_data_size
,
3535 session
->session_recv_window_size_
);
3536 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
3538 EXPECT_TRUE(data
.at_write_eof());
3539 EXPECT_TRUE(data
.at_read_eof());
3541 EXPECT_EQ(msg_data
, delegate
.TakeReceivedData());
3543 // Draining the delegate's read queue should increase the session's
3545 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3546 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3547 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3550 EXPECT_EQ(NULL
, stream
.get());
3552 EXPECT_EQ(OK
, delegate
.WaitForClose());
3554 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_send_window_size_
);
3555 EXPECT_EQ(kSpdySessionInitialWindowSize
, session
->session_recv_window_size_
);
3556 EXPECT_EQ(msg_data_size
, session
->session_unacked_recv_window_bytes_
);
3559 // Given a stall function and an unstall function, runs a test to make
3560 // sure that a stream resumes after unstall.
3561 void SpdySessionTest::RunResumeAfterUnstallTest(
3562 const base::Callback
<void(SpdySession
*, SpdyStream
*)>& stall_function
,
3563 const base::Callback
<void(SpdySession
*, SpdyStream
*, int32
)>&
3565 const char kStreamUrl
[] = "http://www.google.com/";
3566 GURL
url(kStreamUrl
);
3568 session_deps_
.host_resolver
->set_synchronous_mode(true);
3570 scoped_ptr
<SpdyFrame
> req(
3571 spdy_util_
.ConstructSpdyPost(
3572 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
3573 scoped_ptr
<SpdyFrame
> body(
3574 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
3575 MockWrite writes
[] = {
3576 CreateMockWrite(*req
, 0),
3577 CreateMockWrite(*body
, 1),
3580 scoped_ptr
<SpdyFrame
> resp(
3581 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3582 scoped_ptr
<SpdyFrame
> echo(
3583 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
3584 MockRead reads
[] = {
3585 CreateMockRead(*resp
, 2),
3586 MockRead(ASYNC
, 0, 0, 3), // EOF
3589 DeterministicSocketData
data(reads
, arraysize(reads
),
3590 writes
, arraysize(writes
));
3591 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3592 data
.set_connect_data(connect_data
);
3594 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3596 CreateDeterministicNetworkSession();
3597 base::WeakPtr
<SpdySession
> session
=
3598 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3599 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3600 session
->flow_control_state());
3602 base::WeakPtr
<SpdyStream
> stream
=
3603 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3604 session
, url
, LOWEST
, BoundNetLog());
3605 ASSERT_TRUE(stream
.get() != NULL
);
3607 test::StreamDelegateWithBody
delegate(stream
, kBodyDataStringPiece
);
3608 stream
->SetDelegate(&delegate
);
3610 EXPECT_FALSE(stream
->HasUrlFromHeaders());
3611 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
3613 scoped_ptr
<SpdyHeaderBlock
> headers(
3614 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
3615 EXPECT_EQ(ERR_IO_PENDING
,
3616 stream
->SendRequestHeaders(headers
.Pass(), MORE_DATA_TO_SEND
));
3617 EXPECT_TRUE(stream
->HasUrlFromHeaders());
3618 EXPECT_EQ(kStreamUrl
, stream
->GetUrlFromHeaders().spec());
3620 stall_function
.Run(session
.get(), stream
.get());
3624 EXPECT_TRUE(stream
->send_stalled_by_flow_control());
3626 unstall_function
.Run(session
.get(), stream
.get(), kBodyDataSize
);
3628 EXPECT_FALSE(stream
->send_stalled_by_flow_control());
3632 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
3634 EXPECT_TRUE(delegate
.send_headers_completed());
3635 EXPECT_EQ("200", delegate
.GetResponseHeaderValue(":status"));
3636 EXPECT_EQ("HTTP/1.1", delegate
.GetResponseHeaderValue(":version"));
3637 EXPECT_EQ(std::string(), delegate
.TakeReceivedData());
3638 EXPECT_TRUE(data
.at_write_eof());
3641 // Run the resume-after-unstall test with all possible stall and
3642 // unstall sequences.
3644 TEST_P(SpdySessionTest
, ResumeAfterUnstallSession
) {
3645 if (GetParam() < kProtoSPDY31
)
3648 RunResumeAfterUnstallTest(
3649 base::Bind(&SpdySessionTest::StallSessionOnly
,
3650 base::Unretained(this)),
3651 base::Bind(&SpdySessionTest::UnstallSessionOnly
,
3652 base::Unretained(this)));
3656 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
3657 TEST_P(SpdySessionTest
, ResumeAfterUnstallStream
) {
3658 if (GetParam() < kProtoSPDY31
)
3661 RunResumeAfterUnstallTest(
3662 base::Bind(&SpdySessionTest::StallStreamOnly
,
3663 base::Unretained(this)),
3664 base::Bind(&SpdySessionTest::UnstallStreamOnly
,
3665 base::Unretained(this)));
3668 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallSessionStream
) {
3669 if (GetParam() < kProtoSPDY31
)
3672 RunResumeAfterUnstallTest(
3673 base::Bind(&SpdySessionTest::StallSessionStream
,
3674 base::Unretained(this)),
3675 base::Bind(&SpdySessionTest::UnstallSessionStream
,
3676 base::Unretained(this)));
3679 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallSessionStream
) {
3680 if (GetParam() < kProtoSPDY31
)
3683 RunResumeAfterUnstallTest(
3684 base::Bind(&SpdySessionTest::StallStreamSession
,
3685 base::Unretained(this)),
3686 base::Bind(&SpdySessionTest::UnstallSessionStream
,
3687 base::Unretained(this)));
3690 TEST_P(SpdySessionTest
, StallStreamSessionResumeAfterUnstallStreamSession
) {
3691 if (GetParam() < kProtoSPDY31
)
3694 RunResumeAfterUnstallTest(
3695 base::Bind(&SpdySessionTest::StallStreamSession
,
3696 base::Unretained(this)),
3697 base::Bind(&SpdySessionTest::UnstallStreamSession
,
3698 base::Unretained(this)));
3701 TEST_P(SpdySessionTest
, StallSessionStreamResumeAfterUnstallStreamSession
) {
3702 if (GetParam() < kProtoSPDY31
)
3705 RunResumeAfterUnstallTest(
3706 base::Bind(&SpdySessionTest::StallSessionStream
,
3707 base::Unretained(this)),
3708 base::Bind(&SpdySessionTest::UnstallStreamSession
,
3709 base::Unretained(this)));
3712 // Cause a stall by reducing the flow control send window to 0. The
3713 // streams should resume in priority order when that window is then
3715 TEST_P(SpdySessionTest
, ResumeByPriorityAfterSendWindowSizeIncrease
) {
3716 if (GetParam() < kProtoSPDY31
)
3719 const char kStreamUrl
[] = "http://www.google.com/";
3720 GURL
url(kStreamUrl
);
3722 session_deps_
.host_resolver
->set_synchronous_mode(true);
3724 scoped_ptr
<SpdyFrame
> req1(
3725 spdy_util_
.ConstructSpdyPost(
3726 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
3727 scoped_ptr
<SpdyFrame
> req2(
3728 spdy_util_
.ConstructSpdyPost(
3729 kStreamUrl
, 3, kBodyDataSize
, MEDIUM
, NULL
, 0));
3730 scoped_ptr
<SpdyFrame
> body1(
3731 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, true));
3732 scoped_ptr
<SpdyFrame
> body2(
3733 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
3734 MockWrite writes
[] = {
3735 CreateMockWrite(*req1
, 0),
3736 CreateMockWrite(*req2
, 1),
3737 CreateMockWrite(*body2
, 2),
3738 CreateMockWrite(*body1
, 3),
3741 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3742 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3743 MockRead reads
[] = {
3744 CreateMockRead(*resp1
, 4),
3745 CreateMockRead(*resp2
, 5),
3746 MockRead(ASYNC
, 0, 0, 6), // EOF
3749 DeterministicSocketData
data(reads
, arraysize(reads
),
3750 writes
, arraysize(writes
));
3751 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3752 data
.set_connect_data(connect_data
);
3754 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3756 CreateDeterministicNetworkSession();
3757 base::WeakPtr
<SpdySession
> session
=
3758 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3759 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3760 session
->flow_control_state());
3762 base::WeakPtr
<SpdyStream
> stream1
=
3763 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3764 session
, url
, LOWEST
, BoundNetLog());
3765 ASSERT_TRUE(stream1
.get() != NULL
);
3767 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
3768 stream1
->SetDelegate(&delegate1
);
3770 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
3772 base::WeakPtr
<SpdyStream
> stream2
=
3773 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3774 session
, url
, MEDIUM
, BoundNetLog());
3775 ASSERT_TRUE(stream2
.get() != NULL
);
3777 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
3778 stream2
->SetDelegate(&delegate2
);
3780 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
3782 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
3783 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
3785 StallSessionSend(session
.get());
3787 scoped_ptr
<SpdyHeaderBlock
> headers1(
3788 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
3789 EXPECT_EQ(ERR_IO_PENDING
,
3790 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
3791 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
3792 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
3795 EXPECT_EQ(1u, stream1
->stream_id());
3796 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
3798 scoped_ptr
<SpdyHeaderBlock
> headers2(
3799 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
3800 EXPECT_EQ(ERR_IO_PENDING
,
3801 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
3802 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
3803 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
3806 EXPECT_EQ(3u, stream2
->stream_id());
3807 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
3809 // This should unstall only stream2.
3810 UnstallSessionSend(session
.get(), kBodyDataSize
);
3812 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
3813 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
3817 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
3818 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
3820 // This should then unstall stream1.
3821 UnstallSessionSend(session
.get(), kBodyDataSize
);
3823 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
3824 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
3828 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
3829 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
3831 EXPECT_TRUE(delegate1
.send_headers_completed());
3832 EXPECT_EQ("200", delegate1
.GetResponseHeaderValue(":status"));
3833 EXPECT_EQ("HTTP/1.1", delegate1
.GetResponseHeaderValue(":version"));
3834 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
3836 EXPECT_TRUE(delegate2
.send_headers_completed());
3837 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
3838 EXPECT_EQ("HTTP/1.1", delegate2
.GetResponseHeaderValue(":version"));
3839 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
3841 EXPECT_TRUE(data
.at_write_eof());
3844 // Delegate that closes a given stream after sending its body.
3845 class StreamClosingDelegate
: public test::StreamDelegateWithBody
{
3847 StreamClosingDelegate(const base::WeakPtr
<SpdyStream
>& stream
,
3848 base::StringPiece data
)
3849 : StreamDelegateWithBody(stream
, data
) {}
3851 virtual ~StreamClosingDelegate() {}
3853 void set_stream_to_close(const base::WeakPtr
<SpdyStream
>& stream_to_close
) {
3854 stream_to_close_
= stream_to_close
;
3857 virtual void OnDataSent() OVERRIDE
{
3858 test::StreamDelegateWithBody::OnDataSent();
3859 if (stream_to_close_
.get()) {
3860 stream_to_close_
->Close();
3861 EXPECT_EQ(NULL
, stream_to_close_
.get());
3866 base::WeakPtr
<SpdyStream
> stream_to_close_
;
3869 // Cause a stall by reducing the flow control send window to
3870 // 0. Unstalling the session should properly handle deleted streams.
3871 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedStreams
) {
3872 if (GetParam() < kProtoSPDY31
)
3875 const char kStreamUrl
[] = "http://www.google.com/";
3876 GURL
url(kStreamUrl
);
3878 session_deps_
.host_resolver
->set_synchronous_mode(true);
3880 scoped_ptr
<SpdyFrame
> req1(
3881 spdy_util_
.ConstructSpdyPost(
3882 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
3883 scoped_ptr
<SpdyFrame
> req2(
3884 spdy_util_
.ConstructSpdyPost(
3885 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, NULL
, 0));
3886 scoped_ptr
<SpdyFrame
> req3(
3887 spdy_util_
.ConstructSpdyPost(
3888 kStreamUrl
, 5, kBodyDataSize
, LOWEST
, NULL
, 0));
3889 scoped_ptr
<SpdyFrame
> body2(
3890 spdy_util_
.ConstructSpdyBodyFrame(3, kBodyData
, kBodyDataSize
, true));
3891 MockWrite writes
[] = {
3892 CreateMockWrite(*req1
, 0),
3893 CreateMockWrite(*req2
, 1),
3894 CreateMockWrite(*req3
, 2),
3895 CreateMockWrite(*body2
, 3),
3898 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3899 MockRead reads
[] = {
3900 CreateMockRead(*resp2
, 4),
3901 MockRead(ASYNC
, 0, 0, 5), // EOF
3904 DeterministicSocketData
data(reads
, arraysize(reads
),
3905 writes
, arraysize(writes
));
3906 MockConnect
connect_data(SYNCHRONOUS
, OK
);
3907 data
.set_connect_data(connect_data
);
3909 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
3911 CreateDeterministicNetworkSession();
3912 base::WeakPtr
<SpdySession
> session
=
3913 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
3914 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
3915 session
->flow_control_state());
3917 base::WeakPtr
<SpdyStream
> stream1
=
3918 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3919 session
, url
, LOWEST
, BoundNetLog());
3920 ASSERT_TRUE(stream1
.get() != NULL
);
3922 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
3923 stream1
->SetDelegate(&delegate1
);
3925 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
3927 base::WeakPtr
<SpdyStream
> stream2
=
3928 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3929 session
, url
, LOWEST
, BoundNetLog());
3930 ASSERT_TRUE(stream2
.get() != NULL
);
3932 StreamClosingDelegate
delegate2(stream2
, kBodyDataStringPiece
);
3933 stream2
->SetDelegate(&delegate2
);
3935 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
3937 base::WeakPtr
<SpdyStream
> stream3
=
3938 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
3939 session
, url
, LOWEST
, BoundNetLog());
3940 ASSERT_TRUE(stream3
.get() != NULL
);
3942 test::StreamDelegateWithBody
delegate3(stream3
, kBodyDataStringPiece
);
3943 stream3
->SetDelegate(&delegate3
);
3945 EXPECT_FALSE(stream3
->HasUrlFromHeaders());
3947 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
3948 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
3949 EXPECT_FALSE(stream3
->send_stalled_by_flow_control());
3951 StallSessionSend(session
.get());
3953 scoped_ptr
<SpdyHeaderBlock
> headers1(
3954 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
3955 EXPECT_EQ(ERR_IO_PENDING
,
3956 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
3957 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
3958 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
3961 EXPECT_EQ(1u, stream1
->stream_id());
3962 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
3964 scoped_ptr
<SpdyHeaderBlock
> headers2(
3965 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
3966 EXPECT_EQ(ERR_IO_PENDING
,
3967 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
3968 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
3969 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
3972 EXPECT_EQ(3u, stream2
->stream_id());
3973 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
3975 scoped_ptr
<SpdyHeaderBlock
> headers3(
3976 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
3977 EXPECT_EQ(ERR_IO_PENDING
,
3978 stream3
->SendRequestHeaders(headers3
.Pass(), MORE_DATA_TO_SEND
));
3979 EXPECT_TRUE(stream3
->HasUrlFromHeaders());
3980 EXPECT_EQ(kStreamUrl
, stream3
->GetUrlFromHeaders().spec());
3983 EXPECT_EQ(5u, stream3
->stream_id());
3984 EXPECT_TRUE(stream3
->send_stalled_by_flow_control());
3986 SpdyStreamId stream_id1
= stream1
->stream_id();
3987 SpdyStreamId stream_id2
= stream2
->stream_id();
3988 SpdyStreamId stream_id3
= stream3
->stream_id();
3990 // Close stream1 preemptively.
3991 session
->CloseActiveStream(stream_id1
, ERR_CONNECTION_CLOSED
);
3992 EXPECT_EQ(NULL
, stream1
.get());
3994 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
3995 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
3996 EXPECT_TRUE(session
->IsStreamActive(stream_id3
));
3998 // Unstall stream2, which should then close stream3.
3999 delegate2
.set_stream_to_close(stream3
);
4000 UnstallSessionSend(session
.get(), kBodyDataSize
);
4003 EXPECT_EQ(NULL
, stream3
.get());
4005 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4006 EXPECT_FALSE(session
->IsStreamActive(stream_id1
));
4007 EXPECT_TRUE(session
->IsStreamActive(stream_id2
));
4008 EXPECT_FALSE(session
->IsStreamActive(stream_id3
));
4011 EXPECT_EQ(NULL
, stream2
.get());
4013 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4014 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4015 EXPECT_EQ(OK
, delegate3
.WaitForClose());
4017 EXPECT_TRUE(delegate1
.send_headers_completed());
4018 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4020 EXPECT_TRUE(delegate2
.send_headers_completed());
4021 EXPECT_EQ("200", delegate2
.GetResponseHeaderValue(":status"));
4022 EXPECT_EQ("HTTP/1.1", delegate2
.GetResponseHeaderValue(":version"));
4023 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4025 EXPECT_TRUE(delegate3
.send_headers_completed());
4026 EXPECT_EQ(std::string(), delegate3
.TakeReceivedData());
4028 EXPECT_TRUE(data
.at_write_eof());
4031 // Cause a stall by reducing the flow control send window to
4032 // 0. Unstalling the session should properly handle the session itself
4034 TEST_P(SpdySessionTest
, SendWindowSizeIncreaseWithDeletedSession
) {
4035 if (GetParam() < kProtoSPDY31
)
4038 const char kStreamUrl
[] = "http://www.google.com/";
4039 GURL
url(kStreamUrl
);
4041 session_deps_
.host_resolver
->set_synchronous_mode(true);
4043 scoped_ptr
<SpdyFrame
> req1(
4044 spdy_util_
.ConstructSpdyPost(
4045 kStreamUrl
, 1, kBodyDataSize
, LOWEST
, NULL
, 0));
4046 scoped_ptr
<SpdyFrame
> req2(
4047 spdy_util_
.ConstructSpdyPost(
4048 kStreamUrl
, 3, kBodyDataSize
, LOWEST
, NULL
, 0));
4049 scoped_ptr
<SpdyFrame
> body1(
4050 spdy_util_
.ConstructSpdyBodyFrame(1, kBodyData
, kBodyDataSize
, false));
4051 MockWrite writes
[] = {
4052 CreateMockWrite(*req1
, 0),
4053 CreateMockWrite(*req2
, 1),
4056 MockRead reads
[] = {
4057 MockRead(ASYNC
, 0, 0, 2), // EOF
4060 DeterministicSocketData
data(reads
, arraysize(reads
),
4061 writes
, arraysize(writes
));
4062 MockConnect
connect_data(SYNCHRONOUS
, OK
);
4063 data
.set_connect_data(connect_data
);
4065 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
4067 CreateDeterministicNetworkSession();
4068 base::WeakPtr
<SpdySession
> session
=
4069 CreateInsecureSpdySession(http_session_
, key_
, BoundNetLog());
4070 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION
,
4071 session
->flow_control_state());
4073 base::WeakPtr
<SpdyStream
> stream1
=
4074 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4075 session
, url
, LOWEST
, BoundNetLog());
4076 ASSERT_TRUE(stream1
.get() != NULL
);
4078 test::StreamDelegateWithBody
delegate1(stream1
, kBodyDataStringPiece
);
4079 stream1
->SetDelegate(&delegate1
);
4081 EXPECT_FALSE(stream1
->HasUrlFromHeaders());
4083 base::WeakPtr
<SpdyStream
> stream2
=
4084 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM
,
4085 session
, url
, LOWEST
, BoundNetLog());
4086 ASSERT_TRUE(stream2
.get() != NULL
);
4088 test::StreamDelegateWithBody
delegate2(stream2
, kBodyDataStringPiece
);
4089 stream2
->SetDelegate(&delegate2
);
4091 EXPECT_FALSE(stream2
->HasUrlFromHeaders());
4093 EXPECT_FALSE(stream1
->send_stalled_by_flow_control());
4094 EXPECT_FALSE(stream2
->send_stalled_by_flow_control());
4096 StallSessionSend(session
.get());
4098 scoped_ptr
<SpdyHeaderBlock
> headers1(
4099 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4100 EXPECT_EQ(ERR_IO_PENDING
,
4101 stream1
->SendRequestHeaders(headers1
.Pass(), MORE_DATA_TO_SEND
));
4102 EXPECT_TRUE(stream1
->HasUrlFromHeaders());
4103 EXPECT_EQ(kStreamUrl
, stream1
->GetUrlFromHeaders().spec());
4106 EXPECT_EQ(1u, stream1
->stream_id());
4107 EXPECT_TRUE(stream1
->send_stalled_by_flow_control());
4109 scoped_ptr
<SpdyHeaderBlock
> headers2(
4110 spdy_util_
.ConstructPostHeaderBlock(kStreamUrl
, kBodyDataSize
));
4111 EXPECT_EQ(ERR_IO_PENDING
,
4112 stream2
->SendRequestHeaders(headers2
.Pass(), MORE_DATA_TO_SEND
));
4113 EXPECT_TRUE(stream2
->HasUrlFromHeaders());
4114 EXPECT_EQ(kStreamUrl
, stream2
->GetUrlFromHeaders().spec());
4117 EXPECT_EQ(3u, stream2
->stream_id());
4118 EXPECT_TRUE(stream2
->send_stalled_by_flow_control());
4120 EXPECT_TRUE(HasSpdySession(spdy_session_pool_
, key_
));
4123 UnstallSessionSend(session
.get(), kBodyDataSize
);
4125 // Close the session (since we can't do it from within the delegate
4126 // method, since it's in the stream's loop).
4127 session
->CloseSessionOnError(ERR_CONNECTION_CLOSED
, "Closing session");
4128 EXPECT_TRUE(session
== NULL
);
4130 EXPECT_FALSE(HasSpdySession(spdy_session_pool_
, key_
));
4132 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate1
.WaitForClose());
4133 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate2
.WaitForClose());
4135 EXPECT_TRUE(delegate1
.send_headers_completed());
4136 EXPECT_EQ(std::string(), delegate1
.TakeReceivedData());
4138 EXPECT_TRUE(delegate2
.send_headers_completed());
4139 EXPECT_EQ(std::string(), delegate2
.TakeReceivedData());
4141 EXPECT_TRUE(data
.at_write_eof());