Disable view source for Developer Tools.
[chromium-blink-merge.git] / net / spdy / spdy_session_unittest.cc
blob2f185c7c01a09c6c7828f5acf526f8d8b4384365
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/spdy/spdy_session.h"
7 #include "base/bind.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"
30 namespace net {
32 namespace {
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;
47 } // namespace
49 class SpdySessionTest : public PlatformTest,
50 public ::testing::WithParamInterface<NextProto> {
51 public:
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,
73 SpdyStream* stream,
74 int32 delta_window_size) {
75 UnstallSessionSend(session, delta_window_size);
78 void UnstallStreamOnly(SpdySession* session,
79 SpdyStream* stream,
80 int32 delta_window_size) {
81 UnstallStreamSend(stream, delta_window_size);
84 void UnstallSessionStream(SpdySession* session,
85 SpdyStream* stream,
86 int32 delta_window_size) {
87 UnstallSessionSend(session, delta_window_size);
88 UnstallStreamSend(stream, delta_window_size);
91 void UnstallStreamSession(SpdySession* session,
92 SpdyStream* stream,
93 int32 delta_window_size) {
94 UnstallStreamSend(stream, delta_window_size);
95 UnstallSessionSend(session, delta_window_size);
98 protected:
99 SpdySessionTest()
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),
107 test_url_(kTestUrl),
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() {
127 http_session_ =
128 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
129 spdy_session_pool_ = http_session_->spdy_session_pool();
132 void CreateNetworkSession() {
133 http_session_ =
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)>&
165 unstall_function);
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_;
176 GURL test_url_;
177 HostPortPair test_host_port_pair_;
178 SpdySessionKey key_;
181 INSTANTIATE_TEST_CASE_P(
182 NextProto,
183 SpdySessionTest,
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);
197 namespace {
199 // A helper class that vends a callback that, when fired, destroys a
200 // given SpdyStreamRequest.
201 class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
202 public:
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));
216 private:
217 void OnComplete(int result) {
218 request_.reset();
219 SetResult(result);
222 scoped_ptr<SpdyStreamRequest> request_;
225 } // namespace
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,
262 session,
263 test_url_,
264 MEDIUM,
265 BoundNetLog(),
266 callback1.MakeCallback()));
268 // |callback2| is never called.
269 TestCompletionCallback callback2;
270 ASSERT_EQ(ERR_IO_PENDING,
271 request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM,
272 session,
273 test_url_,
274 MEDIUM,
275 BoundNetLog(),
276 callback2.callback()));
278 callback1.SetRequestToDestroy(request2.Pass());
280 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
282 EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
284 data.RunFor(1);
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));
294 MockRead reads[] = {
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.
314 data.RunFor(1);
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));
328 MockRead reads[] = {
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();
340 data.StopAfter(1);
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));
355 MockRead reads[] = {
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());
404 data.RunFor(2);
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.
412 data.RunFor(1);
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));
438 MockRead reads[] = {
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());
488 data.RunFor(2);
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.
496 data.RunFor(1);
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
507 // session.
508 data.RunFor(1);
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));
521 MockRead reads[] = {
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());
570 data.RunFor(2);
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.
578 data.RunFor(1);
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
595 // fail.
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));
602 MockRead reads[] = {
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());
638 data.RunFor(1);
640 EXPECT_EQ(1u, spdy_stream->stream_id());
642 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
644 // Read and process the GOAWAY frame.
645 data.RunFor(1);
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.
657 data.RunFor(1);
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));
672 MockRead reads[] = {
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());
712 data.RunFor(1);
714 EXPECT_EQ(1u, spdy_stream->stream_id());
716 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
718 // Read and process the GOAWAY frame.
719 data.RunFor(1);
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,
725 // and EOF.
726 data.RunFor(3);
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));
737 MockRead reads[] = {
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();
773 data.RunFor(2);
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);
782 data.RunFor(1);
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));
795 MockRead reads[] = {
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),
849 MockRead reads[] = {
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);
882 data.RunFor(2);
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,
907 session,
908 GURL(),
909 DEFAULT_PRIORITY,
910 kSpdyStreamInitialWindowSize,
911 kSpdyStreamInitialWindowSize,
912 session->net_log_));
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);
953 MockRead reads[] = {
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_));
999 data.RunFor(1);
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,
1049 BoundNetLog(),
1050 stream_releaser.MakeCallback(&request)));
1052 data.RunFor(1);
1054 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1056 data.RunFor(1);
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
1063 // correct.
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);
1097 EXPECT_FALSE(
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,
1118 BoundNetLog(),
1119 stream_releaser.MakeCallback(&request)));
1121 data.RunFor(1);
1123 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1125 // Make sure that persisted data is cleared.
1126 EXPECT_TRUE(
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());
1134 data.RunFor(1);
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,
1193 BoundNetLog(),
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();
1201 callback.reset();
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) {
1233 writes.push_back(
1234 MockWrite(ASYNC,
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(
1330 entries, 0,
1331 net::NetLog::TYPE_SPDY_SESSION_INITIALIZED,
1332 net::NetLog::PHASE_NONE);
1333 EXPECT_LT(0, pos);
1335 CapturingNetLog::CapturedEntry entry = entries[pos];
1336 NetLog::Source socket_source;
1337 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1338 &socket_source));
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(
1380 entries, 0,
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];
1386 int error_code = 0;
1387 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1388 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1389 } else {
1390 ADD_FAILURE();
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
1396 // first.
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());
1472 data.RunFor(7);
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());
1548 data.RunFor(1);
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());
1775 data.RunFor(2);
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());
1861 data.RunFor(2);
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 {
1880 public:
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");
1892 private:
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());
1942 data.RunFor(1);
1944 EXPECT_EQ(1u, spdy_stream->stream_id());
1946 // Ensure we don't crash while closing the stream (which closes the
1947 // session).
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:
1974 // www.example.org
1975 // mail.example.org
1976 // www.example.com
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:
2016 // www.example.org
2017 // mail.example.org
2018 // www.example.com
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
2042 // this file.
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
2064 // streams to 1.
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.
2102 data.RunFor(1);
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());
2140 data.RunFor(3);
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());
2166 data.RunFor(3);
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());
2192 data.RunFor(3);
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));
2200 data.RunFor(1);
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
2320 // bytes.
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
2360 // post a task.
2361 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2363 // Run until 1st read.
2364 EXPECT_EQ(0u, delegate1.stream_id());
2365 data.RunFor(2);
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
2370 // posted a task.
2371 data.RunFor(4);
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
2454 // task.
2455 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2457 // Run until 1st read.
2458 EXPECT_EQ(0u, delegate1.stream_id());
2459 data.RunFor(2);
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
2464 // task.
2465 data.RunFor(6);
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
2470 // to read.
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());
2575 data.RunFor(2);
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
2580 // task.
2581 data.RunFor(12);
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
2586 // it to read.
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());
2645 data.RunFor(1);
2646 EXPECT_EQ(1u, spdy_stream1->stream_id());
2648 // Run until GoAway.
2649 data.RunFor(3);
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_);
2685 } else {
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
2740 // new connection.
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
2748 // has an alias.
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,
2794 DEFAULT_PRIORITY,
2795 &addresses,
2796 CompletionCallback(),
2797 NULL,
2798 BoundNetLog());
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
2819 // new connection.
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),
2855 NULL, 0);
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,
2880 BoundNetLog());
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
2909 // happens.
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 {
2962 public:
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");
2972 ignore_result(
2973 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2974 session_, url, MEDIUM, BoundNetLog()));
2977 private:
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());
3031 data.RunFor(1);
3033 EXPECT_EQ(1u, spdy_stream->stream_id());
3035 // Cause the stream to be reset, which should cause another stream
3036 // to be created.
3037 data.RunFor(1);
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)
3049 return;
3051 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3052 // gets sent.
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)
3115 return;
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_);
3161 data.RunFor(1);
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
3175 // is set.
3176 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3177 if (GetParam() < kProtoSPDY31)
3178 return;
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)
3213 return;
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_);
3239 data.RunFor(1);
3241 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3242 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3244 data.RunFor(1);
3247 // A delegate that drops any received data.
3248 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3249 public:
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)
3265 return;
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_);
3332 data.RunFor(4);
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_);
3340 stream->Close();
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)
3354 return;
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_);
3409 data.RunFor(1);
3411 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3413 data.RunFor(1);
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.
3422 stream->Close();
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)
3434 return;
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_);
3503 data.RunFor(1);
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_);
3509 data.RunFor(1);
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_);
3516 data.RunFor(1);
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_);
3523 data.RunFor(1);
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_);
3531 data.RunFor(1);
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
3544 // receive window.
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_);
3549 stream->Close();
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)>&
3564 unstall_function) {
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());
3622 data.RunFor(1);
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());
3630 data.RunFor(3);
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)
3646 return;
3648 RunResumeAfterUnstallTest(
3649 base::Bind(&SpdySessionTest::StallSessionOnly,
3650 base::Unretained(this)),
3651 base::Bind(&SpdySessionTest::UnstallSessionOnly,
3652 base::Unretained(this)));
3655 // Equivalent to
3656 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
3657 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
3658 if (GetParam() < kProtoSPDY31)
3659 return;
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)
3670 return;
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)
3681 return;
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)
3692 return;
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)
3703 return;
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
3714 // increased.
3715 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
3716 if (GetParam() < kProtoSPDY31)
3717 return;
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());
3794 data.RunFor(1);
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());
3805 data.RunFor(1);
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());
3815 data.RunFor(1);
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());
3826 data.RunFor(4);
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 {
3846 public:
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());
3865 private:
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)
3873 return;
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());
3960 data.RunFor(1);
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());
3971 data.RunFor(1);
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());
3982 data.RunFor(1);
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);
4002 data.RunFor(1);
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));
4010 data.RunFor(2);
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
4033 // being closed.
4034 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4035 if (GetParam() < kProtoSPDY31)
4036 return;
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());
4105 data.RunFor(1);
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());
4116 data.RunFor(1);
4117 EXPECT_EQ(3u, stream2->stream_id());
4118 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4120 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4122 // Unstall stream1.
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());
4144 } // namespace net