1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/spdy/spdy_session.h"
7 #include "base/base64.h"
9 #include "base/callback.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/test/histogram_tester.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/ip_endpoint.h"
15 #include "net/base/net_log_unittest.h"
16 #include "net/base/request_priority.h"
17 #include "net/base/test_data_directory.h"
18 #include "net/base/test_data_stream.h"
19 #include "net/socket/client_socket_pool_manager.h"
20 #include "net/socket/next_proto.h"
21 #include "net/socket/socket_test_util.h"
22 #include "net/spdy/spdy_http_utils.h"
23 #include "net/spdy/spdy_session_pool.h"
24 #include "net/spdy/spdy_session_test_util.h"
25 #include "net/spdy/spdy_stream.h"
26 #include "net/spdy/spdy_stream_test_util.h"
27 #include "net/spdy/spdy_test_util_common.h"
28 #include "net/spdy/spdy_test_utils.h"
29 #include "net/test/cert_test_util.h"
30 #include "testing/platform_test.h"
36 static const char kTestUrl[] = "http://www.example.org/";
37 static const char kTestHost[] = "www.example.org";
38 static const int kTestPort = 80;
40 const char kBodyData[] = "Body data";
41 const size_t kBodyDataSize = arraysize(kBodyData);
42 const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize);
44 static base::TimeDelta g_time_delta;
45 base::TimeTicks TheNearFuture() {
46 return base::TimeTicks::Now() + g_time_delta;
51 class SpdySessionTest : public PlatformTest,
52 public ::testing::WithParamInterface<NextProto> {
54 // Functions used with RunResumeAfterUnstallTest().
56 void StallSessionOnly(SpdySession* session, SpdyStream* stream) {
57 StallSessionSend(session);
60 void StallStreamOnly(SpdySession* session, SpdyStream* stream) {
61 StallStreamSend(stream);
64 void StallSessionStream(SpdySession* session, SpdyStream* stream) {
65 StallSessionSend(session);
66 StallStreamSend(stream);
69 void StallStreamSession(SpdySession* session, SpdyStream* stream) {
70 StallStreamSend(stream);
71 StallSessionSend(session);
74 void UnstallSessionOnly(SpdySession* session,
76 int32 delta_window_size) {
77 UnstallSessionSend(session, delta_window_size);
80 void UnstallStreamOnly(SpdySession* session,
82 int32 delta_window_size) {
83 UnstallStreamSend(stream, delta_window_size);
86 void UnstallSessionStream(SpdySession* session,
88 int32 delta_window_size) {
89 UnstallSessionSend(session, delta_window_size);
90 UnstallStreamSend(stream, delta_window_size);
93 void UnstallStreamSession(SpdySession* session,
95 int32 delta_window_size) {
96 UnstallStreamSend(stream, delta_window_size);
97 UnstallSessionSend(session, delta_window_size);
102 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
103 HttpNetworkSession::NORMAL_SOCKET_POOL)),
104 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
105 HttpNetworkSession::NORMAL_SOCKET_POOL)),
106 spdy_util_(GetParam()),
107 session_deps_(GetParam()),
108 spdy_session_pool_(NULL),
110 test_host_port_pair_(kTestHost, kTestPort),
111 key_(test_host_port_pair_, ProxyServer::Direct(),
112 PRIVACY_MODE_DISABLED) {
115 virtual ~SpdySessionTest() {
116 // Important to restore the per-pool limit first, since the pool limit must
117 // always be greater than group limit, and the tests reduce both limits.
118 ClientSocketPoolManager::set_max_sockets_per_pool(
119 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
120 ClientSocketPoolManager::set_max_sockets_per_group(
121 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
124 void SetUp() override { g_time_delta = base::TimeDelta(); }
126 void CreateDeterministicNetworkSession() {
128 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
129 spdy_session_pool_ = http_session_->spdy_session_pool();
132 void CreateNetworkSession() {
134 SpdySessionDependencies::SpdyCreateSession(&session_deps_);
135 spdy_session_pool_ = http_session_->spdy_session_pool();
138 void StallSessionSend(SpdySession* session) {
139 // Reduce the send window size to 0 to stall.
140 while (session->session_send_window_size_ > 0) {
141 session->DecreaseSendWindowSize(
142 std::min(kMaxSpdyFrameChunkSize, session->session_send_window_size_));
146 void UnstallSessionSend(SpdySession* session, int32 delta_window_size) {
147 session->IncreaseSendWindowSize(delta_window_size);
150 void StallStreamSend(SpdyStream* stream) {
151 // Reduce the send window size to 0 to stall.
152 while (stream->send_window_size() > 0) {
153 stream->DecreaseSendWindowSize(
154 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
158 void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) {
159 stream->IncreaseSendWindowSize(delta_window_size);
162 void RunResumeAfterUnstallTest(
163 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
164 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
167 // Original socket limits. Some tests set these. Safest to always restore
168 // them once each test has been run.
169 int old_max_group_sockets_;
170 int old_max_pool_sockets_;
172 SpdyTestUtil spdy_util_;
173 SpdySessionDependencies session_deps_;
174 scoped_refptr<HttpNetworkSession> http_session_;
175 SpdySessionPool* spdy_session_pool_;
177 HostPortPair test_host_port_pair_;
181 INSTANTIATE_TEST_CASE_P(
184 testing::Values(kProtoDeprecatedSPDY2,
185 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
187 // Try to create a SPDY session that will fail during
188 // initialization. Nothing should blow up.
189 TEST_P(SpdySessionTest, InitialReadError) {
190 CreateDeterministicNetworkSession();
192 base::WeakPtr<SpdySession> session = TryCreateFakeSpdySessionExpectingFailure(
193 spdy_session_pool_, key_, ERR_CONNECTION_CLOSED);
194 EXPECT_TRUE(session);
196 base::RunLoop().RunUntilIdle();
197 EXPECT_FALSE(session);
202 // A helper class that vends a callback that, when fired, destroys a
203 // given SpdyStreamRequest.
204 class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
206 StreamRequestDestroyingCallback() {}
208 ~StreamRequestDestroyingCallback() override {}
210 void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) {
211 request_ = request.Pass();
214 CompletionCallback MakeCallback() {
215 return base::Bind(&StreamRequestDestroyingCallback::OnComplete,
216 base::Unretained(this));
220 void OnComplete(int result) {
225 scoped_ptr<SpdyStreamRequest> request_;
230 // Request kInitialMaxConcurrentStreams streams. Request two more
231 // streams, but have the callback for one destroy the second stream
232 // request. Close the session. Nothing should blow up. This is a
233 // regression test for http://crbug.com/250841 .
234 TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
235 session_deps_.host_resolver->set_synchronous_mode(true);
237 MockRead reads[] = {MockRead(ASYNC, 0, 0), };
239 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
240 MockConnect connect_data(SYNCHRONOUS, OK);
241 data.set_connect_data(connect_data);
242 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
244 CreateDeterministicNetworkSession();
246 base::WeakPtr<SpdySession> session =
247 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
249 // Create the maximum number of concurrent streams.
250 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
251 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
252 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog());
253 ASSERT_TRUE(spdy_stream != NULL);
256 SpdyStreamRequest request1;
257 scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest);
259 StreamRequestDestroyingCallback callback1;
260 ASSERT_EQ(ERR_IO_PENDING,
261 request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM,
266 callback1.MakeCallback()));
268 // |callback2| is never called.
269 TestCompletionCallback callback2;
270 ASSERT_EQ(ERR_IO_PENDING,
271 request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM,
276 callback2.callback()));
278 callback1.SetRequestToDestroy(request2.Pass());
280 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
282 EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
285 // A session receiving a GOAWAY frame with no active streams should close.
286 TEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
287 session_deps_.host_resolver->set_synchronous_mode(true);
289 MockConnect connect_data(SYNCHRONOUS, OK);
290 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
292 CreateMockRead(*goaway, 0),
294 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
295 data.set_connect_data(connect_data);
296 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
298 CreateDeterministicNetworkSession();
300 base::WeakPtr<SpdySession> session =
301 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
303 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
305 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
307 // Read and process the GOAWAY frame.
309 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
310 base::RunLoop().RunUntilIdle();
311 EXPECT_TRUE(session == NULL);
314 // A session receiving a GOAWAY frame immediately with no active
315 // streams should then close.
316 TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
317 session_deps_.host_resolver->set_synchronous_mode(true);
319 MockConnect connect_data(SYNCHRONOUS, OK);
320 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
322 CreateMockRead(*goaway, 0, SYNCHRONOUS),
324 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
325 data.set_connect_data(connect_data);
326 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
328 CreateDeterministicNetworkSession();
332 base::WeakPtr<SpdySession> session =
333 TryCreateInsecureSpdySessionExpectingFailure(
334 http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
335 base::RunLoop().RunUntilIdle();
337 EXPECT_FALSE(session);
338 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
341 // A session receiving a GOAWAY frame with active streams should close
342 // when the last active stream is closed.
343 TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
344 session_deps_.host_resolver->set_synchronous_mode(true);
346 MockConnect connect_data(SYNCHRONOUS, OK);
347 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
349 CreateMockRead(*goaway, 2),
350 MockRead(ASYNC, 0, 3) // EOF
352 scoped_ptr<SpdyFrame> req1(
353 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
354 scoped_ptr<SpdyFrame> req2(
355 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
356 MockWrite writes[] = {
357 CreateMockWrite(*req1, 0),
358 CreateMockWrite(*req2, 1),
360 DeterministicSocketData data(reads, arraysize(reads),
361 writes, arraysize(writes));
362 data.set_connect_data(connect_data);
363 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
365 CreateDeterministicNetworkSession();
367 base::WeakPtr<SpdySession> session =
368 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
370 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
372 GURL url(kDefaultURL);
373 base::WeakPtr<SpdyStream> spdy_stream1 =
374 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
375 session, url, MEDIUM, BoundNetLog());
376 test::StreamDelegateDoNothing delegate1(spdy_stream1);
377 spdy_stream1->SetDelegate(&delegate1);
379 base::WeakPtr<SpdyStream> spdy_stream2 =
380 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
381 session, url, MEDIUM, BoundNetLog());
382 test::StreamDelegateDoNothing delegate2(spdy_stream2);
383 spdy_stream2->SetDelegate(&delegate2);
385 scoped_ptr<SpdyHeaderBlock> headers(
386 spdy_util_.ConstructGetHeaderBlock(url.spec()));
387 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
389 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
390 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
391 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
392 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
396 EXPECT_EQ(1u, spdy_stream1->stream_id());
397 EXPECT_EQ(3u, spdy_stream2->stream_id());
399 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
401 // Read and process the GOAWAY frame.
404 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
406 EXPECT_FALSE(session->IsStreamActive(3));
407 EXPECT_EQ(NULL, spdy_stream2.get());
408 EXPECT_TRUE(session->IsStreamActive(1));
410 EXPECT_TRUE(session->IsGoingAway());
412 // Should close the session.
413 spdy_stream1->Close();
414 EXPECT_EQ(NULL, spdy_stream1.get());
416 base::MessageLoop::current()->RunUntilIdle();
417 EXPECT_TRUE(session == NULL);
420 // Have a session receive two GOAWAY frames, with the last one causing
421 // the last active stream to be closed. The session should then be
422 // closed after the second GOAWAY frame.
423 TEST_P(SpdySessionTest, GoAwayTwice) {
424 session_deps_.host_resolver->set_synchronous_mode(true);
426 MockConnect connect_data(SYNCHRONOUS, OK);
427 scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
428 scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
430 CreateMockRead(*goaway1, 2),
431 CreateMockRead(*goaway2, 3),
432 MockRead(ASYNC, 0, 4) // EOF
434 scoped_ptr<SpdyFrame> req1(
435 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
436 scoped_ptr<SpdyFrame> req2(
437 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
438 MockWrite writes[] = {
439 CreateMockWrite(*req1, 0),
440 CreateMockWrite(*req2, 1),
442 DeterministicSocketData data(reads, arraysize(reads),
443 writes, arraysize(writes));
444 data.set_connect_data(connect_data);
445 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
447 CreateDeterministicNetworkSession();
449 base::WeakPtr<SpdySession> session =
450 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
452 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
454 GURL url(kDefaultURL);
455 base::WeakPtr<SpdyStream> spdy_stream1 =
456 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
457 session, url, MEDIUM, BoundNetLog());
458 test::StreamDelegateDoNothing delegate1(spdy_stream1);
459 spdy_stream1->SetDelegate(&delegate1);
461 base::WeakPtr<SpdyStream> spdy_stream2 =
462 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
463 session, url, MEDIUM, BoundNetLog());
464 test::StreamDelegateDoNothing delegate2(spdy_stream2);
465 spdy_stream2->SetDelegate(&delegate2);
467 scoped_ptr<SpdyHeaderBlock> headers(
468 spdy_util_.ConstructGetHeaderBlock(url.spec()));
469 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
471 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
472 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
473 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
474 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
478 EXPECT_EQ(1u, spdy_stream1->stream_id());
479 EXPECT_EQ(3u, spdy_stream2->stream_id());
481 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
483 // Read and process the first GOAWAY frame.
486 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
488 EXPECT_FALSE(session->IsStreamActive(3));
489 EXPECT_EQ(NULL, spdy_stream2.get());
490 EXPECT_TRUE(session->IsStreamActive(1));
491 EXPECT_TRUE(session->IsGoingAway());
493 // Read and process the second GOAWAY frame, which should close the
496 base::MessageLoop::current()->RunUntilIdle();
497 EXPECT_TRUE(session == NULL);
500 // Have a session with active streams receive a GOAWAY frame and then
501 // close it. It should handle the close properly (i.e., not try to
502 // make itself unavailable in its pool twice).
503 TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
504 session_deps_.host_resolver->set_synchronous_mode(true);
506 MockConnect connect_data(SYNCHRONOUS, OK);
507 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
509 CreateMockRead(*goaway, 2),
510 MockRead(ASYNC, 0, 3) // EOF
512 scoped_ptr<SpdyFrame> req1(
513 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
514 scoped_ptr<SpdyFrame> req2(
515 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
516 MockWrite writes[] = {
517 CreateMockWrite(*req1, 0),
518 CreateMockWrite(*req2, 1),
520 DeterministicSocketData data(reads, arraysize(reads),
521 writes, arraysize(writes));
522 data.set_connect_data(connect_data);
523 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
525 CreateDeterministicNetworkSession();
527 base::WeakPtr<SpdySession> session =
528 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
530 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
532 GURL url(kDefaultURL);
533 base::WeakPtr<SpdyStream> spdy_stream1 =
534 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
535 session, url, MEDIUM, BoundNetLog());
536 test::StreamDelegateDoNothing delegate1(spdy_stream1);
537 spdy_stream1->SetDelegate(&delegate1);
539 base::WeakPtr<SpdyStream> spdy_stream2 =
540 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
541 session, url, MEDIUM, BoundNetLog());
542 test::StreamDelegateDoNothing delegate2(spdy_stream2);
543 spdy_stream2->SetDelegate(&delegate2);
545 scoped_ptr<SpdyHeaderBlock> headers(
546 spdy_util_.ConstructGetHeaderBlock(url.spec()));
547 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
549 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
550 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
551 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
552 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
556 EXPECT_EQ(1u, spdy_stream1->stream_id());
557 EXPECT_EQ(3u, spdy_stream2->stream_id());
559 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
561 // Read and process the GOAWAY frame.
564 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
566 EXPECT_FALSE(session->IsStreamActive(3));
567 EXPECT_EQ(NULL, spdy_stream2.get());
568 EXPECT_TRUE(session->IsStreamActive(1));
569 EXPECT_TRUE(session->IsGoingAway());
571 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
572 EXPECT_EQ(NULL, spdy_stream1.get());
574 base::MessageLoop::current()->RunUntilIdle();
575 EXPECT_TRUE(session == NULL);
578 // Process a joint read buffer which causes the session to begin draining, and
579 // then processes a GOAWAY. The session should gracefully drain. Regression test
580 // for crbug.com/379469
581 TEST_P(SpdySessionTest, GoAwayWhileDraining) {
582 session_deps_.host_resolver->set_synchronous_mode(true);
584 scoped_ptr<SpdyFrame> req(
585 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
586 MockWrite writes[] = {
587 CreateMockWrite(*req, 0),
590 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
591 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
592 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
593 size_t joint_size = goaway->size() * 2 + body->size();
595 // Compose interleaved |goaway| and |body| frames into a single read.
596 scoped_ptr<char[]> buffer(new char[joint_size]);
599 memcpy(&buffer[out], goaway->data(), goaway->size());
600 out += goaway->size();
601 memcpy(&buffer[out], body->data(), body->size());
603 memcpy(&buffer[out], goaway->data(), goaway->size());
604 out += goaway->size();
605 ASSERT_EQ(out, joint_size);
607 SpdyFrame joint_frames(buffer.get(), joint_size, false);
610 CreateMockRead(*resp, 1), CreateMockRead(joint_frames, 2),
611 MockRead(ASYNC, 0, 3) // EOF
614 MockConnect connect_data(SYNCHRONOUS, OK);
615 DeterministicSocketData data(
616 reads, arraysize(reads), writes, arraysize(writes));
617 data.set_connect_data(connect_data);
618 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
620 CreateDeterministicNetworkSession();
621 base::WeakPtr<SpdySession> session =
622 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
624 GURL url(kDefaultURL);
625 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
626 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
627 test::StreamDelegateDoNothing delegate(spdy_stream);
628 spdy_stream->SetDelegate(&delegate);
630 scoped_ptr<SpdyHeaderBlock> headers(
631 spdy_util_.ConstructGetHeaderBlock(url.spec()));
632 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
633 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
636 base::MessageLoop::current()->RunUntilIdle();
638 // Stream and session closed gracefully.
639 EXPECT_TRUE(delegate.StreamIsClosed());
640 EXPECT_EQ(OK, delegate.WaitForClose());
641 EXPECT_EQ(kUploadData, delegate.TakeReceivedData());
642 EXPECT_TRUE(session == NULL);
645 // Try to create a stream after receiving a GOAWAY frame. It should
647 TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
648 session_deps_.host_resolver->set_synchronous_mode(true);
650 MockConnect connect_data(SYNCHRONOUS, OK);
651 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
653 CreateMockRead(*goaway, 1),
654 MockRead(ASYNC, 0, 2) // EOF
656 scoped_ptr<SpdyFrame> req(
657 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
658 MockWrite writes[] = {
659 CreateMockWrite(*req, 0),
661 DeterministicSocketData data(reads, arraysize(reads),
662 writes, arraysize(writes));
663 data.set_connect_data(connect_data);
664 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
666 CreateDeterministicNetworkSession();
668 base::WeakPtr<SpdySession> session =
669 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
671 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
673 GURL url(kDefaultURL);
674 base::WeakPtr<SpdyStream> spdy_stream =
675 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
676 session, url, MEDIUM, BoundNetLog());
677 test::StreamDelegateDoNothing delegate(spdy_stream);
678 spdy_stream->SetDelegate(&delegate);
680 scoped_ptr<SpdyHeaderBlock> headers(
681 spdy_util_.ConstructGetHeaderBlock(url.spec()));
682 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
683 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
687 EXPECT_EQ(1u, spdy_stream->stream_id());
689 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
691 // Read and process the GOAWAY frame.
694 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
695 EXPECT_TRUE(session->IsStreamActive(1));
697 SpdyStreamRequest stream_request;
698 int rv = stream_request.StartRequest(
699 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog(),
700 CompletionCallback());
701 EXPECT_EQ(ERR_FAILED, rv);
703 // Read and process EOF.
706 EXPECT_TRUE(session == NULL);
709 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
710 // the stream being refused.
711 TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
712 session_deps_.host_resolver->set_synchronous_mode(true);
714 MockConnect connect_data(SYNCHRONOUS, OK);
715 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
716 scoped_ptr<SpdyFrame>
717 push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kDefaultURL));
719 CreateMockRead(*goaway, 1),
720 CreateMockRead(*push, 2),
721 MockRead(ASYNC, 0, 4) // EOF
723 scoped_ptr<SpdyFrame> req(
724 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
725 scoped_ptr<SpdyFrame> rst(
726 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
727 MockWrite writes[] = {
728 CreateMockWrite(*req, 0),
729 CreateMockWrite(*rst, 3)
731 DeterministicSocketData data(reads, arraysize(reads),
732 writes, arraysize(writes));
733 data.set_connect_data(connect_data);
734 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
736 CreateDeterministicNetworkSession();
738 base::WeakPtr<SpdySession> session =
739 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
741 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
743 GURL url(kDefaultURL);
744 base::WeakPtr<SpdyStream> spdy_stream =
745 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
746 session, url, MEDIUM, BoundNetLog());
747 test::StreamDelegateDoNothing delegate(spdy_stream);
748 spdy_stream->SetDelegate(&delegate);
750 scoped_ptr<SpdyHeaderBlock> headers(
751 spdy_util_.ConstructGetHeaderBlock(url.spec()));
752 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
753 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
757 EXPECT_EQ(1u, spdy_stream->stream_id());
759 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
761 // Read and process the GOAWAY frame.
764 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
765 EXPECT_TRUE(session->IsStreamActive(1));
767 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
770 base::MessageLoop::current()->RunUntilIdle();
771 EXPECT_TRUE(session == NULL);
774 // A session observing a network change with active streams should close
775 // when the last active stream is closed.
776 TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
777 session_deps_.host_resolver->set_synchronous_mode(true);
779 MockConnect connect_data(SYNCHRONOUS, OK);
781 MockRead(ASYNC, 0, 1) // EOF
783 scoped_ptr<SpdyFrame> req1(
784 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
785 MockWrite writes[] = {
786 CreateMockWrite(*req1, 0),
788 DeterministicSocketData data(reads, arraysize(reads),
789 writes, arraysize(writes));
790 data.set_connect_data(connect_data);
791 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
793 CreateDeterministicNetworkSession();
795 base::WeakPtr<SpdySession> session =
796 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
798 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
800 base::WeakPtr<SpdyStream> spdy_stream =
801 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session,
802 GURL(kDefaultURL), MEDIUM, BoundNetLog());
803 test::StreamDelegateDoNothing delegate(spdy_stream);
804 spdy_stream->SetDelegate(&delegate);
806 scoped_ptr<SpdyHeaderBlock> headers(
807 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
809 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
810 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
814 EXPECT_EQ(1u, spdy_stream->stream_id());
816 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
818 spdy_session_pool_->OnIPAddressChanged();
820 // The SpdySessionPool behavior differs based on how the OSs reacts to
821 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
822 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
823 // For OSs where the TCP connections will close upon relevant network
824 // changes, SpdySessionPool doesn't need to force them to close, so in these
825 // cases verify the session has become unavailable but remains open and the
826 // pre-existing stream is still active.
827 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
829 EXPECT_TRUE(session->IsGoingAway());
831 EXPECT_TRUE(session->IsStreamActive(1));
833 // Should close the session.
834 spdy_stream->Close();
836 EXPECT_EQ(NULL, spdy_stream.get());
838 base::MessageLoop::current()->RunUntilIdle();
839 EXPECT_TRUE(session == NULL);
842 TEST_P(SpdySessionTest, ClientPing) {
843 session_deps_.enable_ping = true;
844 session_deps_.host_resolver->set_synchronous_mode(true);
846 MockConnect connect_data(SYNCHRONOUS, OK);
847 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
849 CreateMockRead(*read_ping, 1),
850 MockRead(ASYNC, 0, 0, 2) // EOF
852 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
853 MockWrite writes[] = {
854 CreateMockWrite(*write_ping, 0),
856 DeterministicSocketData data(
857 reads, arraysize(reads), writes, arraysize(writes));
858 data.set_connect_data(connect_data);
859 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
861 CreateDeterministicNetworkSession();
863 base::WeakPtr<SpdySession> session =
864 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
866 base::WeakPtr<SpdyStream> spdy_stream1 =
867 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
868 session, test_url_, MEDIUM, BoundNetLog());
869 ASSERT_TRUE(spdy_stream1.get() != NULL);
870 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
871 spdy_stream1->SetDelegate(&delegate);
873 base::TimeTicks before_ping_time = base::TimeTicks::Now();
875 session->set_connection_at_risk_of_loss_time(
876 base::TimeDelta::FromSeconds(-1));
877 session->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
879 session->SendPrefacePingIfNoneInFlight();
883 session->CheckPingStatus(before_ping_time);
885 EXPECT_EQ(0, session->pings_in_flight());
886 EXPECT_GE(session->next_ping_id(), 1U);
887 EXPECT_FALSE(session->check_ping_status_pending());
888 EXPECT_GE(session->last_activity_time(), before_ping_time);
892 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
894 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
895 EXPECT_TRUE(session == NULL);
898 TEST_P(SpdySessionTest, ServerPing) {
899 session_deps_.host_resolver->set_synchronous_mode(true);
901 MockConnect connect_data(SYNCHRONOUS, OK);
902 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
904 CreateMockRead(*read_ping),
905 MockRead(SYNCHRONOUS, 0, 0) // EOF
907 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
908 MockWrite writes[] = {
909 CreateMockWrite(*write_ping),
911 StaticSocketDataProvider data(
912 reads, arraysize(reads), writes, arraysize(writes));
913 data.set_connect_data(connect_data);
914 session_deps_.socket_factory->AddSocketDataProvider(&data);
916 CreateNetworkSession();
918 base::WeakPtr<SpdySession> session =
919 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
921 base::WeakPtr<SpdyStream> spdy_stream1 =
922 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
923 session, test_url_, MEDIUM, BoundNetLog());
924 ASSERT_TRUE(spdy_stream1.get() != NULL);
925 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
926 spdy_stream1->SetDelegate(&delegate);
928 // Flush the read completion task.
929 base::MessageLoop::current()->RunUntilIdle();
931 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
933 EXPECT_TRUE(session == NULL);
934 EXPECT_EQ(NULL, spdy_stream1.get());
937 // Cause a ping to be sent out while producing a write. The write loop
938 // should handle this properly, i.e. another DoWriteLoop task should
939 // not be posted. This is a regression test for
940 // http://crbug.com/261043 .
941 TEST_P(SpdySessionTest, PingAndWriteLoop) {
942 session_deps_.enable_ping = true;
943 session_deps_.time_func = TheNearFuture;
945 MockConnect connect_data(SYNCHRONOUS, OK);
946 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
947 scoped_ptr<SpdyFrame> req(
948 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
949 MockWrite writes[] = {
950 CreateMockWrite(*req, 0),
951 CreateMockWrite(*write_ping, 1),
955 MockRead(ASYNC, 0, 2) // EOF
958 session_deps_.host_resolver->set_synchronous_mode(true);
960 DeterministicSocketData data(reads, arraysize(reads),
961 writes, arraysize(writes));
962 data.set_connect_data(connect_data);
963 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
965 CreateDeterministicNetworkSession();
967 base::WeakPtr<SpdySession> session =
968 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
970 GURL url(kDefaultURL);
971 base::WeakPtr<SpdyStream> spdy_stream =
972 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
973 session, url, LOWEST, BoundNetLog());
974 test::StreamDelegateDoNothing delegate(spdy_stream);
975 spdy_stream->SetDelegate(&delegate);
977 scoped_ptr<SpdyHeaderBlock> headers(
978 spdy_util_.ConstructGetHeaderBlock(url.spec()));
979 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
981 // Shift time so that a ping will be sent out.
982 g_time_delta = base::TimeDelta::FromSeconds(11);
986 session->CloseSessionOnError(ERR_ABORTED, "Aborting");
989 TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
990 const SpdyStreamId kLastStreamId = 0x7fffffff;
991 session_deps_.host_resolver->set_synchronous_mode(true);
993 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
994 // fixed to allow for two stream ID assignments, and three concurrent
995 // streams. Four streams are started, and two are activated. Verify the
996 // session goes away, and that the created (but not activated) and
997 // stalled streams are aborted. Also verify the activated streams complete,
998 // at which point the session closes.
1000 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
1001 NULL, 0, false, kLastStreamId - 2, MEDIUM, true));
1002 scoped_ptr<SpdyFrame> req2(
1003 spdy_util_.ConstructSpdyGet(NULL, 0, false, kLastStreamId, MEDIUM, true));
1005 MockWrite writes[] = {
1006 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
1009 scoped_ptr<SpdyFrame> resp1(
1010 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId - 2));
1011 scoped_ptr<SpdyFrame> resp2(
1012 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId));
1014 scoped_ptr<SpdyFrame> body1(
1015 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
1016 scoped_ptr<SpdyFrame> body2(
1017 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
1019 MockRead reads[] = {
1020 CreateMockRead(*resp1, 2), CreateMockRead(*resp2, 3),
1021 CreateMockRead(*body1, 4), CreateMockRead(*body2, 5),
1022 MockRead(ASYNC, 0, 6) // EOF
1025 DeterministicSocketData data(
1026 reads, arraysize(reads), writes, arraysize(writes));
1028 MockConnect connect_data(SYNCHRONOUS, OK);
1029 data.set_connect_data(connect_data);
1030 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1032 CreateDeterministicNetworkSession();
1033 base::WeakPtr<SpdySession> session =
1034 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1036 // Fix stream_hi_water_mark_ to allow for two stream activations.
1037 session->stream_hi_water_mark_ = kLastStreamId - 2;
1038 // Fix max_concurrent_streams to allow for three stream creations.
1039 session->max_concurrent_streams_ = 3;
1041 // Create three streams synchronously, and begin a fourth (which is stalled).
1042 GURL url(kDefaultURL);
1043 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1044 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1045 test::StreamDelegateDoNothing delegate1(stream1);
1046 stream1->SetDelegate(&delegate1);
1048 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
1049 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1050 test::StreamDelegateDoNothing delegate2(stream2);
1051 stream2->SetDelegate(&delegate2);
1053 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1054 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1055 test::StreamDelegateDoNothing delegate3(stream3);
1056 stream3->SetDelegate(&delegate3);
1058 SpdyStreamRequest request4;
1059 TestCompletionCallback callback4;
1060 EXPECT_EQ(ERR_IO_PENDING,
1061 request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1066 callback4.callback()));
1068 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1069 EXPECT_EQ(0u, session->num_active_streams());
1070 EXPECT_EQ(3u, session->num_created_streams());
1071 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1073 // Activate stream 1. One ID remains available.
1074 stream1->SendRequestHeaders(
1075 scoped_ptr<SpdyHeaderBlock>(
1076 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1077 NO_MORE_DATA_TO_SEND);
1080 EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1081 EXPECT_EQ(1u, session->num_active_streams());
1082 EXPECT_EQ(2u, session->num_created_streams());
1083 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1085 // Activate stream 2. ID space is exhausted.
1086 stream2->SendRequestHeaders(
1087 scoped_ptr<SpdyHeaderBlock>(
1088 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1089 NO_MORE_DATA_TO_SEND);
1092 // Active streams remain active.
1093 EXPECT_EQ(kLastStreamId, stream2->stream_id());
1094 EXPECT_EQ(2u, session->num_active_streams());
1096 // Session is going away. Created and stalled streams were aborted.
1097 EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session->availability_state_);
1098 EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose());
1099 EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult());
1100 EXPECT_EQ(0u, session->num_created_streams());
1101 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1103 // Read responses on remaining active streams.
1105 EXPECT_EQ(OK, delegate1.WaitForClose());
1106 EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1107 EXPECT_EQ(OK, delegate2.WaitForClose());
1108 EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1110 // Session was destroyed.
1111 base::MessageLoop::current()->RunUntilIdle();
1112 EXPECT_FALSE(session.get());
1115 // Verifies that an unstalled pending stream creation racing with a new stream
1116 // creation doesn't violate the maximum stream concurrency. Regression test for
1117 // crbug.com/373858.
1118 TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) {
1119 session_deps_.host_resolver->set_synchronous_mode(true);
1121 MockRead reads[] = {
1122 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1125 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1127 MockConnect connect_data(SYNCHRONOUS, OK);
1128 data.set_connect_data(connect_data);
1129 session_deps_.socket_factory->AddSocketDataProvider(&data);
1131 CreateNetworkSession();
1132 base::WeakPtr<SpdySession> session =
1133 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1135 // Fix max_concurrent_streams to allow for one open stream.
1136 session->max_concurrent_streams_ = 1;
1138 // Create two streams: one synchronously, and one which stalls.
1139 GURL url(kDefaultURL);
1140 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1141 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1143 SpdyStreamRequest request2;
1144 TestCompletionCallback callback2;
1145 EXPECT_EQ(ERR_IO_PENDING,
1146 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1151 callback2.callback()));
1153 EXPECT_EQ(1u, session->num_created_streams());
1154 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1156 // Cancel the first stream. A callback to unstall the second stream was
1157 // posted. Don't run it yet.
1160 EXPECT_EQ(0u, session->num_created_streams());
1161 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1163 // Create a third stream prior to the second stream's callback.
1164 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1165 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1167 EXPECT_EQ(1u, session->num_created_streams());
1168 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1170 // NOW run the message loop. The unstalled stream will re-stall itself.
1171 base::MessageLoop::current()->RunUntilIdle();
1172 EXPECT_EQ(1u, session->num_created_streams());
1173 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1175 // Cancel the third stream and run the message loop. Verify that the second
1176 // stream creation now completes.
1178 base::MessageLoop::current()->RunUntilIdle();
1180 EXPECT_EQ(1u, session->num_created_streams());
1181 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1182 EXPECT_EQ(OK, callback2.WaitForResult());
1185 TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
1186 session_deps_.host_resolver->set_synchronous_mode(true);
1187 session_deps_.time_func = TheNearFuture;
1189 scoped_ptr<SpdyFrame> req(
1190 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1191 scoped_ptr<SpdyFrame> rst(
1192 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
1194 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
1195 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
1196 scoped_ptr<SpdyFrame> push_a_body(
1197 spdy_util_.ConstructSpdyBodyFrame(2, false));
1198 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
1199 NULL, 0, 4, 1, "http://www.google.com/b.dat"));
1200 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)};
1201 MockRead reads[] = {
1202 CreateMockRead(*push_a, 1), CreateMockRead(*push_a_body, 2),
1203 CreateMockRead(*push_b, 3), MockRead(ASYNC, 0, 5), // EOF
1205 DeterministicSocketData data(
1206 reads, arraysize(reads), writes, arraysize(writes));
1208 MockConnect connect_data(SYNCHRONOUS, OK);
1209 data.set_connect_data(connect_data);
1210 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1212 CreateDeterministicNetworkSession();
1213 base::WeakPtr<SpdySession> session =
1214 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1216 // Process the principal request, and the first push stream request & body.
1217 GURL url(kDefaultURL);
1218 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1219 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1220 test::StreamDelegateDoNothing delegate(spdy_stream);
1221 spdy_stream->SetDelegate(&delegate);
1223 scoped_ptr<SpdyHeaderBlock> headers(
1224 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1225 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1229 // Verify that there is one unclaimed push stream.
1230 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1231 SpdySession::PushedStreamMap::iterator iter =
1232 session->unclaimed_pushed_streams_.find(
1233 GURL("http://www.google.com/a.dat"));
1234 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1236 if (session->flow_control_state_ ==
1237 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1238 // Unclaimed push body consumed bytes from the session window.
1239 EXPECT_EQ(kSpdySessionInitialWindowSize - kUploadDataSize,
1240 session->session_recv_window_size_);
1241 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
1244 // Shift time to expire the push stream. Read the second SYN_STREAM,
1245 // and verify a RST_STREAM was written.
1246 g_time_delta = base::TimeDelta::FromSeconds(301);
1249 // Verify that the second pushed stream evicted the first pushed stream.
1250 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1251 iter = session->unclaimed_pushed_streams_.find(
1252 GURL("http://www.google.com/b.dat"));
1253 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1255 if (session->flow_control_state_ ==
1256 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1257 // Verify that the session window reclaimed the evicted stream body.
1258 EXPECT_EQ(kSpdySessionInitialWindowSize,
1259 session->session_recv_window_size_);
1260 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
1263 // Read and process EOF.
1265 base::MessageLoop::current()->RunUntilIdle();
1266 EXPECT_TRUE(session == NULL);
1269 TEST_P(SpdySessionTest, FailedPing) {
1270 session_deps_.host_resolver->set_synchronous_mode(true);
1272 MockConnect connect_data(SYNCHRONOUS, OK);
1273 MockRead reads[] = {
1274 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1276 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
1277 scoped_ptr<SpdyFrame> goaway(
1278 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping."));
1279 MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)};
1280 StaticSocketDataProvider data(
1281 reads, arraysize(reads), writes, arraysize(writes));
1282 data.set_connect_data(connect_data);
1283 session_deps_.socket_factory->AddSocketDataProvider(&data);
1285 CreateNetworkSession();
1287 base::WeakPtr<SpdySession> session =
1288 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1290 base::WeakPtr<SpdyStream> spdy_stream1 =
1291 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1292 session, test_url_, MEDIUM, BoundNetLog());
1293 ASSERT_TRUE(spdy_stream1.get() != NULL);
1294 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
1295 spdy_stream1->SetDelegate(&delegate);
1297 session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1298 session->set_hung_interval(base::TimeDelta::FromSeconds(0));
1300 // Send a PING frame.
1301 session->WritePingFrame(1, false);
1302 EXPECT_LT(0, session->pings_in_flight());
1303 EXPECT_GE(session->next_ping_id(), 1U);
1304 EXPECT_TRUE(session->check_ping_status_pending());
1306 // Assert session is not closed.
1307 EXPECT_TRUE(session->IsAvailable());
1308 EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams());
1309 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1311 // We set last time we have received any data in 1 sec less than now.
1312 // CheckPingStatus will trigger timeout because hung interval is zero.
1313 base::TimeTicks now = base::TimeTicks::Now();
1314 session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
1315 session->CheckPingStatus(now);
1316 base::MessageLoop::current()->RunUntilIdle();
1318 EXPECT_TRUE(session == NULL);
1319 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1320 EXPECT_EQ(NULL, spdy_stream1.get());
1323 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1324 // settings frame increasing the max concurrent streams by 1. Make
1325 // sure nothing blows up. This is a regression test for
1326 // http://crbug.com/57331 .
1327 TEST_P(SpdySessionTest, OnSettings) {
1328 session_deps_.host_resolver->set_synchronous_mode(true);
1330 const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1332 SettingsMap new_settings;
1333 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1334 new_settings[kSpdySettingsIds] =
1335 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1336 scoped_ptr<SpdyFrame> settings_frame(
1337 spdy_util_.ConstructSpdySettings(new_settings));
1338 MockRead reads[] = {
1339 CreateMockRead(*settings_frame, 0),
1340 MockRead(ASYNC, 0, 1),
1343 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1344 MockWrite writes[] = {
1345 CreateMockWrite(*settings_ack, 2),
1348 DeterministicSocketData data(reads, arraysize(reads),
1349 writes, arraysize(writes));
1350 MockConnect connect_data(SYNCHRONOUS, OK);
1351 data.set_connect_data(connect_data);
1352 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1354 CreateDeterministicNetworkSession();
1356 base::WeakPtr<SpdySession> session =
1357 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1359 // Create the maximum number of concurrent streams.
1360 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1361 base::WeakPtr<SpdyStream> spdy_stream =
1362 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1363 session, test_url_, MEDIUM, BoundNetLog());
1364 ASSERT_TRUE(spdy_stream != NULL);
1367 StreamReleaserCallback stream_releaser;
1368 SpdyStreamRequest request;
1369 ASSERT_EQ(ERR_IO_PENDING,
1370 request.StartRequest(
1371 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1373 stream_releaser.MakeCallback(&request)));
1377 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1380 if (spdy_util_.spdy_version() >= SPDY4) {
1381 // Allow the SETTINGS+ACK to write, so the session finishes draining.
1384 base::MessageLoop::current()->RunUntilIdle();
1385 EXPECT_TRUE(session == NULL);
1388 // Start with a persisted value for max concurrent streams. Receive a
1389 // settings frame increasing the max concurrent streams by 1 and which
1390 // also clears the persisted data. Verify that persisted data is
1392 TEST_P(SpdySessionTest, ClearSettings) {
1393 if (spdy_util_.spdy_version() >= SPDY4) {
1394 // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1395 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4.
1398 session_deps_.host_resolver->set_synchronous_mode(true);
1400 SettingsMap new_settings;
1401 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1402 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1403 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1404 scoped_ptr<SpdyFrame> settings_frame(
1405 spdy_util_.ConstructSpdySettings(new_settings));
1406 uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1407 test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1408 MockRead reads[] = {
1409 CreateMockRead(*settings_frame, 0),
1410 MockRead(ASYNC, 0, 1),
1413 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
1414 MockConnect connect_data(SYNCHRONOUS, OK);
1415 data.set_connect_data(connect_data);
1416 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1418 CreateDeterministicNetworkSession();
1420 // Initialize the SpdySetting with the default.
1421 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1422 test_host_port_pair_,
1423 SETTINGS_MAX_CONCURRENT_STREAMS,
1424 SETTINGS_FLAG_PLEASE_PERSIST,
1425 kInitialMaxConcurrentStreams);
1428 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1429 test_host_port_pair_).empty());
1431 base::WeakPtr<SpdySession> session =
1432 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1434 // Create the maximum number of concurrent streams.
1435 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1436 base::WeakPtr<SpdyStream> spdy_stream =
1437 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1438 session, test_url_, MEDIUM, BoundNetLog());
1439 ASSERT_TRUE(spdy_stream != NULL);
1442 StreamReleaserCallback stream_releaser;
1444 SpdyStreamRequest request;
1445 ASSERT_EQ(ERR_IO_PENDING,
1446 request.StartRequest(
1447 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1449 stream_releaser.MakeCallback(&request)));
1453 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1455 // Make sure that persisted data is cleared.
1457 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1458 test_host_port_pair_).empty());
1460 // Make sure session's max_concurrent_streams is correct.
1461 EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1462 session->max_concurrent_streams());
1465 EXPECT_TRUE(session == NULL);
1468 // Start with max concurrent streams set to 1. Request two streams.
1469 // When the first completes, have the callback close its stream, which
1470 // should trigger the second stream creation. Then cancel that one
1471 // immediately. Don't crash. This is a regression test for
1472 // http://crbug.com/63532 .
1473 TEST_P(SpdySessionTest, CancelPendingCreateStream) {
1474 session_deps_.host_resolver->set_synchronous_mode(true);
1476 MockRead reads[] = {
1477 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1480 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1481 MockConnect connect_data(SYNCHRONOUS, OK);
1483 data.set_connect_data(connect_data);
1484 session_deps_.socket_factory->AddSocketDataProvider(&data);
1486 CreateNetworkSession();
1488 // Initialize the SpdySetting with 1 max concurrent streams.
1489 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1490 test_host_port_pair_,
1491 SETTINGS_MAX_CONCURRENT_STREAMS,
1492 SETTINGS_FLAG_PLEASE_PERSIST,
1495 base::WeakPtr<SpdySession> session =
1496 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1498 // Leave room for only one more stream to be created.
1499 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1500 base::WeakPtr<SpdyStream> spdy_stream =
1501 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1502 session, test_url_, MEDIUM, BoundNetLog());
1503 ASSERT_TRUE(spdy_stream != NULL);
1506 // Create 2 more streams. First will succeed. Second will be pending.
1507 base::WeakPtr<SpdyStream> spdy_stream1 =
1508 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1509 session, test_url_, MEDIUM, BoundNetLog());
1510 ASSERT_TRUE(spdy_stream1.get() != NULL);
1512 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1513 // a valgrind error if the callback is invoked when it's not supposed to be.
1514 scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
1516 SpdyStreamRequest request;
1517 ASSERT_EQ(ERR_IO_PENDING,
1518 request.StartRequest(
1519 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1521 callback->callback()));
1523 // Release the first one, this will allow the second to be created.
1524 spdy_stream1->Cancel();
1525 EXPECT_EQ(NULL, spdy_stream1.get());
1527 request.CancelRequest();
1530 // Should not crash when running the pending callback.
1531 base::MessageLoop::current()->RunUntilIdle();
1534 TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
1535 session_deps_.host_resolver->set_synchronous_mode(true);
1537 MockRead reads[] = {
1538 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1541 SettingsMap settings;
1542 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
1543 const SpdySettingsIds kSpdySettingsIds2 = SETTINGS_INITIAL_WINDOW_SIZE;
1544 const uint32 kInitialRecvWindowSize = 10 * 1024 * 1024;
1545 settings[kSpdySettingsIds1] =
1546 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
1547 if (spdy_util_.spdy_version() >= SPDY3) {
1548 settings[kSpdySettingsIds2] =
1549 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialRecvWindowSize);
1551 MockConnect connect_data(SYNCHRONOUS, OK);
1552 scoped_ptr<SpdyFrame> settings_frame(
1553 spdy_util_.ConstructSpdySettings(settings));
1554 scoped_ptr<SpdyFrame> initial_window_update(
1555 spdy_util_.ConstructSpdyWindowUpdate(
1556 kSessionFlowControlStreamId,
1557 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
1558 std::vector<MockWrite> writes;
1559 if (GetParam() == kProtoSPDY4) {
1562 kHttp2ConnectionHeaderPrefix,
1563 kHttp2ConnectionHeaderPrefixSize));
1565 writes.push_back(CreateMockWrite(*settings_frame));
1566 if (GetParam() >= kProtoSPDY31) {
1567 writes.push_back(CreateMockWrite(*initial_window_update));
1570 SettingsMap server_settings;
1571 const uint32 initial_max_concurrent_streams = 1;
1572 server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1573 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1574 initial_max_concurrent_streams);
1575 scoped_ptr<SpdyFrame> server_settings_frame(
1576 spdy_util_.ConstructSpdySettings(server_settings));
1577 if (GetParam() <= kProtoSPDY31) {
1578 writes.push_back(CreateMockWrite(*server_settings_frame));
1581 session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize;
1583 StaticSocketDataProvider data(reads, arraysize(reads),
1584 vector_as_array(&writes), writes.size());
1585 data.set_connect_data(connect_data);
1586 session_deps_.socket_factory->AddSocketDataProvider(&data);
1588 CreateNetworkSession();
1590 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1591 test_host_port_pair_,
1592 SETTINGS_MAX_CONCURRENT_STREAMS,
1593 SETTINGS_FLAG_PLEASE_PERSIST,
1594 initial_max_concurrent_streams);
1596 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1597 pool_peer.SetEnableSendingInitialData(true);
1599 base::WeakPtr<SpdySession> session =
1600 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1602 base::MessageLoop::current()->RunUntilIdle();
1603 EXPECT_TRUE(data.at_write_eof());
1606 TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
1607 CreateNetworkSession();
1609 base::WeakPtr<HttpServerProperties> test_http_server_properties =
1610 spdy_session_pool_->http_server_properties();
1611 SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
1612 test_http_server_properties->SetSpdySetting(
1613 test_host_port_pair_,
1614 SETTINGS_MAX_CONCURRENT_STREAMS,
1615 SETTINGS_FLAG_PLEASE_PERSIST,
1617 EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
1618 test_host_port_pair_).size());
1619 spdy_session_pool_->OnIPAddressChanged();
1620 EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
1621 test_host_port_pair_).size());
1624 TEST_P(SpdySessionTest, Initialize) {
1625 CapturingBoundNetLog log;
1626 session_deps_.net_log = log.bound().net_log();
1627 session_deps_.host_resolver->set_synchronous_mode(true);
1629 MockConnect connect_data(SYNCHRONOUS, OK);
1630 MockRead reads[] = {
1631 MockRead(ASYNC, 0, 0) // EOF
1634 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1635 data.set_connect_data(connect_data);
1636 session_deps_.socket_factory->AddSocketDataProvider(&data);
1638 CreateNetworkSession();
1640 base::WeakPtr<SpdySession> session =
1641 CreateInsecureSpdySession(http_session_, key_, log.bound());
1642 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1644 // Flush the read completion task.
1645 base::MessageLoop::current()->RunUntilIdle();
1647 net::CapturingNetLog::CapturedEntryList entries;
1648 log.GetEntries(&entries);
1649 EXPECT_LT(0u, entries.size());
1651 // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly.
1652 int pos = net::ExpectLogContainsSomewhere(
1654 net::NetLog::TYPE_SPDY_SESSION_INITIALIZED,
1655 net::NetLog::PHASE_NONE);
1658 CapturingNetLog::CapturedEntry entry = entries[pos];
1659 NetLog::Source socket_source;
1660 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1662 EXPECT_TRUE(socket_source.IsValid());
1663 EXPECT_NE(log.bound().source().id, socket_source.id);
1666 TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
1667 session_deps_.host_resolver->set_synchronous_mode(true);
1669 MockConnect connect_data(SYNCHRONOUS, OK);
1670 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
1671 MockRead reads[] = {
1672 CreateMockRead(*goaway),
1673 MockRead(SYNCHRONOUS, 0, 0) // EOF
1676 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1677 data.set_connect_data(connect_data);
1678 session_deps_.socket_factory->AddSocketDataProvider(&data);
1680 CreateNetworkSession();
1682 CapturingBoundNetLog log;
1683 base::WeakPtr<SpdySession> session =
1684 CreateInsecureSpdySession(http_session_, key_, log.bound());
1685 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1687 // Flush the read completion task.
1688 base::MessageLoop::current()->RunUntilIdle();
1690 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1691 EXPECT_TRUE(session == NULL);
1693 // Check that the NetLog was filled reasonably.
1694 net::CapturingNetLog::CapturedEntryList entries;
1695 log.GetEntries(&entries);
1696 EXPECT_LT(0u, entries.size());
1698 // Check that we logged SPDY_SESSION_CLOSE correctly.
1699 int pos = net::ExpectLogContainsSomewhere(
1701 net::NetLog::TYPE_SPDY_SESSION_CLOSE,
1702 net::NetLog::PHASE_NONE);
1704 if (pos < static_cast<int>(entries.size())) {
1705 CapturingNetLog::CapturedEntry entry = entries[pos];
1707 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1708 EXPECT_EQ(OK, error_code);
1714 TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1715 session_deps_.host_resolver->set_synchronous_mode(true);
1717 MockConnect connect_data(SYNCHRONOUS, OK);
1718 MockRead reads[] = {
1719 MockRead(SYNCHRONOUS, 0, 0) // EOF
1722 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1723 data.set_connect_data(connect_data);
1724 session_deps_.socket_factory->AddSocketDataProvider(&data);
1726 CreateNetworkSession();
1728 CapturingBoundNetLog log;
1729 base::WeakPtr<SpdySession> session =
1730 CreateInsecureSpdySession(http_session_, key_, log.bound());
1731 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1733 // Flush the read completion task.
1734 base::MessageLoop::current()->RunUntilIdle();
1736 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1737 EXPECT_TRUE(session == NULL);
1739 // Check that the NetLog was filled reasonably.
1740 net::CapturingNetLog::CapturedEntryList entries;
1741 log.GetEntries(&entries);
1742 EXPECT_LT(0u, entries.size());
1744 // Check that we logged SPDY_SESSION_CLOSE correctly.
1746 net::ExpectLogContainsSomewhere(entries,
1748 net::NetLog::TYPE_SPDY_SESSION_CLOSE,
1749 net::NetLog::PHASE_NONE);
1751 if (pos < static_cast<int>(entries.size())) {
1752 CapturingNetLog::CapturedEntry entry = entries[pos];
1754 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1755 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1761 TEST_P(SpdySessionTest, SynCompressionHistograms) {
1762 session_deps_.enable_compression = true;
1764 scoped_ptr<SpdyFrame> req(
1765 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, MEDIUM, true));
1766 MockWrite writes[] = {
1767 CreateMockWrite(*req, 0),
1769 MockRead reads[] = {
1770 MockRead(ASYNC, 0, 1) // EOF
1772 DeterministicSocketData data(reads, arraysize(reads),
1773 writes, arraysize(writes));
1774 MockConnect connect_data(SYNCHRONOUS, OK);
1775 data.set_connect_data(connect_data);
1776 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1778 CreateDeterministicNetworkSession();
1779 base::WeakPtr<SpdySession> session =
1780 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1782 GURL url(kDefaultURL);
1783 base::WeakPtr<SpdyStream> spdy_stream =
1784 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1785 session, url, MEDIUM, BoundNetLog());
1786 test::StreamDelegateDoNothing delegate(spdy_stream);
1787 spdy_stream->SetDelegate(&delegate);
1789 scoped_ptr<SpdyHeaderBlock> headers(
1790 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1791 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1792 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1794 // Write request headers & capture resulting histogram update.
1795 base::HistogramTester histogram_tester;
1798 // Regression test of compression performance under the request fixture.
1799 switch (spdy_util_.spdy_version()) {
1801 histogram_tester.ExpectBucketCount(
1802 "Net.SpdySynStreamCompressionPercentage", 0, 1);
1805 histogram_tester.ExpectBucketCount(
1806 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1809 histogram_tester.ExpectBucketCount(
1810 "Net.SpdySynStreamCompressionPercentage", 82, 1);
1813 histogram_tester.ExpectBucketCount(
1814 "Net.SpdySynStreamCompressionPercentage", 82, 1);
1820 // Read and process EOF.
1822 base::MessageLoop::current()->RunUntilIdle();
1823 EXPECT_TRUE(session == NULL);
1826 // Queue up a low-priority SYN_STREAM followed by a high-priority
1827 // one. The high priority one should still send first and receive
1829 TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1830 // Construct the request.
1831 MockConnect connect_data(SYNCHRONOUS, OK);
1832 scoped_ptr<SpdyFrame> req_highest(
1833 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true));
1834 scoped_ptr<SpdyFrame> req_lowest(
1835 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1836 MockWrite writes[] = {
1837 CreateMockWrite(*req_highest, 0),
1838 CreateMockWrite(*req_lowest, 1),
1841 scoped_ptr<SpdyFrame> resp_highest(
1842 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1843 scoped_ptr<SpdyFrame> body_highest(
1844 spdy_util_.ConstructSpdyBodyFrame(1, true));
1845 scoped_ptr<SpdyFrame> resp_lowest(
1846 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1847 scoped_ptr<SpdyFrame> body_lowest(
1848 spdy_util_.ConstructSpdyBodyFrame(3, true));
1849 MockRead reads[] = {
1850 CreateMockRead(*resp_highest, 2),
1851 CreateMockRead(*body_highest, 3),
1852 CreateMockRead(*resp_lowest, 4),
1853 CreateMockRead(*body_lowest, 5),
1854 MockRead(ASYNC, 0, 6) // EOF
1857 session_deps_.host_resolver->set_synchronous_mode(true);
1859 DeterministicSocketData data(reads, arraysize(reads),
1860 writes, arraysize(writes));
1861 data.set_connect_data(connect_data);
1862 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1864 CreateDeterministicNetworkSession();
1866 base::WeakPtr<SpdySession> session =
1867 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1869 GURL url(kDefaultURL);
1871 base::WeakPtr<SpdyStream> spdy_stream_lowest =
1872 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1873 session, url, LOWEST, BoundNetLog());
1874 ASSERT_TRUE(spdy_stream_lowest);
1875 EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1876 test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1877 spdy_stream_lowest->SetDelegate(&delegate_lowest);
1879 base::WeakPtr<SpdyStream> spdy_stream_highest =
1880 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1881 session, url, HIGHEST, BoundNetLog());
1882 ASSERT_TRUE(spdy_stream_highest);
1883 EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1884 test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1885 spdy_stream_highest->SetDelegate(&delegate_highest);
1887 // Queue the lower priority one first.
1889 scoped_ptr<SpdyHeaderBlock> headers_lowest(
1890 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1891 spdy_stream_lowest->SendRequestHeaders(
1892 headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1893 EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1895 scoped_ptr<SpdyHeaderBlock> headers_highest(
1896 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1897 spdy_stream_highest->SendRequestHeaders(
1898 headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1899 EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1903 EXPECT_FALSE(spdy_stream_lowest);
1904 EXPECT_FALSE(spdy_stream_highest);
1905 EXPECT_EQ(3u, delegate_lowest.stream_id());
1906 EXPECT_EQ(1u, delegate_highest.stream_id());
1909 TEST_P(SpdySessionTest, CancelStream) {
1910 MockConnect connect_data(SYNCHRONOUS, OK);
1911 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1912 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1913 scoped_ptr<SpdyFrame> req2(
1914 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1915 MockWrite writes[] = {
1916 CreateMockWrite(*req2, 0),
1919 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1920 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1921 MockRead reads[] = {
1922 CreateMockRead(*resp2, 1),
1923 CreateMockRead(*body2, 2),
1924 MockRead(ASYNC, 0, 3) // EOF
1927 session_deps_.host_resolver->set_synchronous_mode(true);
1929 DeterministicSocketData data(reads, arraysize(reads),
1930 writes, arraysize(writes));
1931 data.set_connect_data(connect_data);
1932 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1934 CreateDeterministicNetworkSession();
1936 base::WeakPtr<SpdySession> session =
1937 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1939 GURL url1(kDefaultURL);
1940 base::WeakPtr<SpdyStream> spdy_stream1 =
1941 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1942 session, url1, HIGHEST, BoundNetLog());
1943 ASSERT_TRUE(spdy_stream1.get() != NULL);
1944 EXPECT_EQ(0u, spdy_stream1->stream_id());
1945 test::StreamDelegateDoNothing delegate1(spdy_stream1);
1946 spdy_stream1->SetDelegate(&delegate1);
1948 GURL url2(kDefaultURL);
1949 base::WeakPtr<SpdyStream> spdy_stream2 =
1950 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1951 session, url2, LOWEST, BoundNetLog());
1952 ASSERT_TRUE(spdy_stream2.get() != NULL);
1953 EXPECT_EQ(0u, spdy_stream2->stream_id());
1954 test::StreamDelegateDoNothing delegate2(spdy_stream2);
1955 spdy_stream2->SetDelegate(&delegate2);
1957 scoped_ptr<SpdyHeaderBlock> headers(
1958 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1959 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1960 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1962 scoped_ptr<SpdyHeaderBlock> headers2(
1963 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1964 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1965 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1967 EXPECT_EQ(0u, spdy_stream1->stream_id());
1969 spdy_stream1->Cancel();
1970 EXPECT_EQ(NULL, spdy_stream1.get());
1972 EXPECT_EQ(0u, delegate1.stream_id());
1976 EXPECT_EQ(0u, delegate1.stream_id());
1977 EXPECT_EQ(1u, delegate2.stream_id());
1979 spdy_stream2->Cancel();
1980 EXPECT_EQ(NULL, spdy_stream2.get());
1983 // Create two streams that are set to re-close themselves on close,
1984 // and then close the session. Nothing should blow up. Also a
1985 // regression test for http://crbug.com/139518 .
1986 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1987 session_deps_.host_resolver->set_synchronous_mode(true);
1989 MockConnect connect_data(SYNCHRONOUS, OK);
1991 // No actual data will be sent.
1992 MockWrite writes[] = {
1993 MockWrite(ASYNC, 0, 1) // EOF
1996 MockRead reads[] = {
1997 MockRead(ASYNC, 0, 0) // EOF
1999 DeterministicSocketData data(reads, arraysize(reads),
2000 writes, arraysize(writes));
2001 data.set_connect_data(connect_data);
2002 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2004 CreateDeterministicNetworkSession();
2006 base::WeakPtr<SpdySession> session =
2007 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2009 GURL url1(kDefaultURL);
2010 base::WeakPtr<SpdyStream> spdy_stream1 =
2011 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2012 session, url1, HIGHEST, BoundNetLog());
2013 ASSERT_TRUE(spdy_stream1.get() != NULL);
2014 EXPECT_EQ(0u, spdy_stream1->stream_id());
2016 GURL url2(kDefaultURL);
2017 base::WeakPtr<SpdyStream> spdy_stream2 =
2018 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2019 session, url2, LOWEST, BoundNetLog());
2020 ASSERT_TRUE(spdy_stream2.get() != NULL);
2021 EXPECT_EQ(0u, spdy_stream2->stream_id());
2023 test::ClosingDelegate delegate1(spdy_stream1);
2024 spdy_stream1->SetDelegate(&delegate1);
2026 test::ClosingDelegate delegate2(spdy_stream2);
2027 spdy_stream2->SetDelegate(&delegate2);
2029 scoped_ptr<SpdyHeaderBlock> headers(
2030 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2031 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2032 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2034 scoped_ptr<SpdyHeaderBlock> headers2(
2035 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2036 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2037 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2039 // Ensure that the streams have not yet been activated and assigned an id.
2040 EXPECT_EQ(0u, spdy_stream1->stream_id());
2041 EXPECT_EQ(0u, spdy_stream2->stream_id());
2043 // Ensure we don't crash while closing the session.
2044 session->CloseSessionOnError(ERR_ABORTED, std::string());
2046 EXPECT_EQ(NULL, spdy_stream1.get());
2047 EXPECT_EQ(NULL, spdy_stream2.get());
2049 EXPECT_TRUE(delegate1.StreamIsClosed());
2050 EXPECT_TRUE(delegate2.StreamIsClosed());
2052 base::MessageLoop::current()->RunUntilIdle();
2053 EXPECT_TRUE(session == NULL);
2056 // Create two streams that are set to close each other on close, and
2057 // then close the session. Nothing should blow up.
2058 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
2059 session_deps_.host_resolver->set_synchronous_mode(true);
2061 MockConnect connect_data(SYNCHRONOUS, OK);
2063 // No actual data will be sent.
2064 MockWrite writes[] = {
2065 MockWrite(ASYNC, 0, 1) // EOF
2068 MockRead reads[] = {
2069 MockRead(ASYNC, 0, 0) // EOF
2071 DeterministicSocketData data(reads, arraysize(reads),
2072 writes, arraysize(writes));
2073 data.set_connect_data(connect_data);
2074 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2076 CreateDeterministicNetworkSession();
2078 base::WeakPtr<SpdySession> session =
2079 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2081 GURL url1(kDefaultURL);
2082 base::WeakPtr<SpdyStream> spdy_stream1 =
2083 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2084 session, url1, HIGHEST, BoundNetLog());
2085 ASSERT_TRUE(spdy_stream1.get() != NULL);
2086 EXPECT_EQ(0u, spdy_stream1->stream_id());
2088 GURL url2(kDefaultURL);
2089 base::WeakPtr<SpdyStream> spdy_stream2 =
2090 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2091 session, url2, LOWEST, BoundNetLog());
2092 ASSERT_TRUE(spdy_stream2.get() != NULL);
2093 EXPECT_EQ(0u, spdy_stream2->stream_id());
2095 // Make |spdy_stream1| close |spdy_stream2|.
2096 test::ClosingDelegate delegate1(spdy_stream2);
2097 spdy_stream1->SetDelegate(&delegate1);
2099 // Make |spdy_stream2| close |spdy_stream1|.
2100 test::ClosingDelegate delegate2(spdy_stream1);
2101 spdy_stream2->SetDelegate(&delegate2);
2103 scoped_ptr<SpdyHeaderBlock> headers(
2104 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2105 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2106 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2108 scoped_ptr<SpdyHeaderBlock> headers2(
2109 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2110 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2111 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2113 // Ensure that the streams have not yet been activated and assigned an id.
2114 EXPECT_EQ(0u, spdy_stream1->stream_id());
2115 EXPECT_EQ(0u, spdy_stream2->stream_id());
2117 // Ensure we don't crash while closing the session.
2118 session->CloseSessionOnError(ERR_ABORTED, std::string());
2120 EXPECT_EQ(NULL, spdy_stream1.get());
2121 EXPECT_EQ(NULL, spdy_stream2.get());
2123 EXPECT_TRUE(delegate1.StreamIsClosed());
2124 EXPECT_TRUE(delegate2.StreamIsClosed());
2126 base::MessageLoop::current()->RunUntilIdle();
2127 EXPECT_TRUE(session == NULL);
2130 // Create two streams that are set to re-close themselves on close,
2131 // activate them, and then close the session. Nothing should blow up.
2132 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
2133 session_deps_.host_resolver->set_synchronous_mode(true);
2135 MockConnect connect_data(SYNCHRONOUS, OK);
2137 scoped_ptr<SpdyFrame> req1(
2138 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2139 scoped_ptr<SpdyFrame> req2(
2140 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2141 MockWrite writes[] = {
2142 CreateMockWrite(*req1, 0),
2143 CreateMockWrite(*req2, 1),
2146 MockRead reads[] = {
2147 MockRead(ASYNC, 0, 2) // EOF
2150 DeterministicSocketData data(reads, arraysize(reads),
2151 writes, arraysize(writes));
2152 data.set_connect_data(connect_data);
2153 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2155 CreateDeterministicNetworkSession();
2157 base::WeakPtr<SpdySession> session =
2158 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2160 GURL url1(kDefaultURL);
2161 base::WeakPtr<SpdyStream> spdy_stream1 =
2162 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2163 session, url1, MEDIUM, BoundNetLog());
2164 ASSERT_TRUE(spdy_stream1.get() != NULL);
2165 EXPECT_EQ(0u, spdy_stream1->stream_id());
2167 GURL url2(kDefaultURL);
2168 base::WeakPtr<SpdyStream> spdy_stream2 =
2169 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2170 session, url2, MEDIUM, BoundNetLog());
2171 ASSERT_TRUE(spdy_stream2.get() != NULL);
2172 EXPECT_EQ(0u, spdy_stream2->stream_id());
2174 test::ClosingDelegate delegate1(spdy_stream1);
2175 spdy_stream1->SetDelegate(&delegate1);
2177 test::ClosingDelegate delegate2(spdy_stream2);
2178 spdy_stream2->SetDelegate(&delegate2);
2180 scoped_ptr<SpdyHeaderBlock> headers(
2181 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2182 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2183 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2185 scoped_ptr<SpdyHeaderBlock> headers2(
2186 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2187 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2188 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2190 // Ensure that the streams have not yet been activated and assigned an id.
2191 EXPECT_EQ(0u, spdy_stream1->stream_id());
2192 EXPECT_EQ(0u, spdy_stream2->stream_id());
2196 EXPECT_EQ(1u, spdy_stream1->stream_id());
2197 EXPECT_EQ(3u, spdy_stream2->stream_id());
2199 // Ensure we don't crash while closing the session.
2200 session->CloseSessionOnError(ERR_ABORTED, std::string());
2202 EXPECT_EQ(NULL, spdy_stream1.get());
2203 EXPECT_EQ(NULL, spdy_stream2.get());
2205 EXPECT_TRUE(delegate1.StreamIsClosed());
2206 EXPECT_TRUE(delegate2.StreamIsClosed());
2208 base::MessageLoop::current()->RunUntilIdle();
2209 EXPECT_TRUE(session == NULL);
2212 // Create two streams that are set to close each other on close,
2213 // activate them, and then close the session. Nothing should blow up.
2214 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2215 session_deps_.host_resolver->set_synchronous_mode(true);
2217 MockConnect connect_data(SYNCHRONOUS, OK);
2219 scoped_ptr<SpdyFrame> req1(
2220 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2221 scoped_ptr<SpdyFrame> req2(
2222 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2223 MockWrite writes[] = {
2224 CreateMockWrite(*req1, 0),
2225 CreateMockWrite(*req2, 1),
2228 MockRead reads[] = {
2229 MockRead(ASYNC, 0, 2) // EOF
2232 DeterministicSocketData data(reads, arraysize(reads),
2233 writes, arraysize(writes));
2234 data.set_connect_data(connect_data);
2235 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2237 CreateDeterministicNetworkSession();
2239 base::WeakPtr<SpdySession> session =
2240 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2242 GURL url1(kDefaultURL);
2243 base::WeakPtr<SpdyStream> spdy_stream1 =
2244 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2245 session, url1, MEDIUM, BoundNetLog());
2246 ASSERT_TRUE(spdy_stream1.get() != NULL);
2247 EXPECT_EQ(0u, spdy_stream1->stream_id());
2249 GURL url2(kDefaultURL);
2250 base::WeakPtr<SpdyStream> spdy_stream2 =
2251 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2252 session, url2, MEDIUM, BoundNetLog());
2253 ASSERT_TRUE(spdy_stream2.get() != NULL);
2254 EXPECT_EQ(0u, spdy_stream2->stream_id());
2256 // Make |spdy_stream1| close |spdy_stream2|.
2257 test::ClosingDelegate delegate1(spdy_stream2);
2258 spdy_stream1->SetDelegate(&delegate1);
2260 // Make |spdy_stream2| close |spdy_stream1|.
2261 test::ClosingDelegate delegate2(spdy_stream1);
2262 spdy_stream2->SetDelegate(&delegate2);
2264 scoped_ptr<SpdyHeaderBlock> headers(
2265 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2266 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2267 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2269 scoped_ptr<SpdyHeaderBlock> headers2(
2270 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2271 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2272 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2274 // Ensure that the streams have not yet been activated and assigned an id.
2275 EXPECT_EQ(0u, spdy_stream1->stream_id());
2276 EXPECT_EQ(0u, spdy_stream2->stream_id());
2280 EXPECT_EQ(1u, spdy_stream1->stream_id());
2281 EXPECT_EQ(3u, spdy_stream2->stream_id());
2283 // Ensure we don't crash while closing the session.
2284 session->CloseSessionOnError(ERR_ABORTED, std::string());
2286 EXPECT_EQ(NULL, spdy_stream1.get());
2287 EXPECT_EQ(NULL, spdy_stream2.get());
2289 EXPECT_TRUE(delegate1.StreamIsClosed());
2290 EXPECT_TRUE(delegate2.StreamIsClosed());
2292 base::MessageLoop::current()->RunUntilIdle();
2293 EXPECT_TRUE(session == NULL);
2296 // Delegate that closes a given session when the stream is closed.
2297 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2299 SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2300 const base::WeakPtr<SpdySession>& session_to_close)
2301 : StreamDelegateDoNothing(stream),
2302 session_to_close_(session_to_close) {}
2304 ~SessionClosingDelegate() override {}
2306 void OnClose(int status) override {
2307 session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2311 base::WeakPtr<SpdySession> session_to_close_;
2314 // Close an activated stream that closes its session. Nothing should
2315 // blow up. This is a regression test for http://crbug.com/263691 .
2316 TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2317 session_deps_.host_resolver->set_synchronous_mode(true);
2319 MockConnect connect_data(SYNCHRONOUS, OK);
2321 scoped_ptr<SpdyFrame> req(
2322 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2323 scoped_ptr<SpdyFrame> rst(
2324 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2325 scoped_ptr<SpdyFrame> goaway(
2326 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2327 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2328 // despite being queued second.
2329 MockWrite writes[] = {
2330 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 1),
2331 CreateMockWrite(*rst, 2),
2334 MockRead reads[] = {
2335 MockRead(ASYNC, 0, 3) // EOF
2337 DeterministicSocketData data(reads, arraysize(reads),
2338 writes, arraysize(writes));
2339 data.set_connect_data(connect_data);
2340 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2342 CreateDeterministicNetworkSession();
2344 base::WeakPtr<SpdySession> session =
2345 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2347 GURL url(kDefaultURL);
2348 base::WeakPtr<SpdyStream> spdy_stream =
2349 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2350 session, url, MEDIUM, BoundNetLog());
2351 ASSERT_TRUE(spdy_stream.get() != NULL);
2352 EXPECT_EQ(0u, spdy_stream->stream_id());
2354 SessionClosingDelegate delegate(spdy_stream, session);
2355 spdy_stream->SetDelegate(&delegate);
2357 scoped_ptr<SpdyHeaderBlock> headers(
2358 spdy_util_.ConstructGetHeaderBlock(url.spec()));
2359 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2360 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2362 EXPECT_EQ(0u, spdy_stream->stream_id());
2366 EXPECT_EQ(1u, spdy_stream->stream_id());
2368 // Ensure we don't crash while closing the stream (which closes the
2370 spdy_stream->Cancel();
2372 EXPECT_EQ(NULL, spdy_stream.get());
2373 EXPECT_TRUE(delegate.StreamIsClosed());
2375 data.RunFor(2); // Write the RST_STREAM & GOAWAY.
2376 base::MessageLoop::current()->RunUntilIdle();
2377 EXPECT_TRUE(session == NULL);
2380 TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2381 session_deps_.host_resolver->set_synchronous_mode(true);
2383 MockConnect connect_data(SYNCHRONOUS, OK);
2385 // No actual data will be sent.
2386 MockWrite writes[] = {
2387 MockWrite(ASYNC, 0, 1) // EOF
2390 MockRead reads[] = {
2391 MockRead(ASYNC, 0, 0) // EOF
2393 DeterministicSocketData data(reads, arraysize(reads),
2394 writes, arraysize(writes));
2395 data.set_connect_data(connect_data);
2396 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2398 // Load a cert that is valid for:
2402 base::FilePath certs_dir = GetTestCertsDirectory();
2403 scoped_refptr<X509Certificate> test_cert(
2404 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2405 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2407 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2408 ssl.cert = test_cert;
2409 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2411 CreateDeterministicNetworkSession();
2413 base::WeakPtr<SpdySession> session =
2414 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2416 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2417 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2418 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
2419 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2422 TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2423 session_deps_.host_resolver->set_synchronous_mode(true);
2425 MockConnect connect_data(SYNCHRONOUS, OK);
2427 // No actual data will be sent.
2428 MockWrite writes[] = {
2429 MockWrite(ASYNC, 0, 1) // EOF
2432 MockRead reads[] = {
2433 MockRead(ASYNC, 0, 0) // EOF
2435 DeterministicSocketData data(reads, arraysize(reads),
2436 writes, arraysize(writes));
2437 data.set_connect_data(connect_data);
2438 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2440 // Load a cert that is valid for:
2444 base::FilePath certs_dir = GetTestCertsDirectory();
2445 scoped_refptr<X509Certificate> test_cert(
2446 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2447 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2449 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2450 ssl.channel_id_sent = true;
2451 ssl.cert = test_cert;
2452 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2454 CreateDeterministicNetworkSession();
2456 base::WeakPtr<SpdySession> session =
2457 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2459 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2460 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2461 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2462 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2465 TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2466 // TODO(rtenneti): Define a helper class/methods and move the common code in
2468 MockConnect connect_data(SYNCHRONOUS, OK);
2470 SettingsMap new_settings;
2471 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2472 const uint32 max_concurrent_streams = 1;
2473 new_settings[kSpdySettingsIds1] =
2474 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2476 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
2477 scoped_ptr<SpdyFrame> req1(
2478 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2479 scoped_ptr<SpdyFrame> req2(
2480 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
2481 scoped_ptr<SpdyFrame> req3(
2482 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
2483 MockWrite writes[] = {
2484 CreateMockWrite(*settings_ack, 1),
2485 CreateMockWrite(*req1, 2),
2486 CreateMockWrite(*req2, 5),
2487 CreateMockWrite(*req3, 8),
2490 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2492 scoped_ptr<SpdyFrame> settings_frame(
2493 spdy_util_.ConstructSpdySettings(new_settings));
2495 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2496 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2498 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2499 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2501 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
2502 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2504 MockRead reads[] = {
2505 CreateMockRead(*settings_frame),
2506 CreateMockRead(*resp1, 3),
2507 CreateMockRead(*body1, 4),
2508 CreateMockRead(*resp2, 6),
2509 CreateMockRead(*body2, 7),
2510 CreateMockRead(*resp3, 9),
2511 CreateMockRead(*body3, 10),
2512 MockRead(ASYNC, 0, 11) // EOF
2515 DeterministicSocketData data(reads, arraysize(reads),
2516 writes, arraysize(writes));
2517 data.set_connect_data(connect_data);
2518 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2520 CreateDeterministicNetworkSession();
2522 base::WeakPtr<SpdySession> session =
2523 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2525 // Read the settings frame.
2528 GURL url1(kDefaultURL);
2529 base::WeakPtr<SpdyStream> spdy_stream1 =
2530 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2531 session, url1, LOWEST, BoundNetLog());
2532 ASSERT_TRUE(spdy_stream1.get() != NULL);
2533 EXPECT_EQ(0u, spdy_stream1->stream_id());
2534 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2535 spdy_stream1->SetDelegate(&delegate1);
2537 TestCompletionCallback callback2;
2538 GURL url2(kDefaultURL);
2539 SpdyStreamRequest request2;
2540 ASSERT_EQ(ERR_IO_PENDING,
2541 request2.StartRequest(
2542 SPDY_REQUEST_RESPONSE_STREAM,
2543 session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2545 TestCompletionCallback callback3;
2546 GURL url3(kDefaultURL);
2547 SpdyStreamRequest request3;
2548 ASSERT_EQ(ERR_IO_PENDING,
2549 request3.StartRequest(
2550 SPDY_REQUEST_RESPONSE_STREAM,
2551 session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2553 EXPECT_EQ(0u, session->num_active_streams());
2554 EXPECT_EQ(1u, session->num_created_streams());
2555 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2557 scoped_ptr<SpdyHeaderBlock> headers(
2558 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2559 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2560 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2562 // Run until 1st stream is activated and then closed.
2563 EXPECT_EQ(0u, delegate1.stream_id());
2565 EXPECT_EQ(NULL, spdy_stream1.get());
2566 EXPECT_EQ(1u, delegate1.stream_id());
2568 EXPECT_EQ(0u, session->num_active_streams());
2569 EXPECT_EQ(0u, session->num_created_streams());
2570 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2572 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2573 // create the 2nd stream.
2574 base::MessageLoop::current()->RunUntilIdle();
2576 EXPECT_EQ(0u, session->num_active_streams());
2577 EXPECT_EQ(1u, session->num_created_streams());
2578 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2580 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2581 test::StreamDelegateDoNothing delegate2(stream2);
2582 stream2->SetDelegate(&delegate2);
2583 scoped_ptr<SpdyHeaderBlock> headers2(
2584 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2585 stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2586 EXPECT_TRUE(stream2->HasUrlFromHeaders());
2588 // Run until 2nd stream is activated and then closed.
2589 EXPECT_EQ(0u, delegate2.stream_id());
2591 EXPECT_EQ(NULL, stream2.get());
2592 EXPECT_EQ(3u, delegate2.stream_id());
2594 EXPECT_EQ(0u, session->num_active_streams());
2595 EXPECT_EQ(0u, session->num_created_streams());
2596 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2598 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2599 // create the 3rd stream.
2600 base::MessageLoop::current()->RunUntilIdle();
2602 EXPECT_EQ(0u, session->num_active_streams());
2603 EXPECT_EQ(1u, session->num_created_streams());
2604 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2606 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2607 test::StreamDelegateDoNothing delegate3(stream3);
2608 stream3->SetDelegate(&delegate3);
2609 scoped_ptr<SpdyHeaderBlock> headers3(
2610 spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2611 stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2612 EXPECT_TRUE(stream3->HasUrlFromHeaders());
2614 // Run until 2nd stream is activated and then closed.
2615 EXPECT_EQ(0u, delegate3.stream_id());
2617 EXPECT_EQ(NULL, stream3.get());
2618 EXPECT_EQ(5u, delegate3.stream_id());
2620 EXPECT_EQ(0u, session->num_active_streams());
2621 EXPECT_EQ(0u, session->num_created_streams());
2622 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2627 TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2628 session_deps_.host_resolver->set_synchronous_mode(true);
2630 MockRead reads[] = {
2631 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2634 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2635 MockConnect connect_data(SYNCHRONOUS, OK);
2637 data.set_connect_data(connect_data);
2638 session_deps_.socket_factory->AddSocketDataProvider(&data);
2640 CreateNetworkSession();
2642 base::WeakPtr<SpdySession> session =
2643 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2645 // Leave room for only one more stream to be created.
2646 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2647 base::WeakPtr<SpdyStream> spdy_stream =
2648 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2649 session, test_url_, MEDIUM, BoundNetLog());
2650 ASSERT_TRUE(spdy_stream != NULL);
2653 GURL url1(kDefaultURL);
2654 base::WeakPtr<SpdyStream> spdy_stream1 =
2655 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2656 session, url1, LOWEST, BoundNetLog());
2657 ASSERT_TRUE(spdy_stream1.get() != NULL);
2658 EXPECT_EQ(0u, spdy_stream1->stream_id());
2660 TestCompletionCallback callback2;
2661 GURL url2(kDefaultURL);
2662 SpdyStreamRequest request2;
2663 ASSERT_EQ(ERR_IO_PENDING,
2664 request2.StartRequest(
2665 SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2666 callback2.callback()));
2668 TestCompletionCallback callback3;
2669 GURL url3(kDefaultURL);
2670 SpdyStreamRequest request3;
2671 ASSERT_EQ(ERR_IO_PENDING,
2672 request3.StartRequest(
2673 SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2674 callback3.callback()));
2676 EXPECT_EQ(0u, session->num_active_streams());
2677 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2678 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2680 // Cancel the first stream; this will allow the second stream to be created.
2681 EXPECT_TRUE(spdy_stream1.get() != NULL);
2682 spdy_stream1->Cancel();
2683 EXPECT_EQ(NULL, spdy_stream1.get());
2685 EXPECT_EQ(OK, callback2.WaitForResult());
2686 EXPECT_EQ(0u, session->num_active_streams());
2687 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2688 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2690 // Cancel the second stream; this will allow the third stream to be created.
2691 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2692 spdy_stream2->Cancel();
2693 EXPECT_EQ(NULL, spdy_stream2.get());
2695 EXPECT_EQ(OK, callback3.WaitForResult());
2696 EXPECT_EQ(0u, session->num_active_streams());
2697 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2698 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2700 // Cancel the third stream.
2701 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2702 spdy_stream3->Cancel();
2703 EXPECT_EQ(NULL, spdy_stream3.get());
2704 EXPECT_EQ(0u, session->num_active_streams());
2705 EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
2706 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2709 // Test that SpdySession::DoReadLoop reads data from the socket
2710 // without yielding. This test makes 32k - 1 bytes of data available
2711 // on the socket for reading. It then verifies that it has read all
2712 // the available data without yielding.
2713 TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2714 MockConnect connect_data(SYNCHRONOUS, OK);
2715 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2717 scoped_ptr<SpdyFrame> req1(
2718 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2719 MockWrite writes[] = {
2720 CreateMockWrite(*req1, 0),
2723 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2724 // (-spdy_data_frame_size).
2725 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2726 const int kPayloadSize =
2727 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2728 TestDataStream test_stream;
2729 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2730 char* payload_data = payload->data();
2731 test_stream.GetBytes(payload_data, kPayloadSize);
2733 scoped_ptr<SpdyFrame> partial_data_frame(
2734 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2735 scoped_ptr<SpdyFrame> finish_data_frame(
2736 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2738 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2740 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2742 MockRead reads[] = {
2743 CreateMockRead(*resp1, 1),
2744 CreateMockRead(*partial_data_frame, 2),
2745 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2746 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2747 CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2748 MockRead(ASYNC, 0, 6) // EOF
2751 // Create SpdySession and SpdyStream and send the request.
2752 DeterministicSocketData data(reads, arraysize(reads),
2753 writes, arraysize(writes));
2754 data.set_connect_data(connect_data);
2755 session_deps_.host_resolver->set_synchronous_mode(true);
2756 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2758 CreateDeterministicNetworkSession();
2760 base::WeakPtr<SpdySession> session =
2761 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2763 GURL url1(kDefaultURL);
2764 base::WeakPtr<SpdyStream> spdy_stream1 =
2765 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2766 session, url1, MEDIUM, BoundNetLog());
2767 ASSERT_TRUE(spdy_stream1.get() != NULL);
2768 EXPECT_EQ(0u, spdy_stream1->stream_id());
2769 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2770 spdy_stream1->SetDelegate(&delegate1);
2772 scoped_ptr<SpdyHeaderBlock> headers1(
2773 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2774 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2775 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2777 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2779 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2781 // Run until 1st read.
2782 EXPECT_EQ(0u, delegate1.stream_id());
2784 EXPECT_EQ(1u, delegate1.stream_id());
2785 EXPECT_EQ(0u, observer.executed_count());
2787 // Read all the data and verify SpdySession::DoReadLoop has not
2790 EXPECT_EQ(NULL, spdy_stream1.get());
2792 // Verify task observer's executed_count is zero, which indicates DoRead read
2793 // all the available data.
2794 EXPECT_EQ(0u, observer.executed_count());
2795 EXPECT_TRUE(data.at_write_eof());
2796 EXPECT_TRUE(data.at_read_eof());
2799 // Test that SpdySession::DoReadLoop yields while reading the
2800 // data. This test makes 32k + 1 bytes of data available on the socket
2801 // for reading. It then verifies that DoRead has yielded even though
2802 // there is data available for it to read (i.e, socket()->Read didn't
2803 // return ERR_IO_PENDING during socket reads).
2804 TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2805 MockConnect connect_data(SYNCHRONOUS, OK);
2806 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2808 scoped_ptr<SpdyFrame> req1(
2809 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2810 MockWrite writes[] = {
2811 CreateMockWrite(*req1, 0),
2814 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2815 // (-spdy_data_frame_size).
2816 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2817 const int kPayloadSize =
2818 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2819 TestDataStream test_stream;
2820 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2821 char* payload_data = payload->data();
2822 test_stream.GetBytes(payload_data, kPayloadSize);
2824 scoped_ptr<SpdyFrame> partial_data_frame(
2825 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2826 scoped_ptr<SpdyFrame> finish_data_frame(
2827 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2829 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2831 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2832 MockRead reads[] = {
2833 CreateMockRead(*resp1, 1),
2834 CreateMockRead(*partial_data_frame, 2),
2835 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2836 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2837 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2838 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2839 MockRead(ASYNC, 0, 7) // EOF
2842 // Create SpdySession and SpdyStream and send the request.
2843 DeterministicSocketData data(reads, arraysize(reads),
2844 writes, arraysize(writes));
2845 data.set_connect_data(connect_data);
2846 session_deps_.host_resolver->set_synchronous_mode(true);
2847 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2849 CreateDeterministicNetworkSession();
2851 base::WeakPtr<SpdySession> session =
2852 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2854 GURL url1(kDefaultURL);
2855 base::WeakPtr<SpdyStream> spdy_stream1 =
2856 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2857 session, url1, MEDIUM, BoundNetLog());
2858 ASSERT_TRUE(spdy_stream1.get() != NULL);
2859 EXPECT_EQ(0u, spdy_stream1->stream_id());
2860 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2861 spdy_stream1->SetDelegate(&delegate1);
2863 scoped_ptr<SpdyHeaderBlock> headers1(
2864 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2865 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2866 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2868 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2870 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2872 // Run until 1st read.
2873 EXPECT_EQ(0u, delegate1.stream_id());
2875 EXPECT_EQ(1u, delegate1.stream_id());
2876 EXPECT_EQ(0u, observer.executed_count());
2878 // Read all the data and verify SpdySession::DoReadLoop has posted a
2881 EXPECT_EQ(NULL, spdy_stream1.get());
2883 // Verify task observer's executed_count is 1, which indicates DoRead has
2884 // posted only one task and thus yielded though there is data available for it
2886 EXPECT_EQ(1u, observer.executed_count());
2887 EXPECT_TRUE(data.at_write_eof());
2888 EXPECT_TRUE(data.at_read_eof());
2891 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2892 // + async, by doing the following MockReads.
2894 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2895 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2897 // The above reads 26K synchronously. Since that is less that 32K, we
2898 // will attempt to read again. However, that DoRead() will return
2899 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2900 // yield. When we come back, DoRead() will read the results from the
2901 // async read, and rest of the data synchronously.
2902 TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2903 MockConnect connect_data(SYNCHRONOUS, OK);
2904 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2906 scoped_ptr<SpdyFrame> req1(
2907 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2908 MockWrite writes[] = {
2909 CreateMockWrite(*req1, 0),
2912 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2913 // (-spdy_data_frame_size).
2914 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2915 TestDataStream test_stream;
2916 const int kEightKPayloadSize =
2917 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2918 scoped_refptr<net::IOBuffer> eightk_payload(
2919 new net::IOBuffer(kEightKPayloadSize));
2920 char* eightk_payload_data = eightk_payload->data();
2921 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2923 // Build buffer of 2k size.
2924 TestDataStream test_stream2;
2925 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2926 scoped_refptr<net::IOBuffer> twok_payload(
2927 new net::IOBuffer(kTwoKPayloadSize));
2928 char* twok_payload_data = twok_payload->data();
2929 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2931 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2932 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2933 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2934 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2935 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2936 1, "h", 1, DATA_FLAG_FIN));
2938 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2940 MockRead reads[] = {
2941 CreateMockRead(*resp1, 1),
2942 CreateMockRead(*eightk_data_frame, 2),
2943 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
2944 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2945 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
2946 CreateMockRead(*eightk_data_frame, 6, ASYNC),
2947 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
2948 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2949 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2950 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
2951 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
2952 MockRead(ASYNC, 0, 12) // EOF
2955 // Create SpdySession and SpdyStream and send the request.
2956 DeterministicSocketData data(reads, arraysize(reads),
2957 writes, arraysize(writes));
2958 data.set_connect_data(connect_data);
2959 session_deps_.host_resolver->set_synchronous_mode(true);
2960 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2962 CreateDeterministicNetworkSession();
2964 base::WeakPtr<SpdySession> session =
2965 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2967 GURL url1(kDefaultURL);
2968 base::WeakPtr<SpdyStream> spdy_stream1 =
2969 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2970 session, url1, MEDIUM, BoundNetLog());
2971 ASSERT_TRUE(spdy_stream1.get() != NULL);
2972 EXPECT_EQ(0u, spdy_stream1->stream_id());
2973 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2974 spdy_stream1->SetDelegate(&delegate1);
2976 scoped_ptr<SpdyHeaderBlock> headers1(
2977 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2978 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2979 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2981 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2982 // posting of tasks.
2983 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2985 // Run until 1st read.
2986 EXPECT_EQ(0u, delegate1.stream_id());
2988 EXPECT_EQ(1u, delegate1.stream_id());
2989 EXPECT_EQ(0u, observer.executed_count());
2991 // Read all the data and verify SpdySession::DoReadLoop has posted a
2994 EXPECT_EQ(NULL, spdy_stream1.get());
2996 // Verify task observer's executed_count is 1, which indicates DoRead has
2997 // posted only one task and thus yielded though there is data available for
2999 EXPECT_EQ(1u, observer.executed_count());
3000 EXPECT_TRUE(data.at_write_eof());
3001 EXPECT_TRUE(data.at_read_eof());
3004 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
3005 // nothing blows up.
3006 TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
3007 MockConnect connect_data(SYNCHRONOUS, OK);
3008 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3010 scoped_ptr<SpdyFrame> req1(
3011 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3012 MockWrite writes[] = {
3013 CreateMockWrite(*req1, 0),
3016 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3017 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
3018 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
3020 MockRead reads[] = {
3021 CreateMockRead(*resp1, 1),
3022 CreateMockRead(*body1, 2),
3023 CreateMockRead(*goaway, 3),
3026 // Create SpdySession and SpdyStream and send the request.
3027 DeterministicSocketData data(reads, arraysize(reads),
3028 writes, arraysize(writes));
3029 data.set_connect_data(connect_data);
3030 session_deps_.host_resolver->set_synchronous_mode(true);
3031 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3033 CreateDeterministicNetworkSession();
3035 base::WeakPtr<SpdySession> session =
3036 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3038 GURL url1(kDefaultURL);
3039 base::WeakPtr<SpdyStream> spdy_stream1 =
3040 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3041 session, url1, MEDIUM, BoundNetLog());
3042 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3043 spdy_stream1->SetDelegate(&delegate1);
3044 ASSERT_TRUE(spdy_stream1.get() != NULL);
3045 EXPECT_EQ(0u, spdy_stream1->stream_id());
3047 scoped_ptr<SpdyHeaderBlock> headers1(
3048 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3049 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
3050 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3052 // Run until 1st read.
3053 EXPECT_EQ(0u, spdy_stream1->stream_id());
3055 EXPECT_EQ(1u, spdy_stream1->stream_id());
3057 // Run until GoAway.
3059 EXPECT_EQ(NULL, spdy_stream1.get());
3060 EXPECT_TRUE(data.at_write_eof());
3061 EXPECT_TRUE(data.at_read_eof());
3062 EXPECT_TRUE(session == NULL);
3065 // Within this framework, a SpdySession should be initialized with
3066 // flow control disabled for protocol version 2, with flow control
3067 // enabled only for streams for protocol version 3, and with flow
3068 // control enabled for streams and sessions for higher versions.
3069 TEST_P(SpdySessionTest, ProtocolNegotiation) {
3070 session_deps_.host_resolver->set_synchronous_mode(true);
3072 MockConnect connect_data(SYNCHRONOUS, OK);
3073 MockRead reads[] = {
3074 MockRead(SYNCHRONOUS, 0, 0) // EOF
3076 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3077 data.set_connect_data(connect_data);
3078 session_deps_.socket_factory->AddSocketDataProvider(&data);
3080 CreateNetworkSession();
3081 base::WeakPtr<SpdySession> session =
3082 CreateFakeSpdySession(spdy_session_pool_, key_);
3084 EXPECT_EQ(spdy_util_.spdy_version(),
3085 session->buffered_spdy_framer_->protocol_version());
3086 if (GetParam() == kProtoDeprecatedSPDY2) {
3087 EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state());
3088 EXPECT_EQ(0, session->session_send_window_size_);
3089 EXPECT_EQ(0, session->session_recv_window_size_);
3090 } else if (GetParam() == kProtoSPDY3) {
3091 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
3092 EXPECT_EQ(0, session->session_send_window_size_);
3093 EXPECT_EQ(0, session->session_recv_window_size_);
3095 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3096 session->flow_control_state());
3097 EXPECT_EQ(kSpdySessionInitialWindowSize,
3098 session->session_send_window_size_);
3099 EXPECT_EQ(kSpdySessionInitialWindowSize,
3100 session->session_recv_window_size_);
3102 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3105 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3106 // pointers to the idle session are currently held.
3107 TEST_P(SpdySessionTest, CloseOneIdleConnection) {
3108 ClientSocketPoolManager::set_max_sockets_per_group(
3109 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3110 ClientSocketPoolManager::set_max_sockets_per_pool(
3111 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3113 MockConnect connect_data(SYNCHRONOUS, OK);
3114 MockRead reads[] = {
3115 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3117 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3118 data.set_connect_data(connect_data);
3119 session_deps_.socket_factory->AddSocketDataProvider(&data);
3120 session_deps_.socket_factory->AddSocketDataProvider(&data);
3122 CreateNetworkSession();
3124 TransportClientSocketPool* pool =
3125 http_session_->GetTransportSocketPool(
3126 HttpNetworkSession::NORMAL_SOCKET_POOL);
3128 // Create an idle SPDY session.
3129 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3130 PRIVACY_MODE_DISABLED);
3131 base::WeakPtr<SpdySession> session1 =
3132 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3133 EXPECT_FALSE(pool->IsStalled());
3135 // Trying to create a new connection should cause the pool to be stalled, and
3136 // post a task asynchronously to try and close the session.
3137 TestCompletionCallback callback2;
3138 HostPortPair host_port2("2.com", 80);
3139 scoped_refptr<TransportSocketParams> params2(
3140 new TransportSocketParams(
3141 host_port2, false, false, OnHostResolutionCallback(),
3142 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3143 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3144 EXPECT_EQ(ERR_IO_PENDING,
3145 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3146 callback2.callback(), pool, BoundNetLog()));
3147 EXPECT_TRUE(pool->IsStalled());
3149 // The socket pool should close the connection asynchronously and establish a
3151 EXPECT_EQ(OK, callback2.WaitForResult());
3152 EXPECT_FALSE(pool->IsStalled());
3153 EXPECT_TRUE(session1 == NULL);
3156 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3157 // pointers to the idle session are currently held, in the case the SPDY session
3159 TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
3160 ClientSocketPoolManager::set_max_sockets_per_group(
3161 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3162 ClientSocketPoolManager::set_max_sockets_per_pool(
3163 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3165 MockConnect connect_data(SYNCHRONOUS, OK);
3166 MockRead reads[] = {
3167 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3169 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3170 data.set_connect_data(connect_data);
3171 session_deps_.socket_factory->AddSocketDataProvider(&data);
3172 session_deps_.socket_factory->AddSocketDataProvider(&data);
3174 session_deps_.host_resolver->set_synchronous_mode(true);
3175 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3176 "1.com", "192.168.0.2", std::string());
3177 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3178 "2.com", "192.168.0.2", std::string());
3179 // Not strictly needed.
3180 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3181 "3.com", "192.168.0.3", std::string());
3183 CreateNetworkSession();
3185 TransportClientSocketPool* pool =
3186 http_session_->GetTransportSocketPool(
3187 HttpNetworkSession::NORMAL_SOCKET_POOL);
3189 // Create an idle SPDY session.
3190 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3191 PRIVACY_MODE_DISABLED);
3192 base::WeakPtr<SpdySession> session1 =
3193 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3194 EXPECT_FALSE(pool->IsStalled());
3196 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3197 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3198 PRIVACY_MODE_DISABLED);
3199 HostResolver::RequestInfo info(key2.host_port_pair());
3200 AddressList addresses;
3201 // Pre-populate the DNS cache, since a synchronous resolution is required in
3202 // order to create the alias.
3203 session_deps_.host_resolver->Resolve(info,
3206 CompletionCallback(),
3209 // Get a session for |key2|, which should return the session created earlier.
3210 base::WeakPtr<SpdySession> session2 =
3211 spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3212 ASSERT_EQ(session1.get(), session2.get());
3213 EXPECT_FALSE(pool->IsStalled());
3215 // Trying to create a new connection should cause the pool to be stalled, and
3216 // post a task asynchronously to try and close the session.
3217 TestCompletionCallback callback3;
3218 HostPortPair host_port3("3.com", 80);
3219 scoped_refptr<TransportSocketParams> params3(
3220 new TransportSocketParams(
3221 host_port3, false, false, OnHostResolutionCallback(),
3222 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3223 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3224 EXPECT_EQ(ERR_IO_PENDING,
3225 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3226 callback3.callback(), pool, BoundNetLog()));
3227 EXPECT_TRUE(pool->IsStalled());
3229 // The socket pool should close the connection asynchronously and establish a
3231 EXPECT_EQ(OK, callback3.WaitForResult());
3232 EXPECT_FALSE(pool->IsStalled());
3233 EXPECT_TRUE(session1 == NULL);
3234 EXPECT_TRUE(session2 == NULL);
3237 // Tests that when a SPDY session becomes idle, it closes itself if there is
3238 // a lower layer pool stalled on the per-pool socket limit.
3239 TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3240 ClientSocketPoolManager::set_max_sockets_per_group(
3241 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3242 ClientSocketPoolManager::set_max_sockets_per_pool(
3243 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3245 MockConnect connect_data(SYNCHRONOUS, OK);
3246 MockRead reads[] = {
3247 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3249 scoped_ptr<SpdyFrame> req1(
3250 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3251 scoped_ptr<SpdyFrame> cancel1(
3252 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3253 MockWrite writes[] = {
3254 CreateMockWrite(*req1, 1),
3255 CreateMockWrite(*cancel1, 1),
3257 StaticSocketDataProvider data(reads, arraysize(reads),
3258 writes, arraysize(writes));
3259 data.set_connect_data(connect_data);
3260 session_deps_.socket_factory->AddSocketDataProvider(&data);
3262 MockRead http_reads[] = {
3263 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3265 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
3267 http_data.set_connect_data(connect_data);
3268 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3271 CreateNetworkSession();
3273 TransportClientSocketPool* pool =
3274 http_session_->GetTransportSocketPool(
3275 HttpNetworkSession::NORMAL_SOCKET_POOL);
3277 // Create a SPDY session.
3278 GURL url1(kDefaultURL);
3279 SpdySessionKey key1(HostPortPair(url1.host(), 80),
3280 ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3281 base::WeakPtr<SpdySession> session1 =
3282 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3283 EXPECT_FALSE(pool->IsStalled());
3285 // Create a stream using the session, and send a request.
3287 TestCompletionCallback callback1;
3288 base::WeakPtr<SpdyStream> spdy_stream1 =
3289 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3290 session1, url1, DEFAULT_PRIORITY,
3292 ASSERT_TRUE(spdy_stream1.get());
3293 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3294 spdy_stream1->SetDelegate(&delegate1);
3296 scoped_ptr<SpdyHeaderBlock> headers1(
3297 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3298 EXPECT_EQ(ERR_IO_PENDING,
3299 spdy_stream1->SendRequestHeaders(
3300 headers1.Pass(), NO_MORE_DATA_TO_SEND));
3301 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3303 base::MessageLoop::current()->RunUntilIdle();
3305 // Trying to create a new connection should cause the pool to be stalled, and
3306 // post a task asynchronously to try and close the session.
3307 TestCompletionCallback callback2;
3308 HostPortPair host_port2("2.com", 80);
3309 scoped_refptr<TransportSocketParams> params2(
3310 new TransportSocketParams(
3311 host_port2, false, false, OnHostResolutionCallback(),
3312 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3313 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3314 EXPECT_EQ(ERR_IO_PENDING,
3315 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3316 callback2.callback(), pool, BoundNetLog()));
3317 EXPECT_TRUE(pool->IsStalled());
3319 // Running the message loop should cause the socket pool to ask the SPDY
3320 // session to close an idle socket, but since the socket is in use, nothing
3322 base::RunLoop().RunUntilIdle();
3323 EXPECT_TRUE(pool->IsStalled());
3324 EXPECT_FALSE(callback2.have_result());
3326 // Cancelling the request should result in the session's socket being
3327 // closed, since the pool is stalled.
3328 ASSERT_TRUE(spdy_stream1.get());
3329 spdy_stream1->Cancel();
3330 base::RunLoop().RunUntilIdle();
3331 ASSERT_FALSE(pool->IsStalled());
3332 EXPECT_EQ(OK, callback2.WaitForResult());
3335 // Verify that SpdySessionKey and therefore SpdySession is different when
3336 // privacy mode is enabled or disabled.
3337 TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3338 CreateDeterministicNetworkSession();
3340 HostPortPair host_port_pair("www.google.com", 443);
3341 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3342 PRIVACY_MODE_ENABLED);
3343 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3344 PRIVACY_MODE_DISABLED);
3346 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3347 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3349 // Add SpdySession with PrivacyMode Enabled to the pool.
3350 base::WeakPtr<SpdySession> session_privacy_enabled =
3351 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3353 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3354 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3356 // Add SpdySession with PrivacyMode Disabled to the pool.
3357 base::WeakPtr<SpdySession> session_privacy_disabled =
3358 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3360 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3361 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3363 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3364 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3365 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3367 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3368 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3369 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3372 // Delegate that creates another stream when its stream is closed.
3373 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3375 StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3376 const base::WeakPtr<SpdySession>& session)
3377 : StreamDelegateDoNothing(stream),
3378 session_(session) {}
3380 ~StreamCreatingDelegate() override {}
3382 void OnClose(int status) override {
3383 GURL url(kDefaultURL);
3385 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3386 session_, url, MEDIUM, BoundNetLog()));
3390 const base::WeakPtr<SpdySession> session_;
3393 // Create another stream in response to a stream being reset. Nothing
3394 // should blow up. This is a regression test for
3395 // http://crbug.com/263690 .
3396 TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3397 session_deps_.host_resolver->set_synchronous_mode(true);
3399 MockConnect connect_data(SYNCHRONOUS, OK);
3401 scoped_ptr<SpdyFrame> req(
3402 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3403 MockWrite writes[] = {
3404 CreateMockWrite(*req, 0),
3407 scoped_ptr<SpdyFrame> rst(
3408 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3409 MockRead reads[] = {
3410 CreateMockRead(*rst, 1),
3411 MockRead(ASYNC, 0, 2) // EOF
3413 DeterministicSocketData data(reads, arraysize(reads),
3414 writes, arraysize(writes));
3415 data.set_connect_data(connect_data);
3416 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3418 CreateDeterministicNetworkSession();
3420 base::WeakPtr<SpdySession> session =
3421 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3423 GURL url(kDefaultURL);
3424 base::WeakPtr<SpdyStream> spdy_stream =
3425 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3426 session, url, MEDIUM, BoundNetLog());
3427 ASSERT_TRUE(spdy_stream.get() != NULL);
3428 EXPECT_EQ(0u, spdy_stream->stream_id());
3430 StreamCreatingDelegate delegate(spdy_stream, session);
3431 spdy_stream->SetDelegate(&delegate);
3433 scoped_ptr<SpdyHeaderBlock> headers(
3434 spdy_util_.ConstructGetHeaderBlock(url.spec()));
3435 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3436 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3438 EXPECT_EQ(0u, spdy_stream->stream_id());
3442 EXPECT_EQ(1u, spdy_stream->stream_id());
3444 // Cause the stream to be reset, which should cause another stream
3448 EXPECT_EQ(NULL, spdy_stream.get());
3449 EXPECT_TRUE(delegate.StreamIsClosed());
3450 EXPECT_EQ(0u, session->num_active_streams());
3451 EXPECT_EQ(1u, session->num_created_streams());
3454 // The tests below are only for SPDY/3 and above.
3456 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3457 if (GetParam() < kProtoSPDY3)
3460 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3462 SettingsMap new_settings;
3463 int32 window_size = 1;
3464 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3465 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3467 // Set up the socket so we read a SETTINGS frame that sets
3468 // INITIAL_WINDOW_SIZE.
3469 MockConnect connect_data(SYNCHRONOUS, OK);
3470 scoped_ptr<SpdyFrame> settings_frame(
3471 spdy_util_.ConstructSpdySettings(new_settings));
3472 MockRead reads[] = {
3473 CreateMockRead(*settings_frame, 0),
3474 MockRead(ASYNC, 0, 1) // EOF
3477 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3478 MockWrite writes[] = {
3479 CreateMockWrite(*settings_ack, 2),
3482 session_deps_.host_resolver->set_synchronous_mode(true);
3484 DeterministicSocketData data(reads, arraysize(reads),
3485 writes, arraysize(writes));
3486 data.set_connect_data(connect_data);
3487 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3489 CreateDeterministicNetworkSession();
3491 base::WeakPtr<SpdySession> session =
3492 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3493 base::WeakPtr<SpdyStream> spdy_stream1 =
3494 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3495 session, test_url_, MEDIUM, BoundNetLog());
3496 ASSERT_TRUE(spdy_stream1.get() != NULL);
3497 TestCompletionCallback callback1;
3498 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3500 data.RunFor(1); // Process the SETTINGS frame, but not the EOF
3501 base::MessageLoop::current()->RunUntilIdle();
3502 EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3503 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3505 // Release the first one, this will allow the second to be created.
3506 spdy_stream1->Cancel();
3507 EXPECT_EQ(NULL, spdy_stream1.get());
3509 base::WeakPtr<SpdyStream> spdy_stream2 =
3510 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3511 session, test_url_, MEDIUM, BoundNetLog());
3512 ASSERT_TRUE(spdy_stream2.get() != NULL);
3513 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3514 spdy_stream2->Cancel();
3515 EXPECT_EQ(NULL, spdy_stream2.get());
3518 // The tests below are only for SPDY/3.1 and above.
3520 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3521 // adjust the session receive window size for SPDY 3.1 and higher. In
3522 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3523 // sending a WINDOW_UPDATE frame for a large enough delta.
3524 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3525 if (GetParam() < kProtoSPDY31)
3528 session_deps_.host_resolver->set_synchronous_mode(true);
3530 const int32 delta_window_size = 100;
3532 MockConnect connect_data(SYNCHRONOUS, OK);
3533 MockRead reads[] = {
3534 MockRead(ASYNC, 0, 1) // EOF
3536 scoped_ptr<SpdyFrame> window_update(
3537 spdy_util_.ConstructSpdyWindowUpdate(
3538 kSessionFlowControlStreamId,
3539 kSpdySessionInitialWindowSize + delta_window_size));
3540 MockWrite writes[] = {
3541 CreateMockWrite(*window_update, 0),
3543 DeterministicSocketData data(reads, arraysize(reads),
3544 writes, arraysize(writes));
3545 data.set_connect_data(connect_data);
3546 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3548 CreateDeterministicNetworkSession();
3549 base::WeakPtr<SpdySession> session =
3550 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3551 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3552 session->flow_control_state());
3554 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3555 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3557 session->IncreaseRecvWindowSize(delta_window_size);
3558 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3559 session->session_recv_window_size_);
3560 EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3562 // Should trigger sending a WINDOW_UPDATE frame.
3563 session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize);
3564 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size +
3565 kSpdySessionInitialWindowSize,
3566 session->session_recv_window_size_);
3567 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3571 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3572 session->in_io_loop_ = true;
3573 session->DecreaseRecvWindowSize(
3574 kSpdySessionInitialWindowSize + delta_window_size +
3575 kSpdySessionInitialWindowSize);
3576 session->in_io_loop_ = false;
3577 EXPECT_EQ(0, session->session_recv_window_size_);
3578 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3581 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3582 // adjust the session send window size when the "enable_spdy_31" flag
3584 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3585 if (GetParam() < kProtoSPDY31)
3588 session_deps_.host_resolver->set_synchronous_mode(true);
3590 MockConnect connect_data(SYNCHRONOUS, OK);
3591 MockRead reads[] = {
3592 MockRead(SYNCHRONOUS, 0, 0) // EOF
3594 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3595 data.set_connect_data(connect_data);
3596 session_deps_.socket_factory->AddSocketDataProvider(&data);
3598 CreateNetworkSession();
3599 base::WeakPtr<SpdySession> session =
3600 CreateFakeSpdySession(spdy_session_pool_, key_);
3601 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3602 session->flow_control_state());
3604 const int32 delta_window_size = 100;
3606 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3608 session->IncreaseSendWindowSize(delta_window_size);
3609 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3610 session->session_send_window_size_);
3612 session->DecreaseSendWindowSize(delta_window_size);
3613 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3616 // Incoming data for an inactive stream should not cause the session
3617 // receive window size to decrease, but it should cause the unacked
3618 // bytes to increase.
3619 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3620 if (GetParam() < kProtoSPDY31)
3623 session_deps_.host_resolver->set_synchronous_mode(true);
3625 MockConnect connect_data(SYNCHRONOUS, OK);
3626 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3627 MockRead reads[] = {
3628 CreateMockRead(*resp, 0),
3629 MockRead(ASYNC, 0, 1) // EOF
3631 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3632 data.set_connect_data(connect_data);
3633 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3635 CreateDeterministicNetworkSession();
3636 base::WeakPtr<SpdySession> session =
3637 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3638 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3639 session->flow_control_state());
3641 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3642 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3646 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3647 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3652 // A delegate that drops any received data.
3653 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3655 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3656 base::StringPiece data)
3657 : StreamDelegateSendImmediate(stream, data) {}
3659 ~DropReceivedDataDelegate() override {}
3661 // Drop any received data.
3662 void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override {}
3665 // Send data back and forth but use a delegate that drops its received
3666 // data. The receive window should still increase to its original
3667 // value, i.e. we shouldn't "leak" receive window bytes.
3668 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3669 if (GetParam() < kProtoSPDY31)
3672 const char kStreamUrl[] = "http://www.google.com/";
3674 const int32 msg_data_size = 100;
3675 const std::string msg_data(msg_data_size, 'a');
3677 MockConnect connect_data(SYNCHRONOUS, OK);
3679 scoped_ptr<SpdyFrame> req(
3680 spdy_util_.ConstructSpdyPost(
3681 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3682 scoped_ptr<SpdyFrame> msg(
3683 spdy_util_.ConstructSpdyBodyFrame(
3684 1, msg_data.data(), msg_data_size, false));
3685 MockWrite writes[] = {
3686 CreateMockWrite(*req, 0),
3687 CreateMockWrite(*msg, 2),
3690 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3691 scoped_ptr<SpdyFrame> echo(
3692 spdy_util_.ConstructSpdyBodyFrame(
3693 1, msg_data.data(), msg_data_size, false));
3694 scoped_ptr<SpdyFrame> window_update(
3695 spdy_util_.ConstructSpdyWindowUpdate(
3696 kSessionFlowControlStreamId, msg_data_size));
3697 MockRead reads[] = {
3698 CreateMockRead(*resp, 1),
3699 CreateMockRead(*echo, 3),
3700 MockRead(ASYNC, 0, 4) // EOF
3703 // Create SpdySession and SpdyStream and send the request.
3704 DeterministicSocketData data(reads, arraysize(reads),
3705 writes, arraysize(writes));
3706 data.set_connect_data(connect_data);
3707 session_deps_.host_resolver->set_synchronous_mode(true);
3708 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3710 CreateDeterministicNetworkSession();
3712 base::WeakPtr<SpdySession> session =
3713 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3715 GURL url(kStreamUrl);
3716 base::WeakPtr<SpdyStream> stream =
3717 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3718 session, url, MEDIUM, BoundNetLog());
3719 ASSERT_TRUE(stream.get() != NULL);
3720 EXPECT_EQ(0u, stream->stream_id());
3722 DropReceivedDataDelegate delegate(stream, msg_data);
3723 stream->SetDelegate(&delegate);
3725 scoped_ptr<SpdyHeaderBlock> headers(
3726 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3727 EXPECT_EQ(ERR_IO_PENDING,
3728 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3729 EXPECT_TRUE(stream->HasUrlFromHeaders());
3731 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3732 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3736 EXPECT_TRUE(data.at_write_eof());
3737 EXPECT_TRUE(data.at_read_eof());
3739 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3740 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3743 EXPECT_EQ(NULL, stream.get());
3745 EXPECT_EQ(OK, delegate.WaitForClose());
3747 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3748 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3751 // Send data back and forth but close the stream before its data frame
3752 // can be written to the socket. The send window should then increase
3753 // to its original value, i.e. we shouldn't "leak" send window bytes.
3754 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3755 if (GetParam() < kProtoSPDY31)
3758 const char kStreamUrl[] = "http://www.google.com/";
3760 const int32 msg_data_size = 100;
3761 const std::string msg_data(msg_data_size, 'a');
3763 MockConnect connect_data(SYNCHRONOUS, OK);
3765 scoped_ptr<SpdyFrame> req(
3766 spdy_util_.ConstructSpdyPost(
3767 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3768 MockWrite writes[] = {
3769 CreateMockWrite(*req, 0),
3772 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3773 MockRead reads[] = {
3774 CreateMockRead(*resp, 1),
3775 MockRead(ASYNC, 0, 2) // EOF
3778 // Create SpdySession and SpdyStream and send the request.
3779 DeterministicSocketData data(reads, arraysize(reads),
3780 writes, arraysize(writes));
3781 data.set_connect_data(connect_data);
3782 session_deps_.host_resolver->set_synchronous_mode(true);
3783 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3785 CreateDeterministicNetworkSession();
3787 base::WeakPtr<SpdySession> session =
3788 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3790 GURL url(kStreamUrl);
3791 base::WeakPtr<SpdyStream> stream =
3792 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3793 session, url, MEDIUM, BoundNetLog());
3794 ASSERT_TRUE(stream.get() != NULL);
3795 EXPECT_EQ(0u, stream->stream_id());
3797 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3798 stream->SetDelegate(&delegate);
3800 scoped_ptr<SpdyHeaderBlock> headers(
3801 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3802 EXPECT_EQ(ERR_IO_PENDING,
3803 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3804 EXPECT_TRUE(stream->HasUrlFromHeaders());
3806 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3810 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3814 EXPECT_TRUE(data.at_write_eof());
3815 EXPECT_TRUE(data.at_read_eof());
3817 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3818 session->session_send_window_size_);
3820 // Closing the stream should increase the session's send window.
3822 EXPECT_EQ(NULL, stream.get());
3824 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3826 EXPECT_EQ(OK, delegate.WaitForClose());
3829 // Send data back and forth; the send and receive windows should
3830 // change appropriately.
3831 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
3832 if (GetParam() < kProtoSPDY31)
3835 const char kStreamUrl[] = "http://www.google.com/";
3837 const int32 msg_data_size = 100;
3838 const std::string msg_data(msg_data_size, 'a');
3840 MockConnect connect_data(SYNCHRONOUS, OK);
3842 scoped_ptr<SpdyFrame> req(
3843 spdy_util_.ConstructSpdyPost(
3844 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3845 scoped_ptr<SpdyFrame> msg(
3846 spdy_util_.ConstructSpdyBodyFrame(
3847 1, msg_data.data(), msg_data_size, false));
3848 MockWrite writes[] = {
3849 CreateMockWrite(*req, 0),
3850 CreateMockWrite(*msg, 2),
3853 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3854 scoped_ptr<SpdyFrame> echo(
3855 spdy_util_.ConstructSpdyBodyFrame(
3856 1, msg_data.data(), msg_data_size, false));
3857 scoped_ptr<SpdyFrame> window_update(
3858 spdy_util_.ConstructSpdyWindowUpdate(
3859 kSessionFlowControlStreamId, msg_data_size));
3860 MockRead reads[] = {
3861 CreateMockRead(*resp, 1),
3862 CreateMockRead(*echo, 3),
3863 CreateMockRead(*window_update, 4),
3864 MockRead(ASYNC, 0, 5) // EOF
3867 // Create SpdySession and SpdyStream and send the request.
3868 DeterministicSocketData data(reads, arraysize(reads),
3869 writes, arraysize(writes));
3870 data.set_connect_data(connect_data);
3871 session_deps_.host_resolver->set_synchronous_mode(true);
3872 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3874 CreateDeterministicNetworkSession();
3876 base::WeakPtr<SpdySession> session =
3877 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3879 GURL url(kStreamUrl);
3880 base::WeakPtr<SpdyStream> stream =
3881 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3882 session, url, MEDIUM, BoundNetLog());
3883 ASSERT_TRUE(stream.get() != NULL);
3884 EXPECT_EQ(0u, stream->stream_id());
3886 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3887 stream->SetDelegate(&delegate);
3889 scoped_ptr<SpdyHeaderBlock> headers(
3890 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3891 EXPECT_EQ(ERR_IO_PENDING,
3892 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3893 EXPECT_TRUE(stream->HasUrlFromHeaders());
3895 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3896 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3897 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3901 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3902 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3903 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3907 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3908 session->session_send_window_size_);
3909 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3910 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3914 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3915 session->session_send_window_size_);
3916 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3917 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3921 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3922 session->session_send_window_size_);
3923 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3924 session->session_recv_window_size_);
3925 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3929 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3930 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3931 session->session_recv_window_size_);
3932 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3934 EXPECT_TRUE(data.at_write_eof());
3935 EXPECT_TRUE(data.at_read_eof());
3937 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
3939 // Draining the delegate's read queue should increase the session's
3941 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3942 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3943 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3946 EXPECT_EQ(NULL, stream.get());
3948 EXPECT_EQ(OK, delegate.WaitForClose());
3950 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3951 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3952 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3955 // Given a stall function and an unstall function, runs a test to make
3956 // sure that a stream resumes after unstall.
3957 void SpdySessionTest::RunResumeAfterUnstallTest(
3958 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
3959 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
3961 const char kStreamUrl[] = "http://www.google.com/";
3962 GURL url(kStreamUrl);
3964 session_deps_.host_resolver->set_synchronous_mode(true);
3966 scoped_ptr<SpdyFrame> req(
3967 spdy_util_.ConstructSpdyPost(
3968 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3969 scoped_ptr<SpdyFrame> body(
3970 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3971 MockWrite writes[] = {
3972 CreateMockWrite(*req, 0),
3973 CreateMockWrite(*body, 1),
3976 scoped_ptr<SpdyFrame> resp(
3977 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3978 scoped_ptr<SpdyFrame> echo(
3979 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
3980 MockRead reads[] = {
3981 CreateMockRead(*resp, 2),
3982 MockRead(ASYNC, 0, 0, 3), // EOF
3985 DeterministicSocketData data(reads, arraysize(reads),
3986 writes, arraysize(writes));
3987 MockConnect connect_data(SYNCHRONOUS, OK);
3988 data.set_connect_data(connect_data);
3990 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3992 CreateDeterministicNetworkSession();
3993 base::WeakPtr<SpdySession> session =
3994 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3995 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3996 session->flow_control_state());
3998 base::WeakPtr<SpdyStream> stream =
3999 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4000 session, url, LOWEST, BoundNetLog());
4001 ASSERT_TRUE(stream.get() != NULL);
4003 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
4004 stream->SetDelegate(&delegate);
4006 EXPECT_FALSE(stream->HasUrlFromHeaders());
4007 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4009 scoped_ptr<SpdyHeaderBlock> headers(
4010 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4011 EXPECT_EQ(ERR_IO_PENDING,
4012 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4013 EXPECT_TRUE(stream->HasUrlFromHeaders());
4014 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
4016 stall_function.Run(session.get(), stream.get());
4020 EXPECT_TRUE(stream->send_stalled_by_flow_control());
4022 unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
4024 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4028 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
4030 EXPECT_TRUE(delegate.send_headers_completed());
4031 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
4032 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
4033 EXPECT_TRUE(data.at_write_eof());
4036 // Run the resume-after-unstall test with all possible stall and
4037 // unstall sequences.
4039 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
4040 if (GetParam() < kProtoSPDY31)
4043 RunResumeAfterUnstallTest(
4044 base::Bind(&SpdySessionTest::StallSessionOnly,
4045 base::Unretained(this)),
4046 base::Bind(&SpdySessionTest::UnstallSessionOnly,
4047 base::Unretained(this)));
4051 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4052 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
4053 if (GetParam() < kProtoSPDY31)
4056 RunResumeAfterUnstallTest(
4057 base::Bind(&SpdySessionTest::StallStreamOnly,
4058 base::Unretained(this)),
4059 base::Bind(&SpdySessionTest::UnstallStreamOnly,
4060 base::Unretained(this)));
4063 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4064 if (GetParam() < kProtoSPDY31)
4067 RunResumeAfterUnstallTest(
4068 base::Bind(&SpdySessionTest::StallSessionStream,
4069 base::Unretained(this)),
4070 base::Bind(&SpdySessionTest::UnstallSessionStream,
4071 base::Unretained(this)));
4074 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4075 if (GetParam() < kProtoSPDY31)
4078 RunResumeAfterUnstallTest(
4079 base::Bind(&SpdySessionTest::StallStreamSession,
4080 base::Unretained(this)),
4081 base::Bind(&SpdySessionTest::UnstallSessionStream,
4082 base::Unretained(this)));
4085 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4086 if (GetParam() < kProtoSPDY31)
4089 RunResumeAfterUnstallTest(
4090 base::Bind(&SpdySessionTest::StallStreamSession,
4091 base::Unretained(this)),
4092 base::Bind(&SpdySessionTest::UnstallStreamSession,
4093 base::Unretained(this)));
4096 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4097 if (GetParam() < kProtoSPDY31)
4100 RunResumeAfterUnstallTest(
4101 base::Bind(&SpdySessionTest::StallSessionStream,
4102 base::Unretained(this)),
4103 base::Bind(&SpdySessionTest::UnstallStreamSession,
4104 base::Unretained(this)));
4107 // Cause a stall by reducing the flow control send window to 0. The
4108 // streams should resume in priority order when that window is then
4110 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4111 if (GetParam() < kProtoSPDY31)
4114 const char kStreamUrl[] = "http://www.google.com/";
4115 GURL url(kStreamUrl);
4117 session_deps_.host_resolver->set_synchronous_mode(true);
4119 scoped_ptr<SpdyFrame> req1(
4120 spdy_util_.ConstructSpdyPost(
4121 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4122 scoped_ptr<SpdyFrame> req2(
4123 spdy_util_.ConstructSpdyPost(
4124 kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
4125 scoped_ptr<SpdyFrame> body1(
4126 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4127 scoped_ptr<SpdyFrame> body2(
4128 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4129 MockWrite writes[] = {
4130 CreateMockWrite(*req1, 0),
4131 CreateMockWrite(*req2, 1),
4132 CreateMockWrite(*body2, 2),
4133 CreateMockWrite(*body1, 3),
4136 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4137 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4138 MockRead reads[] = {
4139 CreateMockRead(*resp1, 4),
4140 CreateMockRead(*resp2, 5),
4141 MockRead(ASYNC, 0, 0, 6), // EOF
4144 DeterministicSocketData data(reads, arraysize(reads),
4145 writes, arraysize(writes));
4146 MockConnect connect_data(SYNCHRONOUS, OK);
4147 data.set_connect_data(connect_data);
4149 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4151 CreateDeterministicNetworkSession();
4152 base::WeakPtr<SpdySession> session =
4153 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4154 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4155 session->flow_control_state());
4157 base::WeakPtr<SpdyStream> stream1 =
4158 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4159 session, url, LOWEST, BoundNetLog());
4160 ASSERT_TRUE(stream1.get() != NULL);
4162 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4163 stream1->SetDelegate(&delegate1);
4165 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4167 base::WeakPtr<SpdyStream> stream2 =
4168 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4169 session, url, MEDIUM, BoundNetLog());
4170 ASSERT_TRUE(stream2.get() != NULL);
4172 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4173 stream2->SetDelegate(&delegate2);
4175 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4177 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4178 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4180 StallSessionSend(session.get());
4182 scoped_ptr<SpdyHeaderBlock> headers1(
4183 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4184 EXPECT_EQ(ERR_IO_PENDING,
4185 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4186 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4187 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4190 EXPECT_EQ(1u, stream1->stream_id());
4191 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4193 scoped_ptr<SpdyHeaderBlock> headers2(
4194 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4195 EXPECT_EQ(ERR_IO_PENDING,
4196 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4197 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4198 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4201 EXPECT_EQ(3u, stream2->stream_id());
4202 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4204 // This should unstall only stream2.
4205 UnstallSessionSend(session.get(), kBodyDataSize);
4207 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4208 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4212 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4213 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4215 // This should then unstall stream1.
4216 UnstallSessionSend(session.get(), kBodyDataSize);
4218 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4219 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4223 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4224 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4226 EXPECT_TRUE(delegate1.send_headers_completed());
4227 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4228 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4230 EXPECT_TRUE(delegate2.send_headers_completed());
4231 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4232 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4234 EXPECT_TRUE(data.at_write_eof());
4237 // Delegate that closes a given stream after sending its body.
4238 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4240 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4241 base::StringPiece data)
4242 : StreamDelegateWithBody(stream, data) {}
4244 ~StreamClosingDelegate() override {}
4246 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4247 stream_to_close_ = stream_to_close;
4250 void OnDataSent() override {
4251 test::StreamDelegateWithBody::OnDataSent();
4252 if (stream_to_close_.get()) {
4253 stream_to_close_->Close();
4254 EXPECT_EQ(NULL, stream_to_close_.get());
4259 base::WeakPtr<SpdyStream> stream_to_close_;
4262 // Cause a stall by reducing the flow control send window to
4263 // 0. Unstalling the session should properly handle deleted streams.
4264 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4265 if (GetParam() < kProtoSPDY31)
4268 const char kStreamUrl[] = "http://www.google.com/";
4269 GURL url(kStreamUrl);
4271 session_deps_.host_resolver->set_synchronous_mode(true);
4273 scoped_ptr<SpdyFrame> req1(
4274 spdy_util_.ConstructSpdyPost(
4275 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4276 scoped_ptr<SpdyFrame> req2(
4277 spdy_util_.ConstructSpdyPost(
4278 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4279 scoped_ptr<SpdyFrame> req3(
4280 spdy_util_.ConstructSpdyPost(
4281 kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
4282 scoped_ptr<SpdyFrame> body2(
4283 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4284 MockWrite writes[] = {
4285 CreateMockWrite(*req1, 0),
4286 CreateMockWrite(*req2, 1),
4287 CreateMockWrite(*req3, 2),
4288 CreateMockWrite(*body2, 3),
4291 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4292 MockRead reads[] = {
4293 CreateMockRead(*resp2, 4),
4294 MockRead(ASYNC, 0, 0, 5), // EOF
4297 DeterministicSocketData data(reads, arraysize(reads),
4298 writes, arraysize(writes));
4299 MockConnect connect_data(SYNCHRONOUS, OK);
4300 data.set_connect_data(connect_data);
4302 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4304 CreateDeterministicNetworkSession();
4305 base::WeakPtr<SpdySession> session =
4306 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4307 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4308 session->flow_control_state());
4310 base::WeakPtr<SpdyStream> stream1 =
4311 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4312 session, url, LOWEST, BoundNetLog());
4313 ASSERT_TRUE(stream1.get() != NULL);
4315 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4316 stream1->SetDelegate(&delegate1);
4318 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4320 base::WeakPtr<SpdyStream> stream2 =
4321 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4322 session, url, LOWEST, BoundNetLog());
4323 ASSERT_TRUE(stream2.get() != NULL);
4325 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4326 stream2->SetDelegate(&delegate2);
4328 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4330 base::WeakPtr<SpdyStream> stream3 =
4331 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4332 session, url, LOWEST, BoundNetLog());
4333 ASSERT_TRUE(stream3.get() != NULL);
4335 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4336 stream3->SetDelegate(&delegate3);
4338 EXPECT_FALSE(stream3->HasUrlFromHeaders());
4340 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4341 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4342 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4344 StallSessionSend(session.get());
4346 scoped_ptr<SpdyHeaderBlock> headers1(
4347 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4348 EXPECT_EQ(ERR_IO_PENDING,
4349 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4350 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4351 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4354 EXPECT_EQ(1u, stream1->stream_id());
4355 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4357 scoped_ptr<SpdyHeaderBlock> headers2(
4358 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4359 EXPECT_EQ(ERR_IO_PENDING,
4360 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4361 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4362 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4365 EXPECT_EQ(3u, stream2->stream_id());
4366 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4368 scoped_ptr<SpdyHeaderBlock> headers3(
4369 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4370 EXPECT_EQ(ERR_IO_PENDING,
4371 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4372 EXPECT_TRUE(stream3->HasUrlFromHeaders());
4373 EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4376 EXPECT_EQ(5u, stream3->stream_id());
4377 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4379 SpdyStreamId stream_id1 = stream1->stream_id();
4380 SpdyStreamId stream_id2 = stream2->stream_id();
4381 SpdyStreamId stream_id3 = stream3->stream_id();
4383 // Close stream1 preemptively.
4384 session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4385 EXPECT_EQ(NULL, stream1.get());
4387 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4388 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4389 EXPECT_TRUE(session->IsStreamActive(stream_id3));
4391 // Unstall stream2, which should then close stream3.
4392 delegate2.set_stream_to_close(stream3);
4393 UnstallSessionSend(session.get(), kBodyDataSize);
4396 EXPECT_EQ(NULL, stream3.get());
4398 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4399 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4400 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4401 EXPECT_FALSE(session->IsStreamActive(stream_id3));
4404 EXPECT_EQ(NULL, stream2.get());
4406 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4407 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4408 EXPECT_EQ(OK, delegate3.WaitForClose());
4410 EXPECT_TRUE(delegate1.send_headers_completed());
4411 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4413 EXPECT_TRUE(delegate2.send_headers_completed());
4414 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4415 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4417 EXPECT_TRUE(delegate3.send_headers_completed());
4418 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4420 EXPECT_TRUE(data.at_write_eof());
4423 // Cause a stall by reducing the flow control send window to
4424 // 0. Unstalling the session should properly handle the session itself
4426 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4427 if (GetParam() < kProtoSPDY31)
4430 const char kStreamUrl[] = "http://www.google.com/";
4431 GURL url(kStreamUrl);
4433 session_deps_.host_resolver->set_synchronous_mode(true);
4435 scoped_ptr<SpdyFrame> req1(
4436 spdy_util_.ConstructSpdyPost(
4437 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4438 scoped_ptr<SpdyFrame> req2(
4439 spdy_util_.ConstructSpdyPost(
4440 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4441 scoped_ptr<SpdyFrame> body1(
4442 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4443 MockWrite writes[] = {
4444 CreateMockWrite(*req1, 0),
4445 CreateMockWrite(*req2, 1),
4448 MockRead reads[] = {
4449 MockRead(ASYNC, 0, 0, 2), // EOF
4452 DeterministicSocketData data(reads, arraysize(reads),
4453 writes, arraysize(writes));
4454 MockConnect connect_data(SYNCHRONOUS, OK);
4455 data.set_connect_data(connect_data);
4457 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4459 CreateDeterministicNetworkSession();
4460 base::WeakPtr<SpdySession> session =
4461 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4462 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4463 session->flow_control_state());
4465 base::WeakPtr<SpdyStream> stream1 =
4466 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4467 session, url, LOWEST, BoundNetLog());
4468 ASSERT_TRUE(stream1.get() != NULL);
4470 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4471 stream1->SetDelegate(&delegate1);
4473 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4475 base::WeakPtr<SpdyStream> stream2 =
4476 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4477 session, url, LOWEST, BoundNetLog());
4478 ASSERT_TRUE(stream2.get() != NULL);
4480 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4481 stream2->SetDelegate(&delegate2);
4483 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4485 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4486 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4488 StallSessionSend(session.get());
4490 scoped_ptr<SpdyHeaderBlock> headers1(
4491 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4492 EXPECT_EQ(ERR_IO_PENDING,
4493 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4494 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4495 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4498 EXPECT_EQ(1u, stream1->stream_id());
4499 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4501 scoped_ptr<SpdyHeaderBlock> headers2(
4502 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4503 EXPECT_EQ(ERR_IO_PENDING,
4504 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4505 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4506 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4509 EXPECT_EQ(3u, stream2->stream_id());
4510 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4512 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4515 UnstallSessionSend(session.get(), kBodyDataSize);
4517 // Close the session (since we can't do it from within the delegate
4518 // method, since it's in the stream's loop).
4519 session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4520 base::RunLoop().RunUntilIdle();
4521 EXPECT_TRUE(session == NULL);
4523 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4525 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4526 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4528 EXPECT_TRUE(delegate1.send_headers_completed());
4529 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4531 EXPECT_TRUE(delegate2.send_headers_completed());
4532 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4534 EXPECT_TRUE(data.at_write_eof());
4537 TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4538 if (GetParam() < kProtoSPDY31)
4541 MockConnect connect_data(SYNCHRONOUS, OK);
4543 scoped_ptr<SpdyFrame> req(
4544 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4545 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4547 GOAWAY_FLOW_CONTROL_ERROR,
4548 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4549 "the receive window size of 1"));
4550 MockWrite writes[] = {
4551 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
4554 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4555 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4556 MockRead reads[] = {
4557 CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
4560 DeterministicSocketData data(
4561 reads, arraysize(reads), writes, arraysize(writes));
4562 data.set_connect_data(connect_data);
4563 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4565 CreateDeterministicNetworkSession();
4567 base::WeakPtr<SpdySession> session =
4568 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4570 GURL url(kDefaultURL);
4571 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4572 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
4573 ASSERT_TRUE(spdy_stream.get() != NULL);
4574 test::StreamDelegateDoNothing delegate(spdy_stream);
4575 spdy_stream->SetDelegate(&delegate);
4577 scoped_ptr<SpdyHeaderBlock> headers(
4578 spdy_util_.ConstructGetHeaderBlock(url.spec()));
4579 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4581 data.RunFor(1); // Write request.
4583 // Put session on the edge of overflowing it's recv window.
4584 session->session_recv_window_size_ = 1;
4586 // Read response headers & body. Body overflows the session window, and a
4587 // goaway is written.
4589 base::MessageLoop::current()->RunUntilIdle();
4591 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4592 EXPECT_TRUE(session == NULL);
4595 TEST_P(SpdySessionTest, SplitHeaders) {
4596 GURL kStreamUrl("http://www.google.com/foo.dat");
4597 SpdyHeaderBlock headers;
4598 spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4599 headers["alpha"] = "beta";
4601 SpdyHeaderBlock request_headers;
4602 SpdyHeaderBlock response_headers;
4604 SplitPushedHeadersToRequestAndResponse(
4605 headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4607 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4608 std::string alpha_val =
4609 (it == response_headers.end()) ? std::string() : it->second;
4610 EXPECT_EQ("beta", alpha_val);
4613 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4614 EXPECT_EQ(kStreamUrl, request_url);
4617 // Regression. Sorta. Push streams and client streams were sharing a single
4618 // limit for a long time.
4619 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4620 SettingsMap new_settings;
4621 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4622 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4623 scoped_ptr<SpdyFrame> settings_frame(
4624 spdy_util_.ConstructSpdySettings(new_settings));
4625 scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4626 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4627 MockRead reads[] = {
4628 CreateMockRead(*settings_frame), CreateMockRead(*pushed, 3),
4629 MockRead(ASYNC, 0, 4),
4632 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4633 scoped_ptr<SpdyFrame> req(
4634 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4635 MockWrite writes[] = {
4636 CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4639 DeterministicSocketData data(
4640 reads, arraysize(reads), writes, arraysize(writes));
4641 MockConnect connect_data(SYNCHRONOUS, OK);
4642 data.set_connect_data(connect_data);
4643 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4645 CreateDeterministicNetworkSession();
4647 base::WeakPtr<SpdySession> session =
4648 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4650 // Read the settings frame.
4653 GURL url1(kDefaultURL);
4654 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4655 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4656 ASSERT_TRUE(spdy_stream1.get() != NULL);
4657 EXPECT_EQ(0u, spdy_stream1->stream_id());
4658 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4659 spdy_stream1->SetDelegate(&delegate1);
4661 EXPECT_EQ(0u, session->num_active_streams());
4662 EXPECT_EQ(1u, session->num_created_streams());
4663 EXPECT_EQ(0u, session->num_pushed_streams());
4664 EXPECT_EQ(0u, session->num_active_pushed_streams());
4666 scoped_ptr<SpdyHeaderBlock> headers(
4667 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4668 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4669 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4671 // Run until 1st stream is activated.
4672 EXPECT_EQ(0u, delegate1.stream_id());
4674 EXPECT_EQ(1u, delegate1.stream_id());
4675 EXPECT_EQ(1u, session->num_active_streams());
4676 EXPECT_EQ(0u, session->num_created_streams());
4677 EXPECT_EQ(0u, session->num_pushed_streams());
4678 EXPECT_EQ(0u, session->num_active_pushed_streams());
4680 // Run until pushed stream is created.
4682 EXPECT_EQ(2u, session->num_active_streams());
4683 EXPECT_EQ(0u, session->num_created_streams());
4684 EXPECT_EQ(1u, session->num_pushed_streams());
4685 EXPECT_EQ(1u, session->num_active_pushed_streams());
4687 // Second stream should not be stalled, although we have 2 active streams, but
4688 // one of them is push stream and should not be taken into account when we
4689 // create streams on the client.
4690 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4691 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4692 EXPECT_TRUE(spdy_stream2.get() != NULL);
4693 EXPECT_EQ(2u, session->num_active_streams());
4694 EXPECT_EQ(1u, session->num_created_streams());
4695 EXPECT_EQ(1u, session->num_pushed_streams());
4696 EXPECT_EQ(1u, session->num_active_pushed_streams());
4702 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4703 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4704 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4705 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4706 NULL, 0, 4, 1, "http://www.google.com/b.dat"));
4707 MockRead reads[] = {
4708 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4709 MockRead(ASYNC, 0, 4),
4712 scoped_ptr<SpdyFrame> req(
4713 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4714 scoped_ptr<SpdyFrame> rst(
4715 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4716 MockWrite writes[] = {
4717 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4720 DeterministicSocketData data(
4721 reads, arraysize(reads), writes, arraysize(writes));
4722 MockConnect connect_data(SYNCHRONOUS, OK);
4723 data.set_connect_data(connect_data);
4724 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4726 CreateDeterministicNetworkSession();
4728 base::WeakPtr<SpdySession> session =
4729 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4730 session->set_max_concurrent_pushed_streams(1);
4732 GURL url1(kDefaultURL);
4733 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4734 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4735 ASSERT_TRUE(spdy_stream1.get() != NULL);
4736 EXPECT_EQ(0u, spdy_stream1->stream_id());
4737 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4738 spdy_stream1->SetDelegate(&delegate1);
4740 EXPECT_EQ(0u, session->num_active_streams());
4741 EXPECT_EQ(1u, session->num_created_streams());
4742 EXPECT_EQ(0u, session->num_pushed_streams());
4743 EXPECT_EQ(0u, session->num_active_pushed_streams());
4745 scoped_ptr<SpdyHeaderBlock> headers(
4746 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4747 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4748 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4750 // Run until 1st stream is activated.
4751 EXPECT_EQ(0u, delegate1.stream_id());
4753 EXPECT_EQ(1u, delegate1.stream_id());
4754 EXPECT_EQ(1u, session->num_active_streams());
4755 EXPECT_EQ(0u, session->num_created_streams());
4756 EXPECT_EQ(0u, session->num_pushed_streams());
4757 EXPECT_EQ(0u, session->num_active_pushed_streams());
4759 // Run until pushed stream is created.
4761 EXPECT_EQ(2u, session->num_active_streams());
4762 EXPECT_EQ(0u, session->num_created_streams());
4763 EXPECT_EQ(1u, session->num_pushed_streams());
4764 EXPECT_EQ(1u, session->num_active_pushed_streams());
4766 // Reset incoming pushed stream.
4768 EXPECT_EQ(2u, session->num_active_streams());
4769 EXPECT_EQ(0u, session->num_created_streams());
4770 EXPECT_EQ(1u, session->num_pushed_streams());
4771 EXPECT_EQ(1u, session->num_active_pushed_streams());
4777 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4778 // Streams in reserved remote state exist only in SPDY4.
4779 if (spdy_util_.spdy_version() < SPDY4)
4782 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4783 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4784 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4785 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
4786 push_headers.get());
4787 scoped_ptr<SpdyFrame> push_b(
4788 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4789 scoped_ptr<SpdyFrame> headers_b(
4790 spdy_util_.ConstructSpdyPushHeaders(4, NULL, 0));
4791 MockRead reads[] = {
4792 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4793 CreateMockRead(*headers_b, 3), MockRead(ASYNC, 0, 5),
4796 scoped_ptr<SpdyFrame> req(
4797 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4798 scoped_ptr<SpdyFrame> rst(
4799 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4800 MockWrite writes[] = {
4801 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
4804 DeterministicSocketData data(
4805 reads, arraysize(reads), writes, arraysize(writes));
4806 MockConnect connect_data(SYNCHRONOUS, OK);
4807 data.set_connect_data(connect_data);
4808 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4810 CreateDeterministicNetworkSession();
4812 base::WeakPtr<SpdySession> session =
4813 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4814 session->set_max_concurrent_pushed_streams(1);
4816 GURL url1(kDefaultURL);
4817 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4818 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4819 ASSERT_TRUE(spdy_stream1.get() != NULL);
4820 EXPECT_EQ(0u, spdy_stream1->stream_id());
4821 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4822 spdy_stream1->SetDelegate(&delegate1);
4824 EXPECT_EQ(0u, session->num_active_streams());
4825 EXPECT_EQ(1u, session->num_created_streams());
4826 EXPECT_EQ(0u, session->num_pushed_streams());
4827 EXPECT_EQ(0u, session->num_active_pushed_streams());
4829 scoped_ptr<SpdyHeaderBlock> headers(
4830 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4831 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4832 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4834 // Run until 1st stream is activated.
4835 EXPECT_EQ(0u, delegate1.stream_id());
4837 EXPECT_EQ(1u, delegate1.stream_id());
4838 EXPECT_EQ(1u, session->num_active_streams());
4839 EXPECT_EQ(0u, session->num_created_streams());
4840 EXPECT_EQ(0u, session->num_pushed_streams());
4841 EXPECT_EQ(0u, session->num_active_pushed_streams());
4843 // Run until pushed stream is created.
4845 EXPECT_EQ(2u, session->num_active_streams());
4846 EXPECT_EQ(0u, session->num_created_streams());
4847 EXPECT_EQ(1u, session->num_pushed_streams());
4848 EXPECT_EQ(1u, session->num_active_pushed_streams());
4850 // Accept promised stream. It should not count towards pushed stream limit.
4852 EXPECT_EQ(3u, session->num_active_streams());
4853 EXPECT_EQ(0u, session->num_created_streams());
4854 EXPECT_EQ(2u, session->num_pushed_streams());
4855 EXPECT_EQ(1u, session->num_active_pushed_streams());
4857 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4858 // while we accept only one.
4860 EXPECT_EQ(2u, session->num_active_streams());
4861 EXPECT_EQ(0u, session->num_created_streams());
4862 EXPECT_EQ(1u, session->num_pushed_streams());
4863 EXPECT_EQ(1u, session->num_active_pushed_streams());
4869 TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
4870 // Streams in reserved remote state exist only in SPDY4.
4871 if (spdy_util_.spdy_version() < SPDY4)
4874 const char kPushedUrl[] = "http://www.google.com/a.dat";
4875 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4876 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
4877 scoped_ptr<SpdyFrame> push_promise(
4878 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
4879 scoped_ptr<SpdyFrame> headers_frame(
4880 spdy_util_.ConstructSpdyPushHeaders(2, NULL, 0));
4881 MockRead reads[] = {
4882 CreateMockRead(*push_promise, 1), CreateMockRead(*headers_frame, 2),
4883 MockRead(ASYNC, 0, 4),
4886 scoped_ptr<SpdyFrame> req(
4887 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4888 scoped_ptr<SpdyFrame> rst(
4889 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
4890 MockWrite writes[] = {
4891 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4894 DeterministicSocketData data(
4895 reads, arraysize(reads), writes, arraysize(writes));
4896 MockConnect connect_data(SYNCHRONOUS, OK);
4897 data.set_connect_data(connect_data);
4898 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4900 CreateDeterministicNetworkSession();
4902 base::WeakPtr<SpdySession> session =
4903 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4905 GURL url1(kDefaultURL);
4906 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4907 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4908 ASSERT_TRUE(spdy_stream1.get() != NULL);
4909 EXPECT_EQ(0u, spdy_stream1->stream_id());
4910 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4911 spdy_stream1->SetDelegate(&delegate1);
4913 EXPECT_EQ(0u, session->num_active_streams());
4914 EXPECT_EQ(1u, session->num_created_streams());
4915 EXPECT_EQ(0u, session->num_pushed_streams());
4916 EXPECT_EQ(0u, session->num_active_pushed_streams());
4918 scoped_ptr<SpdyHeaderBlock> headers(
4919 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4920 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4921 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4923 // Run until 1st stream is activated.
4924 EXPECT_EQ(0u, delegate1.stream_id());
4926 EXPECT_EQ(1u, delegate1.stream_id());
4927 EXPECT_EQ(1u, session->num_active_streams());
4928 EXPECT_EQ(0u, session->num_created_streams());
4929 EXPECT_EQ(0u, session->num_pushed_streams());
4930 EXPECT_EQ(0u, session->num_active_pushed_streams());
4932 // Run until pushed stream is created.
4934 EXPECT_EQ(2u, session->num_active_streams());
4935 EXPECT_EQ(0u, session->num_created_streams());
4936 EXPECT_EQ(1u, session->num_pushed_streams());
4937 EXPECT_EQ(0u, session->num_active_pushed_streams());
4939 base::WeakPtr<SpdyStream> pushed_stream;
4941 session->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
4943 ASSERT_TRUE(pushed_stream.get() != NULL);
4944 test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
4945 pushed_stream->SetDelegate(&delegate2);
4947 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4948 // that all our counters are in consistent state.
4950 EXPECT_EQ(1u, session->num_active_streams());
4951 EXPECT_EQ(0u, session->num_created_streams());
4952 EXPECT_EQ(0u, session->num_pushed_streams());
4953 EXPECT_EQ(0u, session->num_active_pushed_streams());
4959 TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
4960 session_deps_.host_resolver->set_synchronous_mode(true);
4962 MockRead reads[] = {
4963 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
4966 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
4968 MockConnect connect_data(SYNCHRONOUS, OK);
4969 data.set_connect_data(connect_data);
4970 session_deps_.socket_factory->AddSocketDataProvider(&data);
4972 CreateNetworkSession();
4973 base::WeakPtr<SpdySession> session =
4974 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4976 session->stream_hi_water_mark_ = 5;
4977 // Low client (odd) ids are fine.
4978 EXPECT_TRUE(session->OnUnknownFrame(3, 0));
4979 // Client id exceeding watermark.
4980 EXPECT_FALSE(session->OnUnknownFrame(9, 0));
4982 session->last_accepted_push_stream_id_ = 6;
4983 // Low server (even) ids are fine.
4984 EXPECT_TRUE(session->OnUnknownFrame(2, 0));
4985 // Server id exceeding last accepted id.
4986 EXPECT_FALSE(session->OnUnknownFrame(8, 0));
4989 TEST(MapFramerErrorToProtocolError, MapsValues) {
4991 SPDY_ERROR_INVALID_CONTROL_FRAME,
4992 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4994 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4995 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4997 SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
4998 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
4999 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
5000 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
5003 TEST(MapFramerErrorToNetError, MapsValue) {
5004 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
5005 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
5006 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5007 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
5008 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5009 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
5011 ERR_SPDY_FRAME_SIZE_ERROR,
5012 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
5015 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
5016 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
5017 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
5018 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
5019 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
5020 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
5021 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
5024 TEST(MapNetErrorToGoAwayStatus, MapsValue) {
5025 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
5026 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
5027 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
5028 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
5029 CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
5030 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
5031 CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
5032 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
5033 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
5034 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
5035 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
5038 TEST(CanPoolTest, CanPool) {
5039 // Load a cert that is valid for:
5044 TransportSecurityState tss;
5046 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5047 "spdy_pooling.pem");
5049 EXPECT_TRUE(SpdySession::CanPool(
5050 &tss, ssl_info, "www.example.org", "www.example.org"));
5051 EXPECT_TRUE(SpdySession::CanPool(
5052 &tss, ssl_info, "www.example.org", "mail.example.org"));
5053 EXPECT_TRUE(SpdySession::CanPool(
5054 &tss, ssl_info, "www.example.org", "mail.example.com"));
5055 EXPECT_FALSE(SpdySession::CanPool(
5056 &tss, ssl_info, "www.example.org", "mail.google.com"));
5059 TEST(CanPoolTest, CanNotPoolWithCertErrors) {
5060 // Load a cert that is valid for:
5065 TransportSecurityState tss;
5067 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5068 "spdy_pooling.pem");
5069 ssl_info.cert_status = CERT_STATUS_REVOKED;
5071 EXPECT_FALSE(SpdySession::CanPool(
5072 &tss, ssl_info, "www.example.org", "mail.example.org"));
5075 TEST(CanPoolTest, CanNotPoolWithClientCerts) {
5076 // Load a cert that is valid for:
5081 TransportSecurityState tss;
5083 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5084 "spdy_pooling.pem");
5085 ssl_info.client_cert_sent = true;
5087 EXPECT_FALSE(SpdySession::CanPool(
5088 &tss, ssl_info, "www.example.org", "mail.example.org"));
5091 TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
5092 // Load a cert that is valid for:
5097 TransportSecurityState tss;
5099 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5100 "spdy_pooling.pem");
5101 ssl_info.channel_id_sent = true;
5103 EXPECT_TRUE(SpdySession::CanPool(
5104 &tss, ssl_info, "www.example.org", "mail.example.org"));
5105 EXPECT_FALSE(SpdySession::CanPool(
5106 &tss, ssl_info, "www.example.org", "www.example.com"));
5109 TEST(CanPoolTest, CanNotPoolWithBadPins) {
5110 uint8 primary_pin = 1;
5111 uint8 backup_pin = 2;
5113 TransportSecurityState tss;
5114 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5117 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5118 "spdy_pooling.pem");
5119 ssl_info.is_issued_by_known_root = true;
5120 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
5122 EXPECT_FALSE(SpdySession::CanPool(
5123 &tss, ssl_info, "www.example.org", "mail.example.org"));
5126 TEST(CanPoolTest, CanPoolWithAcceptablePins) {
5127 uint8 primary_pin = 1;
5128 uint8 backup_pin = 2;
5129 TransportSecurityState tss;
5130 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5133 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5134 "spdy_pooling.pem");
5135 ssl_info.is_issued_by_known_root = true;
5136 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
5138 EXPECT_TRUE(SpdySession::CanPool(
5139 &tss, ssl_info, "www.example.org", "mail.example.org"));