Add GN isolate support for a bunch of unittests.
[chromium-blink-merge.git] / net / spdy / spdy_session_unittest.cc
blob8368038cb27dde004b268edd64cd2e2b805146f3
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"
8 #include "base/bind.h"
9 #include "base/callback.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/test/histogram_tester.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/ip_endpoint.h"
15 #include "net/base/request_priority.h"
16 #include "net/base/test_data_directory.h"
17 #include "net/base/test_data_stream.h"
18 #include "net/log/test_net_log.h"
19 #include "net/log/test_net_log_entry.h"
20 #include "net/log/test_net_log_util.h"
21 #include "net/socket/client_socket_pool_manager.h"
22 #include "net/socket/next_proto.h"
23 #include "net/socket/socket_test_util.h"
24 #include "net/spdy/spdy_http_utils.h"
25 #include "net/spdy/spdy_session_pool.h"
26 #include "net/spdy/spdy_session_test_util.h"
27 #include "net/spdy/spdy_stream.h"
28 #include "net/spdy/spdy_stream_test_util.h"
29 #include "net/spdy/spdy_test_util_common.h"
30 #include "net/spdy/spdy_test_utils.h"
31 #include "net/test/cert_test_util.h"
32 #include "testing/platform_test.h"
34 namespace net {
36 namespace {
38 static const char kTestUrl[] = "http://www.example.org/";
39 static const char kTestHost[] = "www.example.org";
40 static const int kTestPort = 80;
42 const char kBodyData[] = "Body data";
43 const size_t kBodyDataSize = arraysize(kBodyData);
44 const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize);
46 static base::TimeDelta g_time_delta;
47 base::TimeTicks TheNearFuture() {
48 return base::TimeTicks::Now() + g_time_delta;
51 base::TimeTicks SlowReads() {
52 g_time_delta +=
53 base::TimeDelta::FromMilliseconds(2 * kYieldAfterDurationMilliseconds);
54 return base::TimeTicks::Now() + g_time_delta;
57 } // namespace
59 class SpdySessionTest : public PlatformTest,
60 public ::testing::WithParamInterface<NextProto> {
61 public:
62 // Functions used with RunResumeAfterUnstallTest().
64 void StallSessionOnly(SpdySession* session, SpdyStream* stream) {
65 StallSessionSend(session);
68 void StallStreamOnly(SpdySession* session, SpdyStream* stream) {
69 StallStreamSend(stream);
72 void StallSessionStream(SpdySession* session, SpdyStream* stream) {
73 StallSessionSend(session);
74 StallStreamSend(stream);
77 void StallStreamSession(SpdySession* session, SpdyStream* stream) {
78 StallStreamSend(stream);
79 StallSessionSend(session);
82 void UnstallSessionOnly(SpdySession* session,
83 SpdyStream* stream,
84 int32 delta_window_size) {
85 UnstallSessionSend(session, delta_window_size);
88 void UnstallStreamOnly(SpdySession* session,
89 SpdyStream* stream,
90 int32 delta_window_size) {
91 UnstallStreamSend(stream, delta_window_size);
94 void UnstallSessionStream(SpdySession* session,
95 SpdyStream* stream,
96 int32 delta_window_size) {
97 UnstallSessionSend(session, delta_window_size);
98 UnstallStreamSend(stream, delta_window_size);
101 void UnstallStreamSession(SpdySession* session,
102 SpdyStream* stream,
103 int32 delta_window_size) {
104 UnstallStreamSend(stream, delta_window_size);
105 UnstallSessionSend(session, delta_window_size);
108 protected:
109 SpdySessionTest()
110 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
111 HttpNetworkSession::NORMAL_SOCKET_POOL)),
112 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
113 HttpNetworkSession::NORMAL_SOCKET_POOL)),
114 spdy_util_(GetParam()),
115 session_deps_(GetParam()),
116 spdy_session_pool_(nullptr),
117 test_url_(kTestUrl),
118 test_host_port_pair_(kTestHost, kTestPort),
119 key_(test_host_port_pair_,
120 ProxyServer::Direct(),
121 PRIVACY_MODE_DISABLED) {}
123 virtual ~SpdySessionTest() {
124 // Important to restore the per-pool limit first, since the pool limit must
125 // always be greater than group limit, and the tests reduce both limits.
126 ClientSocketPoolManager::set_max_sockets_per_pool(
127 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
128 ClientSocketPoolManager::set_max_sockets_per_group(
129 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
132 void SetUp() override { g_time_delta = base::TimeDelta(); }
134 void CreateNetworkSession() {
135 http_session_ =
136 SpdySessionDependencies::SpdyCreateSession(&session_deps_);
137 spdy_session_pool_ = http_session_->spdy_session_pool();
140 void StallSessionSend(SpdySession* session) {
141 // Reduce the send window size to 0 to stall.
142 while (session->session_send_window_size_ > 0) {
143 session->DecreaseSendWindowSize(
144 std::min(kMaxSpdyFrameChunkSize, session->session_send_window_size_));
148 void UnstallSessionSend(SpdySession* session, int32 delta_window_size) {
149 session->IncreaseSendWindowSize(delta_window_size);
152 void StallStreamSend(SpdyStream* stream) {
153 // Reduce the send window size to 0 to stall.
154 while (stream->send_window_size() > 0) {
155 stream->DecreaseSendWindowSize(
156 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
160 void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) {
161 stream->IncreaseSendWindowSize(delta_window_size);
164 void RunResumeAfterUnstallTest(
165 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
166 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
167 unstall_function);
169 // Original socket limits. Some tests set these. Safest to always restore
170 // them once each test has been run.
171 int old_max_group_sockets_;
172 int old_max_pool_sockets_;
174 SpdyTestUtil spdy_util_;
175 SpdySessionDependencies session_deps_;
176 scoped_refptr<HttpNetworkSession> http_session_;
177 SpdySessionPool* spdy_session_pool_;
178 GURL test_url_;
179 HostPortPair test_host_port_pair_;
180 SpdySessionKey key_;
183 INSTANTIATE_TEST_CASE_P(NextProto,
184 SpdySessionTest,
185 testing::Values(kProtoSPDY31,
186 kProtoHTTP2_14,
187 kProtoHTTP2));
189 // Try to create a SPDY session that will fail during
190 // initialization. Nothing should blow up.
191 TEST_P(SpdySessionTest, InitialReadError) {
192 CreateNetworkSession();
194 base::WeakPtr<SpdySession> session = TryCreateFakeSpdySessionExpectingFailure(
195 spdy_session_pool_, key_, ERR_CONNECTION_CLOSED);
196 EXPECT_TRUE(session);
197 // Flush the read.
198 base::RunLoop().RunUntilIdle();
199 EXPECT_FALSE(session);
202 namespace {
204 // A helper class that vends a callback that, when fired, destroys a
205 // given SpdyStreamRequest.
206 class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
207 public:
208 StreamRequestDestroyingCallback() {}
210 ~StreamRequestDestroyingCallback() override {}
212 void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) {
213 request_ = request.Pass();
216 CompletionCallback MakeCallback() {
217 return base::Bind(&StreamRequestDestroyingCallback::OnComplete,
218 base::Unretained(this));
221 private:
222 void OnComplete(int result) {
223 request_.reset();
224 SetResult(result);
227 scoped_ptr<SpdyStreamRequest> request_;
230 } // namespace
232 // Request kInitialMaxConcurrentStreams streams. Request two more
233 // streams, but have the callback for one destroy the second stream
234 // request. Close the session. Nothing should blow up. This is a
235 // regression test for http://crbug.com/250841 .
236 TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
237 session_deps_.host_resolver->set_synchronous_mode(true);
239 MockRead reads[] = {MockRead(ASYNC, 0, 0), };
241 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
242 session_deps_.socket_factory->AddSocketDataProvider(&data);
244 CreateNetworkSession();
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 != nullptr);
256 SpdyStreamRequest request1;
257 scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest);
259 StreamRequestDestroyingCallback callback1;
260 ASSERT_EQ(ERR_IO_PENDING,
261 request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM,
262 session,
263 test_url_,
264 MEDIUM,
265 BoundNetLog(),
266 callback1.MakeCallback()));
268 // |callback2| is never called.
269 TestCompletionCallback callback2;
270 ASSERT_EQ(ERR_IO_PENDING,
271 request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM,
272 session,
273 test_url_,
274 MEDIUM,
275 BoundNetLog(),
276 callback2.callback()));
278 callback1.SetRequestToDestroy(request2.Pass());
280 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
282 EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
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 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
290 MockRead reads[] = {
291 CreateMockRead(*goaway, 0),
293 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
294 session_deps_.socket_factory->AddSocketDataProvider(&data);
296 CreateNetworkSession();
298 base::WeakPtr<SpdySession> session =
299 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
301 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
303 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
305 // Read and process the GOAWAY frame.
306 base::RunLoop().RunUntilIdle();
307 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
308 EXPECT_FALSE(session);
311 // A session receiving a GOAWAY frame immediately with no active
312 // streams should then close.
313 TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
314 session_deps_.host_resolver->set_synchronous_mode(true);
316 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
317 MockRead reads[] = {
318 CreateMockRead(*goaway, 0, SYNCHRONOUS), MockRead(ASYNC, 0, 1) // EOF
320 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
321 session_deps_.socket_factory->AddSocketDataProvider(&data);
323 CreateNetworkSession();
325 base::WeakPtr<SpdySession> session =
326 TryCreateInsecureSpdySessionExpectingFailure(
327 http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
328 base::RunLoop().RunUntilIdle();
330 EXPECT_FALSE(session);
331 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
332 EXPECT_FALSE(data.AllReadDataConsumed());
335 // A session receiving a GOAWAY frame with active streams should close
336 // when the last active stream is closed.
337 TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
338 session_deps_.host_resolver->set_synchronous_mode(true);
340 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
341 MockRead reads[] = {
342 MockRead(ASYNC, ERR_IO_PENDING, 2),
343 CreateMockRead(*goaway, 3),
344 MockRead(ASYNC, ERR_IO_PENDING, 4),
345 MockRead(ASYNC, 0, 5) // EOF
347 scoped_ptr<SpdyFrame> req1(
348 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
349 scoped_ptr<SpdyFrame> req2(
350 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
351 MockWrite writes[] = {
352 CreateMockWrite(*req1, 0),
353 CreateMockWrite(*req2, 1),
355 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
356 session_deps_.socket_factory->AddSocketDataProvider(&data);
358 CreateNetworkSession();
360 base::WeakPtr<SpdySession> session =
361 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
363 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
365 GURL url(kDefaultURL);
366 base::WeakPtr<SpdyStream> spdy_stream1 =
367 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
368 session, url, MEDIUM, BoundNetLog());
369 test::StreamDelegateDoNothing delegate1(spdy_stream1);
370 spdy_stream1->SetDelegate(&delegate1);
372 base::WeakPtr<SpdyStream> spdy_stream2 =
373 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
374 session, url, MEDIUM, BoundNetLog());
375 test::StreamDelegateDoNothing delegate2(spdy_stream2);
376 spdy_stream2->SetDelegate(&delegate2);
378 scoped_ptr<SpdyHeaderBlock> headers(
379 spdy_util_.ConstructGetHeaderBlock(url.spec()));
380 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
382 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
383 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
384 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
385 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
387 base::RunLoop().RunUntilIdle();
389 EXPECT_EQ(1u, spdy_stream1->stream_id());
390 EXPECT_EQ(3u, spdy_stream2->stream_id());
392 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
394 // Read and process the GOAWAY frame.
395 data.CompleteRead();
396 base::RunLoop().RunUntilIdle();
398 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
400 EXPECT_FALSE(session->IsStreamActive(3));
401 EXPECT_FALSE(spdy_stream2);
402 EXPECT_TRUE(session->IsStreamActive(1));
404 EXPECT_TRUE(session->IsGoingAway());
406 // Should close the session.
407 spdy_stream1->Close();
408 EXPECT_FALSE(spdy_stream1);
410 EXPECT_TRUE(session);
411 data.CompleteRead();
412 base::RunLoop().RunUntilIdle();
413 EXPECT_FALSE(session);
416 // Have a session receive two GOAWAY frames, with the last one causing
417 // the last active stream to be closed. The session should then be
418 // closed after the second GOAWAY frame.
419 TEST_P(SpdySessionTest, GoAwayTwice) {
420 session_deps_.host_resolver->set_synchronous_mode(true);
422 scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
423 scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
424 MockRead reads[] = {
425 MockRead(ASYNC, ERR_IO_PENDING, 2),
426 CreateMockRead(*goaway1, 3),
427 MockRead(ASYNC, ERR_IO_PENDING, 4),
428 CreateMockRead(*goaway2, 5),
429 MockRead(ASYNC, ERR_IO_PENDING, 6),
430 MockRead(ASYNC, 0, 7) // EOF
432 scoped_ptr<SpdyFrame> req1(
433 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
434 scoped_ptr<SpdyFrame> req2(
435 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
436 MockWrite writes[] = {
437 CreateMockWrite(*req1, 0),
438 CreateMockWrite(*req2, 1),
440 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
441 session_deps_.socket_factory->AddSocketDataProvider(&data);
443 CreateNetworkSession();
445 base::WeakPtr<SpdySession> session =
446 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
448 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
450 GURL url(kDefaultURL);
451 base::WeakPtr<SpdyStream> spdy_stream1 =
452 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
453 session, url, MEDIUM, BoundNetLog());
454 test::StreamDelegateDoNothing delegate1(spdy_stream1);
455 spdy_stream1->SetDelegate(&delegate1);
457 base::WeakPtr<SpdyStream> spdy_stream2 =
458 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
459 session, url, MEDIUM, BoundNetLog());
460 test::StreamDelegateDoNothing delegate2(spdy_stream2);
461 spdy_stream2->SetDelegate(&delegate2);
463 scoped_ptr<SpdyHeaderBlock> headers(
464 spdy_util_.ConstructGetHeaderBlock(url.spec()));
465 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
467 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
468 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
469 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
470 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
472 base::RunLoop().RunUntilIdle();
474 EXPECT_EQ(1u, spdy_stream1->stream_id());
475 EXPECT_EQ(3u, spdy_stream2->stream_id());
477 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
479 // Read and process the first GOAWAY frame.
480 data.CompleteRead();
481 base::RunLoop().RunUntilIdle();
483 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
485 EXPECT_FALSE(session->IsStreamActive(3));
486 EXPECT_FALSE(spdy_stream2);
487 EXPECT_TRUE(session->IsStreamActive(1));
488 EXPECT_TRUE(session->IsGoingAway());
490 // Read and process the second GOAWAY frame, which should close the
491 // session.
492 data.CompleteRead();
493 base::RunLoop().RunUntilIdle();
494 EXPECT_FALSE(session);
497 // Have a session with active streams receive a GOAWAY frame and then
498 // close it. It should handle the close properly (i.e., not try to
499 // make itself unavailable in its pool twice).
500 TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
501 session_deps_.host_resolver->set_synchronous_mode(true);
503 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
504 MockRead reads[] = {
505 MockRead(ASYNC, ERR_IO_PENDING, 2),
506 CreateMockRead(*goaway, 3),
507 MockRead(ASYNC, ERR_IO_PENDING, 4),
508 MockRead(ASYNC, 0, 5) // EOF
510 scoped_ptr<SpdyFrame> req1(
511 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
512 scoped_ptr<SpdyFrame> req2(
513 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
514 MockWrite writes[] = {
515 CreateMockWrite(*req1, 0),
516 CreateMockWrite(*req2, 1),
518 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
519 session_deps_.socket_factory->AddSocketDataProvider(&data);
521 CreateNetworkSession();
523 base::WeakPtr<SpdySession> session =
524 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
526 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
528 GURL url(kDefaultURL);
529 base::WeakPtr<SpdyStream> spdy_stream1 =
530 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
531 session, url, MEDIUM, BoundNetLog());
532 test::StreamDelegateDoNothing delegate1(spdy_stream1);
533 spdy_stream1->SetDelegate(&delegate1);
535 base::WeakPtr<SpdyStream> spdy_stream2 =
536 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
537 session, url, MEDIUM, BoundNetLog());
538 test::StreamDelegateDoNothing delegate2(spdy_stream2);
539 spdy_stream2->SetDelegate(&delegate2);
541 scoped_ptr<SpdyHeaderBlock> headers(
542 spdy_util_.ConstructGetHeaderBlock(url.spec()));
543 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
545 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
546 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
547 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
548 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
550 base::RunLoop().RunUntilIdle();
552 EXPECT_EQ(1u, spdy_stream1->stream_id());
553 EXPECT_EQ(3u, spdy_stream2->stream_id());
555 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
557 // Read and process the GOAWAY frame.
558 data.CompleteRead();
559 base::RunLoop().RunUntilIdle();
561 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
563 EXPECT_FALSE(session->IsStreamActive(3));
564 EXPECT_FALSE(spdy_stream2);
565 EXPECT_TRUE(session->IsStreamActive(1));
566 EXPECT_TRUE(session->IsGoingAway());
568 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
569 EXPECT_FALSE(spdy_stream1);
571 data.CompleteRead();
572 base::RunLoop().RunUntilIdle();
573 EXPECT_FALSE(session);
576 // Process a joint read buffer which causes the session to begin draining, and
577 // then processes a GOAWAY. The session should gracefully drain. Regression test
578 // for crbug.com/379469
579 TEST_P(SpdySessionTest, GoAwayWhileDraining) {
580 session_deps_.host_resolver->set_synchronous_mode(true);
582 scoped_ptr<SpdyFrame> req(
583 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
584 MockWrite writes[] = {
585 CreateMockWrite(*req, 0),
588 scoped_ptr<SpdyFrame> resp(
589 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
590 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
591 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
592 size_t joint_size = goaway->size() * 2 + body->size();
594 // Compose interleaved |goaway| and |body| frames into a single read.
595 scoped_ptr<char[]> buffer(new char[joint_size]);
597 size_t out = 0;
598 memcpy(&buffer[out], goaway->data(), goaway->size());
599 out += goaway->size();
600 memcpy(&buffer[out], body->data(), body->size());
601 out += body->size();
602 memcpy(&buffer[out], goaway->data(), goaway->size());
603 out += goaway->size();
604 ASSERT_EQ(out, joint_size);
606 SpdyFrame joint_frames(buffer.get(), joint_size, false);
608 MockRead reads[] = {
609 CreateMockRead(*resp, 1), CreateMockRead(joint_frames, 2),
610 MockRead(ASYNC, 0, 3) // EOF
613 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
614 session_deps_.socket_factory->AddSocketDataProvider(&data);
616 CreateNetworkSession();
617 base::WeakPtr<SpdySession> session =
618 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
620 GURL url(kDefaultURL);
621 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
622 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
623 test::StreamDelegateDoNothing delegate(spdy_stream);
624 spdy_stream->SetDelegate(&delegate);
626 scoped_ptr<SpdyHeaderBlock> headers(
627 spdy_util_.ConstructGetHeaderBlock(url.spec()));
628 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
629 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
631 base::RunLoop().RunUntilIdle();
633 // Stream and session closed gracefully.
634 EXPECT_TRUE(delegate.StreamIsClosed());
635 EXPECT_EQ(OK, delegate.WaitForClose());
636 EXPECT_EQ(kUploadData, delegate.TakeReceivedData());
637 EXPECT_FALSE(session);
640 // Try to create a stream after receiving a GOAWAY frame. It should
641 // fail.
642 TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
643 session_deps_.host_resolver->set_synchronous_mode(true);
645 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
646 MockRead reads[] = {
647 MockRead(ASYNC, ERR_IO_PENDING, 1),
648 CreateMockRead(*goaway, 2),
649 MockRead(ASYNC, ERR_IO_PENDING, 3),
650 MockRead(ASYNC, 0, 4) // EOF
652 scoped_ptr<SpdyFrame> req(
653 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
654 MockWrite writes[] = {
655 CreateMockWrite(*req, 0),
657 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
658 session_deps_.socket_factory->AddSocketDataProvider(&data);
660 CreateNetworkSession();
662 base::WeakPtr<SpdySession> session =
663 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
665 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
667 GURL url(kDefaultURL);
668 base::WeakPtr<SpdyStream> spdy_stream =
669 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
670 session, url, MEDIUM, BoundNetLog());
671 test::StreamDelegateDoNothing delegate(spdy_stream);
672 spdy_stream->SetDelegate(&delegate);
674 scoped_ptr<SpdyHeaderBlock> headers(
675 spdy_util_.ConstructGetHeaderBlock(url.spec()));
676 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
677 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
679 base::RunLoop().RunUntilIdle();
681 EXPECT_EQ(1u, spdy_stream->stream_id());
683 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
685 // Read and process the GOAWAY frame.
686 data.CompleteRead();
687 base::RunLoop().RunUntilIdle();
689 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
690 EXPECT_TRUE(session->IsStreamActive(1));
692 SpdyStreamRequest stream_request;
693 int rv = stream_request.StartRequest(
694 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog(),
695 CompletionCallback());
696 EXPECT_EQ(ERR_FAILED, rv);
698 EXPECT_TRUE(session);
699 data.CompleteRead();
700 base::RunLoop().RunUntilIdle();
701 EXPECT_FALSE(session);
704 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
705 // the stream being refused.
706 TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
707 session_deps_.host_resolver->set_synchronous_mode(true);
709 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
710 scoped_ptr<SpdyFrame> push(
711 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kDefaultURL));
712 MockRead reads[] = {
713 MockRead(ASYNC, ERR_IO_PENDING, 1),
714 CreateMockRead(*goaway, 2),
715 MockRead(ASYNC, ERR_IO_PENDING, 3),
716 CreateMockRead(*push, 4),
717 MockRead(ASYNC, 0, 6) // EOF
719 scoped_ptr<SpdyFrame> req(
720 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
721 scoped_ptr<SpdyFrame> rst(
722 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
723 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5)};
724 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
725 session_deps_.socket_factory->AddSocketDataProvider(&data);
727 CreateNetworkSession();
729 base::WeakPtr<SpdySession> session =
730 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
732 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
734 GURL url(kDefaultURL);
735 base::WeakPtr<SpdyStream> spdy_stream =
736 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
737 session, url, MEDIUM, BoundNetLog());
738 test::StreamDelegateDoNothing delegate(spdy_stream);
739 spdy_stream->SetDelegate(&delegate);
741 scoped_ptr<SpdyHeaderBlock> headers(
742 spdy_util_.ConstructGetHeaderBlock(url.spec()));
743 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
744 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
746 base::RunLoop().RunUntilIdle();
748 EXPECT_EQ(1u, spdy_stream->stream_id());
750 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
752 // Read and process the GOAWAY frame.
753 data.CompleteRead();
754 base::RunLoop().RunUntilIdle();
756 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
757 EXPECT_TRUE(session->IsStreamActive(1));
759 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
760 // and EOF.
761 data.CompleteRead();
762 base::RunLoop().RunUntilIdle();
763 EXPECT_FALSE(session);
766 // A session observing a network change with active streams should close
767 // when the last active stream is closed.
768 TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
769 session_deps_.host_resolver->set_synchronous_mode(true);
771 MockRead reads[] = {
772 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
774 scoped_ptr<SpdyFrame> req1(
775 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
776 MockWrite writes[] = {
777 CreateMockWrite(*req1, 0),
779 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
780 session_deps_.socket_factory->AddSocketDataProvider(&data);
782 CreateNetworkSession();
784 base::WeakPtr<SpdySession> session =
785 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
787 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
789 base::WeakPtr<SpdyStream> spdy_stream =
790 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session,
791 GURL(kDefaultURL), MEDIUM, BoundNetLog());
792 test::StreamDelegateDoNothing delegate(spdy_stream);
793 spdy_stream->SetDelegate(&delegate);
795 scoped_ptr<SpdyHeaderBlock> headers(
796 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
798 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
799 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
801 base::RunLoop().RunUntilIdle();
803 EXPECT_EQ(1u, spdy_stream->stream_id());
805 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
807 spdy_session_pool_->OnIPAddressChanged();
809 // The SpdySessionPool behavior differs based on how the OSs reacts to
810 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
811 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
812 // For OSs where the TCP connections will close upon relevant network
813 // changes, SpdySessionPool doesn't need to force them to close, so in these
814 // cases verify the session has become unavailable but remains open and the
815 // pre-existing stream is still active.
816 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
818 EXPECT_TRUE(session->IsGoingAway());
820 EXPECT_TRUE(session->IsStreamActive(1));
822 // Should close the session.
823 spdy_stream->Close();
824 #endif
825 EXPECT_FALSE(spdy_stream);
827 data.CompleteRead();
828 base::RunLoop().RunUntilIdle();
829 EXPECT_FALSE(session);
832 TEST_P(SpdySessionTest, ClientPing) {
833 session_deps_.enable_ping = true;
834 session_deps_.host_resolver->set_synchronous_mode(true);
836 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
837 MockRead reads[] = {
838 CreateMockRead(*read_ping, 1),
839 MockRead(ASYNC, ERR_IO_PENDING, 2),
840 MockRead(ASYNC, 0, 3) // EOF
842 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
843 MockWrite writes[] = {
844 CreateMockWrite(*write_ping, 0),
846 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
847 session_deps_.socket_factory->AddSocketDataProvider(&data);
849 CreateNetworkSession();
851 base::WeakPtr<SpdySession> session =
852 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
854 base::WeakPtr<SpdyStream> spdy_stream1 =
855 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
856 session, test_url_, MEDIUM, BoundNetLog());
857 ASSERT_TRUE(spdy_stream1.get() != nullptr);
858 test::StreamDelegateSendImmediate delegate(spdy_stream1, nullptr);
859 spdy_stream1->SetDelegate(&delegate);
861 base::TimeTicks before_ping_time = base::TimeTicks::Now();
863 session->set_connection_at_risk_of_loss_time(
864 base::TimeDelta::FromSeconds(-1));
865 session->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
867 session->SendPrefacePingIfNoneInFlight();
869 base::RunLoop().RunUntilIdle();
871 session->CheckPingStatus(before_ping_time);
873 EXPECT_EQ(0, session->pings_in_flight());
874 EXPECT_GE(session->next_ping_id(), 1U);
875 EXPECT_FALSE(session->check_ping_status_pending());
876 EXPECT_GE(session->last_activity_time(), before_ping_time);
878 data.CompleteRead();
879 base::RunLoop().RunUntilIdle();
881 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
883 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
884 EXPECT_FALSE(session);
887 TEST_P(SpdySessionTest, ServerPing) {
888 session_deps_.host_resolver->set_synchronous_mode(true);
890 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
891 MockRead reads[] = {
892 CreateMockRead(*read_ping),
893 MockRead(SYNCHRONOUS, 0, 0) // EOF
895 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
896 MockWrite writes[] = {
897 CreateMockWrite(*write_ping),
899 StaticSocketDataProvider data(
900 reads, arraysize(reads), writes, arraysize(writes));
901 session_deps_.socket_factory->AddSocketDataProvider(&data);
903 CreateNetworkSession();
905 base::WeakPtr<SpdySession> session =
906 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
908 base::WeakPtr<SpdyStream> spdy_stream1 =
909 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
910 session, test_url_, MEDIUM, BoundNetLog());
911 ASSERT_TRUE(spdy_stream1.get() != nullptr);
912 test::StreamDelegateSendImmediate delegate(spdy_stream1, nullptr);
913 spdy_stream1->SetDelegate(&delegate);
915 // Flush the read completion task.
916 base::RunLoop().RunUntilIdle();
918 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
920 EXPECT_FALSE(session);
921 EXPECT_FALSE(spdy_stream1);
924 // Cause a ping to be sent out while producing a write. The write loop
925 // should handle this properly, i.e. another DoWriteLoop task should
926 // not be posted. This is a regression test for
927 // http://crbug.com/261043 .
928 TEST_P(SpdySessionTest, PingAndWriteLoop) {
929 session_deps_.enable_ping = true;
930 session_deps_.time_func = TheNearFuture;
932 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
933 scoped_ptr<SpdyFrame> req(
934 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
935 MockWrite writes[] = {
936 CreateMockWrite(*req, 0),
937 CreateMockWrite(*write_ping, 1),
940 MockRead reads[] = {
941 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
944 session_deps_.host_resolver->set_synchronous_mode(true);
946 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
947 session_deps_.socket_factory->AddSocketDataProvider(&data);
949 CreateNetworkSession();
951 base::WeakPtr<SpdySession> session =
952 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
954 GURL url(kDefaultURL);
955 base::WeakPtr<SpdyStream> spdy_stream =
956 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
957 session, url, LOWEST, BoundNetLog());
958 test::StreamDelegateDoNothing delegate(spdy_stream);
959 spdy_stream->SetDelegate(&delegate);
961 scoped_ptr<SpdyHeaderBlock> headers(
962 spdy_util_.ConstructGetHeaderBlock(url.spec()));
963 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
965 // Shift time so that a ping will be sent out.
966 g_time_delta = base::TimeDelta::FromSeconds(11);
968 base::RunLoop().RunUntilIdle();
969 session->CloseSessionOnError(ERR_ABORTED, "Aborting");
971 data.CompleteRead();
972 base::RunLoop().RunUntilIdle();
973 EXPECT_FALSE(session);
976 TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
977 const SpdyStreamId kLastStreamId = 0x7fffffff;
978 session_deps_.host_resolver->set_synchronous_mode(true);
980 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
981 // fixed to allow for two stream ID assignments, and three concurrent
982 // streams. Four streams are started, and two are activated. Verify the
983 // session goes away, and that the created (but not activated) and
984 // stalled streams are aborted. Also verify the activated streams complete,
985 // at which point the session closes.
987 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
988 nullptr, 0, false, kLastStreamId - 2, MEDIUM, true));
989 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
990 nullptr, 0, false, kLastStreamId, MEDIUM, true));
992 MockWrite writes[] = {
993 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
996 scoped_ptr<SpdyFrame> resp1(
997 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId - 2));
998 scoped_ptr<SpdyFrame> resp2(
999 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId));
1001 scoped_ptr<SpdyFrame> body1(
1002 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
1003 scoped_ptr<SpdyFrame> body2(
1004 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
1006 MockRead reads[] = {
1007 CreateMockRead(*resp1, 2),
1008 CreateMockRead(*resp2, 3),
1009 MockRead(ASYNC, ERR_IO_PENDING, 4),
1010 CreateMockRead(*body1, 5),
1011 CreateMockRead(*body2, 6),
1012 MockRead(ASYNC, 0, 7) // EOF
1015 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1016 session_deps_.socket_factory->AddSocketDataProvider(&data);
1018 CreateNetworkSession();
1019 base::WeakPtr<SpdySession> session =
1020 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1022 // Fix stream_hi_water_mark_ to allow for two stream activations.
1023 session->stream_hi_water_mark_ = kLastStreamId - 2;
1024 // Fix max_concurrent_streams to allow for three stream creations.
1025 session->max_concurrent_streams_ = 3;
1027 // Create three streams synchronously, and begin a fourth (which is stalled).
1028 GURL url(kDefaultURL);
1029 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1030 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1031 test::StreamDelegateDoNothing delegate1(stream1);
1032 stream1->SetDelegate(&delegate1);
1034 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
1035 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1036 test::StreamDelegateDoNothing delegate2(stream2);
1037 stream2->SetDelegate(&delegate2);
1039 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1040 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1041 test::StreamDelegateDoNothing delegate3(stream3);
1042 stream3->SetDelegate(&delegate3);
1044 SpdyStreamRequest request4;
1045 TestCompletionCallback callback4;
1046 EXPECT_EQ(ERR_IO_PENDING,
1047 request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1048 session,
1049 url,
1050 MEDIUM,
1051 BoundNetLog(),
1052 callback4.callback()));
1054 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1055 EXPECT_EQ(0u, session->num_active_streams());
1056 EXPECT_EQ(3u, session->num_created_streams());
1057 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1059 // Activate stream 1. One ID remains available.
1060 stream1->SendRequestHeaders(
1061 scoped_ptr<SpdyHeaderBlock>(
1062 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1063 NO_MORE_DATA_TO_SEND);
1064 base::RunLoop().RunUntilIdle();
1066 EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1067 EXPECT_EQ(1u, session->num_active_streams());
1068 EXPECT_EQ(2u, session->num_created_streams());
1069 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1071 // Activate stream 2. ID space is exhausted.
1072 stream2->SendRequestHeaders(
1073 scoped_ptr<SpdyHeaderBlock>(
1074 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1075 NO_MORE_DATA_TO_SEND);
1076 base::RunLoop().RunUntilIdle();
1078 // Active streams remain active.
1079 EXPECT_EQ(kLastStreamId, stream2->stream_id());
1080 EXPECT_EQ(2u, session->num_active_streams());
1082 // Session is going away. Created and stalled streams were aborted.
1083 EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session->availability_state_);
1084 EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose());
1085 EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult());
1086 EXPECT_EQ(0u, session->num_created_streams());
1087 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1089 // Read responses on remaining active streams.
1090 data.CompleteRead();
1091 base::RunLoop().RunUntilIdle();
1092 EXPECT_EQ(OK, delegate1.WaitForClose());
1093 EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1094 EXPECT_EQ(OK, delegate2.WaitForClose());
1095 EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1097 // Session was destroyed.
1098 EXPECT_FALSE(session);
1101 // Verifies that an unstalled pending stream creation racing with a new stream
1102 // creation doesn't violate the maximum stream concurrency. Regression test for
1103 // crbug.com/373858.
1104 TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) {
1105 session_deps_.host_resolver->set_synchronous_mode(true);
1107 MockRead reads[] = {
1108 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1111 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1112 session_deps_.socket_factory->AddSocketDataProvider(&data);
1114 CreateNetworkSession();
1115 base::WeakPtr<SpdySession> session =
1116 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1118 // Fix max_concurrent_streams to allow for one open stream.
1119 session->max_concurrent_streams_ = 1;
1121 // Create two streams: one synchronously, and one which stalls.
1122 GURL url(kDefaultURL);
1123 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1124 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1126 SpdyStreamRequest request2;
1127 TestCompletionCallback callback2;
1128 EXPECT_EQ(ERR_IO_PENDING,
1129 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1130 session,
1131 url,
1132 MEDIUM,
1133 BoundNetLog(),
1134 callback2.callback()));
1136 EXPECT_EQ(1u, session->num_created_streams());
1137 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1139 // Cancel the first stream. A callback to unstall the second stream was
1140 // posted. Don't run it yet.
1141 stream1->Cancel();
1143 EXPECT_EQ(0u, session->num_created_streams());
1144 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1146 // Create a third stream prior to the second stream's callback.
1147 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1148 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1150 EXPECT_EQ(1u, session->num_created_streams());
1151 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1153 // Now run the message loop. The unstalled stream will re-stall itself.
1154 base::RunLoop().RunUntilIdle();
1155 EXPECT_EQ(1u, session->num_created_streams());
1156 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1158 // Cancel the third stream and run the message loop. Verify that the second
1159 // stream creation now completes.
1160 stream3->Cancel();
1161 base::RunLoop().RunUntilIdle();
1163 EXPECT_EQ(1u, session->num_created_streams());
1164 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1165 EXPECT_EQ(OK, callback2.WaitForResult());
1168 TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
1169 session_deps_.host_resolver->set_synchronous_mode(true);
1170 session_deps_.time_func = TheNearFuture;
1172 scoped_ptr<SpdyFrame> req(
1173 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
1174 scoped_ptr<SpdyFrame> rst(
1175 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
1176 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5)};
1178 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
1179 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
1180 scoped_ptr<SpdyFrame> push_a_body(
1181 spdy_util_.ConstructSpdyBodyFrame(2, false));
1182 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1183 // iterators inside. See http://crbug.com/443490
1184 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
1185 nullptr, 0, 4, 1, "http://www.example.org/0.dat"));
1186 MockRead reads[] = {
1187 CreateMockRead(*push_a, 1),
1188 CreateMockRead(*push_a_body, 2),
1189 MockRead(ASYNC, ERR_IO_PENDING, 3),
1190 CreateMockRead(*push_b, 4),
1191 MockRead(ASYNC, ERR_IO_PENDING, 6),
1192 MockRead(ASYNC, 0, 7) // EOF
1195 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1196 session_deps_.socket_factory->AddSocketDataProvider(&data);
1198 CreateNetworkSession();
1199 base::WeakPtr<SpdySession> session =
1200 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1202 // Process the principal request, and the first push stream request & body.
1203 GURL url(kDefaultURL);
1204 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1205 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1206 test::StreamDelegateDoNothing delegate(spdy_stream);
1207 spdy_stream->SetDelegate(&delegate);
1209 scoped_ptr<SpdyHeaderBlock> headers(
1210 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1211 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1213 base::RunLoop().RunUntilIdle();
1215 // Verify that there is one unclaimed push stream.
1216 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1217 SpdySession::PushedStreamMap::iterator iter =
1218 session->unclaimed_pushed_streams_.find(
1219 GURL("http://www.example.org/a.dat"));
1220 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1222 if (session->flow_control_state_ ==
1223 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1224 // Unclaimed push body consumed bytes from the session window.
1225 EXPECT_EQ(
1226 SpdySession::GetDefaultInitialWindowSize(GetParam()) - kUploadDataSize,
1227 session->session_recv_window_size_);
1228 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
1231 // Shift time to expire the push stream. Read the second SYN_STREAM,
1232 // and verify a RST_STREAM was written.
1233 g_time_delta = base::TimeDelta::FromSeconds(301);
1234 data.CompleteRead();
1235 base::RunLoop().RunUntilIdle();
1237 // Verify that the second pushed stream evicted the first pushed stream.
1238 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1239 iter = session->unclaimed_pushed_streams_.find(
1240 GURL("http://www.example.org/0.dat"));
1241 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1243 if (session->flow_control_state_ ==
1244 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1245 // Verify that the session window reclaimed the evicted stream body.
1246 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
1247 session->session_recv_window_size_);
1248 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
1251 // Read and process EOF.
1252 EXPECT_TRUE(session);
1253 data.CompleteRead();
1254 base::RunLoop().RunUntilIdle();
1255 EXPECT_FALSE(session);
1258 TEST_P(SpdySessionTest, FailedPing) {
1259 session_deps_.host_resolver->set_synchronous_mode(true);
1261 MockRead reads[] = {
1262 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1264 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
1265 scoped_ptr<SpdyFrame> goaway(
1266 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping."));
1267 MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)};
1269 StaticSocketDataProvider data(
1270 reads, arraysize(reads), writes, arraysize(writes));
1271 session_deps_.socket_factory->AddSocketDataProvider(&data);
1273 CreateNetworkSession();
1275 base::WeakPtr<SpdySession> session =
1276 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1278 base::WeakPtr<SpdyStream> spdy_stream1 =
1279 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1280 session, test_url_, MEDIUM, BoundNetLog());
1281 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1282 test::StreamDelegateSendImmediate delegate(spdy_stream1, nullptr);
1283 spdy_stream1->SetDelegate(&delegate);
1285 session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1286 session->set_hung_interval(base::TimeDelta::FromSeconds(0));
1288 // Send a PING frame.
1289 session->WritePingFrame(1, false);
1290 EXPECT_LT(0, session->pings_in_flight());
1291 EXPECT_GE(session->next_ping_id(), 1U);
1292 EXPECT_TRUE(session->check_ping_status_pending());
1294 // Assert session is not closed.
1295 EXPECT_TRUE(session->IsAvailable());
1296 EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams());
1297 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1299 // We set last time we have received any data in 1 sec less than now.
1300 // CheckPingStatus will trigger timeout because hung interval is zero.
1301 base::TimeTicks now = base::TimeTicks::Now();
1302 session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
1303 session->CheckPingStatus(now);
1304 base::RunLoop().RunUntilIdle();
1306 EXPECT_FALSE(session);
1307 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1308 EXPECT_FALSE(spdy_stream1);
1311 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1312 // settings frame increasing the max concurrent streams by 1. Make
1313 // sure nothing blows up. This is a regression test for
1314 // http://crbug.com/57331 .
1315 TEST_P(SpdySessionTest, OnSettings) {
1316 session_deps_.host_resolver->set_synchronous_mode(true);
1318 const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1320 int seq = 0;
1321 std::vector<MockWrite> writes;
1322 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1323 if (GetParam() >= kProtoHTTP2MinimumVersion) {
1324 writes.push_back(CreateMockWrite(*settings_ack, ++seq));
1327 SettingsMap new_settings;
1328 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1329 new_settings[kSpdySettingsIds] =
1330 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1331 scoped_ptr<SpdyFrame> settings_frame(
1332 spdy_util_.ConstructSpdySettings(new_settings));
1333 MockRead reads[] = {
1334 CreateMockRead(*settings_frame, 0),
1335 MockRead(ASYNC, ERR_IO_PENDING, ++seq),
1336 MockRead(ASYNC, 0, ++seq),
1339 SequencedSocketData data(reads, arraysize(reads), vector_as_array(&writes),
1340 writes.size());
1341 session_deps_.socket_factory->AddSocketDataProvider(&data);
1343 CreateNetworkSession();
1345 base::WeakPtr<SpdySession> session =
1346 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1348 // Create the maximum number of concurrent streams.
1349 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1350 base::WeakPtr<SpdyStream> spdy_stream =
1351 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1352 session, test_url_, MEDIUM, BoundNetLog());
1353 ASSERT_TRUE(spdy_stream != nullptr);
1356 StreamReleaserCallback stream_releaser;
1357 SpdyStreamRequest request;
1358 ASSERT_EQ(ERR_IO_PENDING,
1359 request.StartRequest(
1360 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1361 BoundNetLog(),
1362 stream_releaser.MakeCallback(&request)));
1364 base::RunLoop().RunUntilIdle();
1366 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1368 data.CompleteRead();
1369 base::RunLoop().RunUntilIdle();
1370 EXPECT_FALSE(session);
1372 EXPECT_TRUE(data.AllWriteDataConsumed());
1373 EXPECT_TRUE(data.AllReadDataConsumed());
1376 // Start with a persisted value for max concurrent streams. Receive a
1377 // settings frame increasing the max concurrent streams by 1 and which
1378 // also clears the persisted data. Verify that persisted data is
1379 // correct.
1380 TEST_P(SpdySessionTest, ClearSettings) {
1381 if (spdy_util_.spdy_version() >= HTTP2) {
1382 // HTTP/2 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1383 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in HTTP/2.
1384 return;
1386 session_deps_.host_resolver->set_synchronous_mode(true);
1388 SettingsMap new_settings;
1389 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1390 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1391 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1392 scoped_ptr<SpdyFrame> settings_frame(
1393 spdy_util_.ConstructSpdySettings(new_settings));
1394 uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1395 test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1396 MockRead reads[] = {
1397 CreateMockRead(*settings_frame, 0),
1398 MockRead(ASYNC, ERR_IO_PENDING, 1),
1399 MockRead(ASYNC, 0, 2),
1402 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
1403 session_deps_.socket_factory->AddSocketDataProvider(&data);
1405 CreateNetworkSession();
1407 // Initialize the SpdySetting with the default.
1408 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1409 test_host_port_pair_,
1410 SETTINGS_MAX_CONCURRENT_STREAMS,
1411 SETTINGS_FLAG_PLEASE_PERSIST,
1412 kInitialMaxConcurrentStreams);
1414 EXPECT_FALSE(
1415 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1416 test_host_port_pair_).empty());
1418 base::WeakPtr<SpdySession> session =
1419 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1421 // Create the maximum number of concurrent streams.
1422 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1423 base::WeakPtr<SpdyStream> spdy_stream =
1424 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1425 session, test_url_, MEDIUM, BoundNetLog());
1426 ASSERT_TRUE(spdy_stream != nullptr);
1429 StreamReleaserCallback stream_releaser;
1431 SpdyStreamRequest request;
1432 ASSERT_EQ(ERR_IO_PENDING,
1433 request.StartRequest(
1434 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1435 BoundNetLog(),
1436 stream_releaser.MakeCallback(&request)));
1438 base::RunLoop().RunUntilIdle();
1440 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1442 // Make sure that persisted data is cleared.
1443 EXPECT_TRUE(
1444 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1445 test_host_port_pair_).empty());
1447 // Make sure session's max_concurrent_streams is correct.
1448 EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1449 session->max_concurrent_streams());
1451 data.CompleteRead();
1452 base::RunLoop().RunUntilIdle();
1453 EXPECT_FALSE(session);
1456 // Start with max concurrent streams set to 1. Request two streams.
1457 // When the first completes, have the callback close its stream, which
1458 // should trigger the second stream creation. Then cancel that one
1459 // immediately. Don't crash. This is a regression test for
1460 // http://crbug.com/63532 .
1461 TEST_P(SpdySessionTest, CancelPendingCreateStream) {
1462 session_deps_.host_resolver->set_synchronous_mode(true);
1464 MockRead reads[] = {
1465 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1468 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1469 session_deps_.socket_factory->AddSocketDataProvider(&data);
1471 CreateNetworkSession();
1473 // Initialize the SpdySetting with 1 max concurrent streams.
1474 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1475 test_host_port_pair_,
1476 SETTINGS_MAX_CONCURRENT_STREAMS,
1477 SETTINGS_FLAG_PLEASE_PERSIST,
1480 base::WeakPtr<SpdySession> session =
1481 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1483 // Leave room for only one more stream to be created.
1484 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1485 base::WeakPtr<SpdyStream> spdy_stream =
1486 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1487 session, test_url_, MEDIUM, BoundNetLog());
1488 ASSERT_TRUE(spdy_stream != nullptr);
1491 // Create 2 more streams. First will succeed. Second will be pending.
1492 base::WeakPtr<SpdyStream> spdy_stream1 =
1493 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1494 session, test_url_, MEDIUM, BoundNetLog());
1495 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1497 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1498 // a valgrind error if the callback is invoked when it's not supposed to be.
1499 scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
1501 SpdyStreamRequest request;
1502 ASSERT_EQ(ERR_IO_PENDING,
1503 request.StartRequest(
1504 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1505 BoundNetLog(),
1506 callback->callback()));
1508 // Release the first one, this will allow the second to be created.
1509 spdy_stream1->Cancel();
1510 EXPECT_FALSE(spdy_stream1);
1512 request.CancelRequest();
1513 callback.reset();
1515 // Should not crash when running the pending callback.
1516 base::RunLoop().RunUntilIdle();
1519 TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
1520 session_deps_.host_resolver->set_synchronous_mode(true);
1522 MockRead reads[] = {
1523 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1526 SettingsMap settings;
1527 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1528 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
1529 scoped_ptr<SpdyFrame> settings_frame(
1530 spdy_util_.ConstructSpdySettings(settings));
1531 std::vector<MockWrite> writes;
1532 if ((GetParam() >= kProtoHTTP2MinimumVersion) &&
1533 (GetParam() <= kProtoHTTP2MaximumVersion)) {
1534 writes.push_back(
1535 MockWrite(ASYNC,
1536 kHttp2ConnectionHeaderPrefix,
1537 kHttp2ConnectionHeaderPrefixSize));
1539 writes.push_back(CreateMockWrite(*settings_frame));
1541 SettingsMap server_settings;
1542 const uint32 initial_max_concurrent_streams = 1;
1543 server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1544 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1545 initial_max_concurrent_streams);
1546 scoped_ptr<SpdyFrame> server_settings_frame(
1547 spdy_util_.ConstructSpdySettings(server_settings));
1548 if (GetParam() <= kProtoSPDY31) {
1549 writes.push_back(CreateMockWrite(*server_settings_frame));
1552 StaticSocketDataProvider data(reads, arraysize(reads),
1553 vector_as_array(&writes), writes.size());
1554 session_deps_.socket_factory->AddSocketDataProvider(&data);
1556 CreateNetworkSession();
1558 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1559 test_host_port_pair_,
1560 SETTINGS_MAX_CONCURRENT_STREAMS,
1561 SETTINGS_FLAG_PLEASE_PERSIST,
1562 initial_max_concurrent_streams);
1564 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1565 pool_peer.SetEnableSendingInitialData(true);
1567 base::WeakPtr<SpdySession> session =
1568 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1570 base::RunLoop().RunUntilIdle();
1571 EXPECT_TRUE(data.AllWriteDataConsumed());
1574 TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
1575 CreateNetworkSession();
1577 base::WeakPtr<HttpServerProperties> test_http_server_properties =
1578 spdy_session_pool_->http_server_properties();
1579 SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
1580 test_http_server_properties->SetSpdySetting(
1581 test_host_port_pair_,
1582 SETTINGS_MAX_CONCURRENT_STREAMS,
1583 SETTINGS_FLAG_PLEASE_PERSIST,
1585 EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
1586 test_host_port_pair_).size());
1587 spdy_session_pool_->OnIPAddressChanged();
1588 EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
1589 test_host_port_pair_).size());
1592 TEST_P(SpdySessionTest, Initialize) {
1593 BoundTestNetLog log;
1594 session_deps_.net_log = log.bound().net_log();
1595 session_deps_.host_resolver->set_synchronous_mode(true);
1597 MockRead reads[] = {
1598 MockRead(ASYNC, 0, 0) // EOF
1601 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1602 session_deps_.socket_factory->AddSocketDataProvider(&data);
1604 CreateNetworkSession();
1606 base::WeakPtr<SpdySession> session =
1607 CreateInsecureSpdySession(http_session_, key_, log.bound());
1608 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1610 // Flush the read completion task.
1611 base::RunLoop().RunUntilIdle();
1613 TestNetLogEntry::List entries;
1614 log.GetEntries(&entries);
1615 EXPECT_LT(0u, entries.size());
1617 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1618 int pos = ExpectLogContainsSomewhere(
1619 entries, 0, NetLog::TYPE_HTTP2_SESSION_INITIALIZED, NetLog::PHASE_NONE);
1620 EXPECT_LT(0, pos);
1622 TestNetLogEntry entry = entries[pos];
1623 NetLog::Source socket_source;
1624 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1625 &socket_source));
1626 EXPECT_TRUE(socket_source.IsValid());
1627 EXPECT_NE(log.bound().source().id, socket_source.id);
1630 TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
1631 session_deps_.host_resolver->set_synchronous_mode(true);
1633 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
1634 MockRead reads[] = {
1635 CreateMockRead(*goaway),
1636 MockRead(SYNCHRONOUS, 0, 0) // EOF
1639 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1640 session_deps_.socket_factory->AddSocketDataProvider(&data);
1642 CreateNetworkSession();
1644 BoundTestNetLog log;
1645 base::WeakPtr<SpdySession> session =
1646 CreateInsecureSpdySession(http_session_, key_, log.bound());
1647 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1649 // Flush the read completion task.
1650 base::RunLoop().RunUntilIdle();
1652 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1653 EXPECT_FALSE(session);
1655 // Check that the NetLog was filled reasonably.
1656 TestNetLogEntry::List entries;
1657 log.GetEntries(&entries);
1658 EXPECT_LT(0u, entries.size());
1660 // Check that we logged SPDY_SESSION_CLOSE correctly.
1661 int pos = ExpectLogContainsSomewhere(
1662 entries, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE, NetLog::PHASE_NONE);
1664 if (pos < static_cast<int>(entries.size())) {
1665 TestNetLogEntry entry = entries[pos];
1666 int error_code = 0;
1667 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1668 EXPECT_EQ(OK, error_code);
1669 } else {
1670 ADD_FAILURE();
1674 TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1675 session_deps_.host_resolver->set_synchronous_mode(true);
1677 MockRead reads[] = {
1678 MockRead(SYNCHRONOUS, 0, 0) // EOF
1681 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1682 session_deps_.socket_factory->AddSocketDataProvider(&data);
1684 CreateNetworkSession();
1686 BoundTestNetLog log;
1687 base::WeakPtr<SpdySession> session =
1688 CreateInsecureSpdySession(http_session_, key_, log.bound());
1689 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1691 // Flush the read completion task.
1692 base::RunLoop().RunUntilIdle();
1694 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1695 EXPECT_FALSE(session);
1697 // Check that the NetLog was filled reasonably.
1698 TestNetLogEntry::List entries;
1699 log.GetEntries(&entries);
1700 EXPECT_LT(0u, entries.size());
1702 // Check that we logged SPDY_SESSION_CLOSE correctly.
1703 int pos = ExpectLogContainsSomewhere(
1704 entries, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE, NetLog::PHASE_NONE);
1706 if (pos < static_cast<int>(entries.size())) {
1707 TestNetLogEntry entry = entries[pos];
1708 int error_code = 0;
1709 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1710 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1711 } else {
1712 ADD_FAILURE();
1716 TEST_P(SpdySessionTest, SynCompressionHistograms) {
1717 session_deps_.enable_compression = true;
1719 scoped_ptr<SpdyFrame> req(
1720 spdy_util_.ConstructSpdyGet(nullptr, 0, true, 1, MEDIUM, true));
1721 MockWrite writes[] = {
1722 CreateMockWrite(*req, 0),
1724 MockRead reads[] = {
1725 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
1727 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1728 session_deps_.socket_factory->AddSocketDataProvider(&data);
1730 CreateNetworkSession();
1731 base::WeakPtr<SpdySession> session =
1732 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1734 GURL url(kDefaultURL);
1735 base::WeakPtr<SpdyStream> spdy_stream =
1736 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1737 session, url, MEDIUM, BoundNetLog());
1738 test::StreamDelegateDoNothing delegate(spdy_stream);
1739 spdy_stream->SetDelegate(&delegate);
1741 scoped_ptr<SpdyHeaderBlock> headers(
1742 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1743 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1744 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1746 // Write request headers & capture resulting histogram update.
1747 base::HistogramTester histogram_tester;
1749 base::RunLoop().RunUntilIdle();
1750 // Regression test of compression performance under the request fixture.
1751 switch (spdy_util_.spdy_version()) {
1752 case SPDY3:
1753 histogram_tester.ExpectBucketCount(
1754 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1755 break;
1756 case HTTP2:
1757 histogram_tester.ExpectBucketCount(
1758 "Net.SpdySynStreamCompressionPercentage", 81, 1);
1759 break;
1760 default:
1761 NOTREACHED();
1764 // Read and process EOF.
1765 EXPECT_TRUE(session);
1766 data.CompleteRead();
1767 base::RunLoop().RunUntilIdle();
1768 EXPECT_FALSE(session);
1771 // Queue up a low-priority SYN_STREAM followed by a high-priority
1772 // one. The high priority one should still send first and receive
1773 // first.
1774 TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1775 // Construct the request.
1776 scoped_ptr<SpdyFrame> req_highest(
1777 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, HIGHEST, true));
1778 scoped_ptr<SpdyFrame> req_lowest(
1779 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST, true));
1780 MockWrite writes[] = {
1781 CreateMockWrite(*req_highest, 0),
1782 CreateMockWrite(*req_lowest, 1),
1785 scoped_ptr<SpdyFrame> resp_highest(
1786 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
1787 scoped_ptr<SpdyFrame> body_highest(
1788 spdy_util_.ConstructSpdyBodyFrame(1, true));
1789 scoped_ptr<SpdyFrame> resp_lowest(
1790 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
1791 scoped_ptr<SpdyFrame> body_lowest(
1792 spdy_util_.ConstructSpdyBodyFrame(3, true));
1793 MockRead reads[] = {
1794 CreateMockRead(*resp_highest, 2),
1795 CreateMockRead(*body_highest, 3),
1796 CreateMockRead(*resp_lowest, 4),
1797 CreateMockRead(*body_lowest, 5),
1798 MockRead(ASYNC, 0, 6) // EOF
1801 session_deps_.host_resolver->set_synchronous_mode(true);
1803 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1804 session_deps_.socket_factory->AddSocketDataProvider(&data);
1806 CreateNetworkSession();
1808 base::WeakPtr<SpdySession> session =
1809 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1811 GURL url(kDefaultURL);
1813 base::WeakPtr<SpdyStream> spdy_stream_lowest =
1814 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1815 session, url, LOWEST, BoundNetLog());
1816 ASSERT_TRUE(spdy_stream_lowest);
1817 EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1818 test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1819 spdy_stream_lowest->SetDelegate(&delegate_lowest);
1821 base::WeakPtr<SpdyStream> spdy_stream_highest =
1822 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1823 session, url, HIGHEST, BoundNetLog());
1824 ASSERT_TRUE(spdy_stream_highest);
1825 EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1826 test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1827 spdy_stream_highest->SetDelegate(&delegate_highest);
1829 // Queue the lower priority one first.
1831 scoped_ptr<SpdyHeaderBlock> headers_lowest(
1832 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1833 spdy_stream_lowest->SendRequestHeaders(
1834 headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1835 EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1837 scoped_ptr<SpdyHeaderBlock> headers_highest(
1838 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1839 spdy_stream_highest->SendRequestHeaders(
1840 headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1841 EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1843 base::RunLoop().RunUntilIdle();
1845 EXPECT_FALSE(spdy_stream_lowest);
1846 EXPECT_FALSE(spdy_stream_highest);
1847 EXPECT_EQ(3u, delegate_lowest.stream_id());
1848 EXPECT_EQ(1u, delegate_highest.stream_id());
1851 TEST_P(SpdySessionTest, CancelStream) {
1852 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1853 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1854 scoped_ptr<SpdyFrame> req2(
1855 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
1856 MockWrite writes[] = {
1857 CreateMockWrite(*req2, 0),
1860 scoped_ptr<SpdyFrame> resp2(
1861 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
1862 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1863 MockRead reads[] = {
1864 CreateMockRead(*resp2, 1),
1865 MockRead(ASYNC, ERR_IO_PENDING, 2),
1866 CreateMockRead(*body2, 3),
1867 MockRead(ASYNC, 0, 4) // EOF
1870 session_deps_.host_resolver->set_synchronous_mode(true);
1872 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1873 session_deps_.socket_factory->AddSocketDataProvider(&data);
1875 CreateNetworkSession();
1877 base::WeakPtr<SpdySession> session =
1878 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1880 GURL url1(kDefaultURL);
1881 base::WeakPtr<SpdyStream> spdy_stream1 =
1882 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1883 session, url1, HIGHEST, BoundNetLog());
1884 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1885 EXPECT_EQ(0u, spdy_stream1->stream_id());
1886 test::StreamDelegateDoNothing delegate1(spdy_stream1);
1887 spdy_stream1->SetDelegate(&delegate1);
1889 GURL url2(kDefaultURL);
1890 base::WeakPtr<SpdyStream> spdy_stream2 =
1891 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1892 session, url2, LOWEST, BoundNetLog());
1893 ASSERT_TRUE(spdy_stream2.get() != nullptr);
1894 EXPECT_EQ(0u, spdy_stream2->stream_id());
1895 test::StreamDelegateDoNothing delegate2(spdy_stream2);
1896 spdy_stream2->SetDelegate(&delegate2);
1898 scoped_ptr<SpdyHeaderBlock> headers(
1899 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1900 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1901 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1903 scoped_ptr<SpdyHeaderBlock> headers2(
1904 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1905 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1906 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1908 EXPECT_EQ(0u, spdy_stream1->stream_id());
1910 spdy_stream1->Cancel();
1911 EXPECT_FALSE(spdy_stream1);
1913 EXPECT_EQ(0u, delegate1.stream_id());
1915 base::RunLoop().RunUntilIdle();
1917 EXPECT_EQ(0u, delegate1.stream_id());
1918 EXPECT_EQ(1u, delegate2.stream_id());
1920 spdy_stream2->Cancel();
1921 EXPECT_FALSE(spdy_stream2);
1924 // Create two streams that are set to re-close themselves on close,
1925 // and then close the session. Nothing should blow up. Also a
1926 // regression test for http://crbug.com/139518 .
1927 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1928 session_deps_.host_resolver->set_synchronous_mode(true);
1931 // No actual data will be sent.
1932 MockWrite writes[] = {
1933 MockWrite(ASYNC, 0, 1) // EOF
1936 MockRead reads[] = {
1937 MockRead(ASYNC, 0, 0) // EOF
1939 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1940 session_deps_.socket_factory->AddSocketDataProvider(&data);
1942 CreateNetworkSession();
1944 base::WeakPtr<SpdySession> session =
1945 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1947 GURL url1(kDefaultURL);
1948 base::WeakPtr<SpdyStream> spdy_stream1 =
1949 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1950 session, url1, HIGHEST, BoundNetLog());
1951 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1952 EXPECT_EQ(0u, spdy_stream1->stream_id());
1954 GURL url2(kDefaultURL);
1955 base::WeakPtr<SpdyStream> spdy_stream2 =
1956 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1957 session, url2, LOWEST, BoundNetLog());
1958 ASSERT_TRUE(spdy_stream2.get() != nullptr);
1959 EXPECT_EQ(0u, spdy_stream2->stream_id());
1961 test::ClosingDelegate delegate1(spdy_stream1);
1962 spdy_stream1->SetDelegate(&delegate1);
1964 test::ClosingDelegate delegate2(spdy_stream2);
1965 spdy_stream2->SetDelegate(&delegate2);
1967 scoped_ptr<SpdyHeaderBlock> headers(
1968 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1969 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1970 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1972 scoped_ptr<SpdyHeaderBlock> headers2(
1973 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1974 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1975 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1977 // Ensure that the streams have not yet been activated and assigned an id.
1978 EXPECT_EQ(0u, spdy_stream1->stream_id());
1979 EXPECT_EQ(0u, spdy_stream2->stream_id());
1981 // Ensure we don't crash while closing the session.
1982 session->CloseSessionOnError(ERR_ABORTED, std::string());
1984 EXPECT_FALSE(spdy_stream1);
1985 EXPECT_FALSE(spdy_stream2);
1987 EXPECT_TRUE(delegate1.StreamIsClosed());
1988 EXPECT_TRUE(delegate2.StreamIsClosed());
1990 base::RunLoop().RunUntilIdle();
1991 EXPECT_FALSE(session);
1994 // Create two streams that are set to close each other on close, and
1995 // then close the session. Nothing should blow up.
1996 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
1997 session_deps_.host_resolver->set_synchronous_mode(true);
1999 SequencedSocketData data(nullptr, 0, nullptr, 0);
2000 session_deps_.socket_factory->AddSocketDataProvider(&data);
2002 CreateNetworkSession();
2004 base::WeakPtr<SpdySession> session =
2005 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2007 GURL url1(kDefaultURL);
2008 base::WeakPtr<SpdyStream> spdy_stream1 =
2009 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2010 session, url1, HIGHEST, BoundNetLog());
2011 ASSERT_TRUE(spdy_stream1);
2012 EXPECT_EQ(0u, spdy_stream1->stream_id());
2014 GURL url2(kDefaultURL);
2015 base::WeakPtr<SpdyStream> spdy_stream2 =
2016 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2017 session, url2, LOWEST, BoundNetLog());
2018 ASSERT_TRUE(spdy_stream2);
2019 EXPECT_EQ(0u, spdy_stream2->stream_id());
2021 // Make |spdy_stream1| close |spdy_stream2|.
2022 test::ClosingDelegate delegate1(spdy_stream2);
2023 spdy_stream1->SetDelegate(&delegate1);
2025 // Make |spdy_stream2| close |spdy_stream1|.
2026 test::ClosingDelegate delegate2(spdy_stream1);
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_FALSE(spdy_stream1);
2047 EXPECT_FALSE(spdy_stream2);
2049 EXPECT_TRUE(delegate1.StreamIsClosed());
2050 EXPECT_TRUE(delegate2.StreamIsClosed());
2052 base::RunLoop().RunUntilIdle();
2053 EXPECT_FALSE(session);
2056 // Create two streams that are set to re-close themselves on close,
2057 // activate them, and then close the session. Nothing should blow up.
2058 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
2059 session_deps_.host_resolver->set_synchronous_mode(true);
2061 scoped_ptr<SpdyFrame> req1(
2062 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2063 scoped_ptr<SpdyFrame> req2(
2064 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
2065 MockWrite writes[] = {
2066 CreateMockWrite(*req1, 0),
2067 CreateMockWrite(*req2, 1),
2070 MockRead reads[] = {
2071 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
2074 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2075 session_deps_.socket_factory->AddSocketDataProvider(&data);
2077 CreateNetworkSession();
2079 base::WeakPtr<SpdySession> session =
2080 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2082 GURL url1(kDefaultURL);
2083 base::WeakPtr<SpdyStream> spdy_stream1 =
2084 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2085 session, url1, MEDIUM, BoundNetLog());
2086 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2087 EXPECT_EQ(0u, spdy_stream1->stream_id());
2089 GURL url2(kDefaultURL);
2090 base::WeakPtr<SpdyStream> spdy_stream2 =
2091 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2092 session, url2, MEDIUM, BoundNetLog());
2093 ASSERT_TRUE(spdy_stream2.get() != nullptr);
2094 EXPECT_EQ(0u, spdy_stream2->stream_id());
2096 test::ClosingDelegate delegate1(spdy_stream1);
2097 spdy_stream1->SetDelegate(&delegate1);
2099 test::ClosingDelegate delegate2(spdy_stream2);
2100 spdy_stream2->SetDelegate(&delegate2);
2102 scoped_ptr<SpdyHeaderBlock> headers(
2103 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2104 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2105 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2107 scoped_ptr<SpdyHeaderBlock> headers2(
2108 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2109 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2110 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2112 // Ensure that the streams have not yet been activated and assigned an id.
2113 EXPECT_EQ(0u, spdy_stream1->stream_id());
2114 EXPECT_EQ(0u, spdy_stream2->stream_id());
2116 base::RunLoop().RunUntilIdle();
2118 EXPECT_EQ(1u, spdy_stream1->stream_id());
2119 EXPECT_EQ(3u, spdy_stream2->stream_id());
2121 // Ensure we don't crash while closing the session.
2122 session->CloseSessionOnError(ERR_ABORTED, std::string());
2124 EXPECT_FALSE(spdy_stream1);
2125 EXPECT_FALSE(spdy_stream2);
2127 EXPECT_TRUE(delegate1.StreamIsClosed());
2128 EXPECT_TRUE(delegate2.StreamIsClosed());
2130 EXPECT_TRUE(session);
2131 data.CompleteRead();
2132 base::RunLoop().RunUntilIdle();
2133 EXPECT_FALSE(session);
2136 // Create two streams that are set to close each other on close,
2137 // activate them, and then close the session. Nothing should blow up.
2138 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2139 session_deps_.host_resolver->set_synchronous_mode(true);
2141 scoped_ptr<SpdyFrame> req1(
2142 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2143 scoped_ptr<SpdyFrame> req2(
2144 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
2145 MockWrite writes[] = {
2146 CreateMockWrite(*req1, 0),
2147 CreateMockWrite(*req2, 1),
2150 MockRead reads[] = {
2151 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
2154 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2155 session_deps_.socket_factory->AddSocketDataProvider(&data);
2157 CreateNetworkSession();
2159 base::WeakPtr<SpdySession> session =
2160 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2162 GURL url1(kDefaultURL);
2163 base::WeakPtr<SpdyStream> spdy_stream1 =
2164 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2165 session, url1, MEDIUM, BoundNetLog());
2166 ASSERT_TRUE(spdy_stream1);
2167 EXPECT_EQ(0u, spdy_stream1->stream_id());
2169 GURL url2(kDefaultURL);
2170 base::WeakPtr<SpdyStream> spdy_stream2 =
2171 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2172 session, url2, MEDIUM, BoundNetLog());
2173 ASSERT_TRUE(spdy_stream2);
2174 EXPECT_EQ(0u, spdy_stream2->stream_id());
2176 // Make |spdy_stream1| close |spdy_stream2|.
2177 test::ClosingDelegate delegate1(spdy_stream2);
2178 spdy_stream1->SetDelegate(&delegate1);
2180 // Make |spdy_stream2| close |spdy_stream1|.
2181 test::ClosingDelegate delegate2(spdy_stream1);
2182 spdy_stream2->SetDelegate(&delegate2);
2184 scoped_ptr<SpdyHeaderBlock> headers(
2185 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2186 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2187 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2189 scoped_ptr<SpdyHeaderBlock> headers2(
2190 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2191 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2192 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2194 // Ensure that the streams have not yet been activated and assigned an id.
2195 EXPECT_EQ(0u, spdy_stream1->stream_id());
2196 EXPECT_EQ(0u, spdy_stream2->stream_id());
2198 base::RunLoop().RunUntilIdle();
2200 EXPECT_EQ(1u, spdy_stream1->stream_id());
2201 EXPECT_EQ(3u, spdy_stream2->stream_id());
2203 // Ensure we don't crash while closing the session.
2204 session->CloseSessionOnError(ERR_ABORTED, std::string());
2206 EXPECT_FALSE(spdy_stream1);
2207 EXPECT_FALSE(spdy_stream2);
2209 EXPECT_TRUE(delegate1.StreamIsClosed());
2210 EXPECT_TRUE(delegate2.StreamIsClosed());
2212 EXPECT_TRUE(session);
2213 data.CompleteRead();
2214 base::RunLoop().RunUntilIdle();
2215 EXPECT_FALSE(session);
2218 // Delegate that closes a given session when the stream is closed.
2219 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2220 public:
2221 SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2222 const base::WeakPtr<SpdySession>& session_to_close)
2223 : StreamDelegateDoNothing(stream),
2224 session_to_close_(session_to_close) {}
2226 ~SessionClosingDelegate() override {}
2228 void OnClose(int status) override {
2229 session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2232 private:
2233 base::WeakPtr<SpdySession> session_to_close_;
2236 // Close an activated stream that closes its session. Nothing should
2237 // blow up. This is a regression test for https://crbug.com/263691.
2238 TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2239 session_deps_.host_resolver->set_synchronous_mode(true);
2241 scoped_ptr<SpdyFrame> req(
2242 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2243 scoped_ptr<SpdyFrame> rst(
2244 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2245 scoped_ptr<SpdyFrame> goaway(
2246 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2247 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2248 // despite being queued second.
2249 MockWrite writes[] = {
2250 CreateMockWrite(*req, 0),
2251 CreateMockWrite(*goaway, 1),
2252 CreateMockWrite(*rst, 3),
2255 MockRead reads[] = {
2256 MockRead(ASYNC, 0, 2) // EOF
2258 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2259 session_deps_.socket_factory->AddSocketDataProvider(&data);
2261 CreateNetworkSession();
2263 base::WeakPtr<SpdySession> session =
2264 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2266 GURL url(kDefaultURL);
2267 base::WeakPtr<SpdyStream> spdy_stream =
2268 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2269 session, url, MEDIUM, BoundNetLog());
2270 ASSERT_TRUE(spdy_stream.get() != nullptr);
2271 EXPECT_EQ(0u, spdy_stream->stream_id());
2273 SessionClosingDelegate delegate(spdy_stream, session);
2274 spdy_stream->SetDelegate(&delegate);
2276 scoped_ptr<SpdyHeaderBlock> headers(
2277 spdy_util_.ConstructGetHeaderBlock(url.spec()));
2278 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2279 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2281 EXPECT_EQ(0u, spdy_stream->stream_id());
2283 base::RunLoop().RunUntilIdle();
2285 EXPECT_EQ(1u, spdy_stream->stream_id());
2287 // Ensure we don't crash while closing the stream (which closes the
2288 // session).
2289 spdy_stream->Cancel();
2291 EXPECT_FALSE(spdy_stream);
2292 EXPECT_TRUE(delegate.StreamIsClosed());
2294 // Write the RST_STREAM & GOAWAY.
2295 base::RunLoop().RunUntilIdle();
2296 EXPECT_TRUE(data.AllWriteDataConsumed());
2297 EXPECT_TRUE(data.AllReadDataConsumed());
2300 TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2301 session_deps_.host_resolver->set_synchronous_mode(true);
2303 SequencedSocketData data(nullptr, 0, nullptr, 0);
2304 session_deps_.socket_factory->AddSocketDataProvider(&data);
2306 // Load a cert that is valid for:
2307 // www.example.org
2308 // mail.example.org
2309 // www.example.com
2310 base::FilePath certs_dir = GetTestCertsDirectory();
2311 scoped_refptr<X509Certificate> test_cert(
2312 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2313 ASSERT_NE(static_cast<X509Certificate*>(nullptr), test_cert.get());
2315 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2316 ssl.cert = test_cert;
2317 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2319 CreateNetworkSession();
2321 base::WeakPtr<SpdySession> session =
2322 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2324 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2325 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2326 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
2327 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2330 TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2331 session_deps_.host_resolver->set_synchronous_mode(true);
2333 SequencedSocketData data(nullptr, 0, nullptr, 0);
2334 session_deps_.socket_factory->AddSocketDataProvider(&data);
2336 // Load a cert that is valid for:
2337 // www.example.org
2338 // mail.example.org
2339 // www.example.com
2340 base::FilePath certs_dir = GetTestCertsDirectory();
2341 scoped_refptr<X509Certificate> test_cert(
2342 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2343 ASSERT_NE(static_cast<X509Certificate*>(nullptr), test_cert.get());
2345 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2346 ssl.channel_id_sent = true;
2347 ssl.cert = test_cert;
2348 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2350 CreateNetworkSession();
2352 base::WeakPtr<SpdySession> session =
2353 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2355 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2356 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2357 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2358 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2361 TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2362 // TODO(rtenneti): Define a helper class/methods and move the common code in
2363 // this file.
2364 SettingsMap new_settings;
2365 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2366 const uint32 max_concurrent_streams = 1;
2367 new_settings[kSpdySettingsIds1] =
2368 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2370 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
2371 scoped_ptr<SpdyFrame> req1(
2372 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
2373 scoped_ptr<SpdyFrame> req2(
2374 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST, true));
2375 scoped_ptr<SpdyFrame> req3(
2376 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 5, LOWEST, true));
2377 MockWrite writes[] = {
2378 CreateMockWrite(*settings_ack, 1),
2379 CreateMockWrite(*req1, 2),
2380 CreateMockWrite(*req2, 5),
2381 CreateMockWrite(*req3, 8),
2384 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2385 // streams to 1.
2386 scoped_ptr<SpdyFrame> settings_frame(
2387 spdy_util_.ConstructSpdySettings(new_settings));
2389 scoped_ptr<SpdyFrame> resp1(
2390 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2391 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2393 scoped_ptr<SpdyFrame> resp2(
2394 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
2395 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2397 scoped_ptr<SpdyFrame> resp3(
2398 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 5));
2399 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2401 MockRead reads[] = {
2402 CreateMockRead(*settings_frame, 0),
2403 CreateMockRead(*resp1, 3),
2404 CreateMockRead(*body1, 4),
2405 CreateMockRead(*resp2, 6),
2406 CreateMockRead(*body2, 7),
2407 CreateMockRead(*resp3, 9),
2408 CreateMockRead(*body3, 10),
2409 MockRead(ASYNC, ERR_IO_PENDING, 11),
2410 MockRead(ASYNC, 0, 12) // EOF
2413 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2414 session_deps_.socket_factory->AddSocketDataProvider(&data);
2416 CreateNetworkSession();
2418 base::WeakPtr<SpdySession> session =
2419 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2421 // Read the settings frame.
2422 base::RunLoop().RunUntilIdle();
2424 GURL url1(kDefaultURL);
2425 base::WeakPtr<SpdyStream> spdy_stream1 =
2426 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2427 session, url1, LOWEST, BoundNetLog());
2428 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2429 EXPECT_EQ(0u, spdy_stream1->stream_id());
2430 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2431 spdy_stream1->SetDelegate(&delegate1);
2433 TestCompletionCallback callback2;
2434 GURL url2(kDefaultURL);
2435 SpdyStreamRequest request2;
2436 ASSERT_EQ(ERR_IO_PENDING,
2437 request2.StartRequest(
2438 SPDY_REQUEST_RESPONSE_STREAM,
2439 session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2441 TestCompletionCallback callback3;
2442 GURL url3(kDefaultURL);
2443 SpdyStreamRequest request3;
2444 ASSERT_EQ(ERR_IO_PENDING,
2445 request3.StartRequest(
2446 SPDY_REQUEST_RESPONSE_STREAM,
2447 session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2449 EXPECT_EQ(0u, session->num_active_streams());
2450 EXPECT_EQ(1u, session->num_created_streams());
2451 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2453 scoped_ptr<SpdyHeaderBlock> headers(
2454 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2455 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2456 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2458 // Run until 1st stream is activated and then closed.
2459 EXPECT_EQ(0u, delegate1.stream_id());
2460 base::RunLoop().RunUntilIdle();
2461 EXPECT_FALSE(spdy_stream1);
2462 EXPECT_EQ(1u, delegate1.stream_id());
2464 EXPECT_EQ(0u, session->num_active_streams());
2465 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2467 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2468 // create the 2nd stream.
2469 base::RunLoop().RunUntilIdle();
2471 EXPECT_EQ(0u, session->num_active_streams());
2472 EXPECT_EQ(1u, session->num_created_streams());
2473 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2475 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2476 test::StreamDelegateDoNothing delegate2(stream2);
2477 stream2->SetDelegate(&delegate2);
2478 scoped_ptr<SpdyHeaderBlock> headers2(
2479 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2480 stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2481 EXPECT_TRUE(stream2->HasUrlFromHeaders());
2483 // Run until 2nd stream is activated and then closed.
2484 EXPECT_EQ(0u, delegate2.stream_id());
2485 base::RunLoop().RunUntilIdle();
2486 EXPECT_FALSE(stream2);
2487 EXPECT_EQ(3u, delegate2.stream_id());
2489 EXPECT_EQ(0u, session->num_active_streams());
2490 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2492 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2493 // create the 3rd stream.
2494 base::RunLoop().RunUntilIdle();
2496 EXPECT_EQ(0u, session->num_active_streams());
2497 EXPECT_EQ(1u, session->num_created_streams());
2498 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2500 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2501 test::StreamDelegateDoNothing delegate3(stream3);
2502 stream3->SetDelegate(&delegate3);
2503 scoped_ptr<SpdyHeaderBlock> headers3(
2504 spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2505 stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2506 EXPECT_TRUE(stream3->HasUrlFromHeaders());
2508 // Run until 2nd stream is activated and then closed.
2509 EXPECT_EQ(0u, delegate3.stream_id());
2510 base::RunLoop().RunUntilIdle();
2511 EXPECT_FALSE(stream3);
2512 EXPECT_EQ(5u, delegate3.stream_id());
2514 EXPECT_EQ(0u, session->num_active_streams());
2515 EXPECT_EQ(0u, session->num_created_streams());
2516 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2518 data.CompleteRead();
2519 base::RunLoop().RunUntilIdle();
2522 TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2523 session_deps_.host_resolver->set_synchronous_mode(true);
2525 MockRead reads[] = {
2526 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2529 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
2530 session_deps_.socket_factory->AddSocketDataProvider(&data);
2532 CreateNetworkSession();
2534 base::WeakPtr<SpdySession> session =
2535 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2537 // Leave room for only one more stream to be created.
2538 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2539 base::WeakPtr<SpdyStream> spdy_stream =
2540 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2541 session, test_url_, MEDIUM, BoundNetLog());
2542 ASSERT_TRUE(spdy_stream != nullptr);
2545 GURL url1(kDefaultURL);
2546 base::WeakPtr<SpdyStream> spdy_stream1 =
2547 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2548 session, url1, LOWEST, BoundNetLog());
2549 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2550 EXPECT_EQ(0u, spdy_stream1->stream_id());
2552 TestCompletionCallback callback2;
2553 GURL url2(kDefaultURL);
2554 SpdyStreamRequest request2;
2555 ASSERT_EQ(ERR_IO_PENDING,
2556 request2.StartRequest(
2557 SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2558 callback2.callback()));
2560 TestCompletionCallback callback3;
2561 GURL url3(kDefaultURL);
2562 SpdyStreamRequest request3;
2563 ASSERT_EQ(ERR_IO_PENDING,
2564 request3.StartRequest(
2565 SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2566 callback3.callback()));
2568 EXPECT_EQ(0u, session->num_active_streams());
2569 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2570 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2572 // Cancel the first stream; this will allow the second stream to be created.
2573 EXPECT_TRUE(spdy_stream1);
2574 spdy_stream1->Cancel();
2575 EXPECT_FALSE(spdy_stream1);
2577 EXPECT_EQ(OK, callback2.WaitForResult());
2578 EXPECT_EQ(0u, session->num_active_streams());
2579 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2580 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2582 // Cancel the second stream; this will allow the third stream to be created.
2583 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2584 spdy_stream2->Cancel();
2585 EXPECT_FALSE(spdy_stream2);
2587 EXPECT_EQ(OK, callback3.WaitForResult());
2588 EXPECT_EQ(0u, session->num_active_streams());
2589 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2590 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2592 // Cancel the third stream.
2593 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2594 spdy_stream3->Cancel();
2595 EXPECT_FALSE(spdy_stream3);
2596 EXPECT_EQ(0u, session->num_active_streams());
2597 EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
2598 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2601 // Test that SpdySession::DoReadLoop reads data from the socket
2602 // without yielding. This test makes 32k - 1 bytes of data available
2603 // on the socket for reading. It then verifies that it has read all
2604 // the available data without yielding.
2605 TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2606 session_deps_.host_resolver->set_synchronous_mode(true);
2608 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2610 scoped_ptr<SpdyFrame> req1(
2611 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2612 MockWrite writes[] = {
2613 CreateMockWrite(*req1, 0),
2616 // Build buffer of size kYieldAfterBytesRead / 4
2617 // (-spdy_data_frame_size).
2618 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
2619 const int kPayloadSize =
2620 kYieldAfterBytesRead / 4 - framer.GetControlFrameHeaderSize();
2621 TestDataStream test_stream;
2622 scoped_refptr<IOBuffer> payload(new IOBuffer(kPayloadSize));
2623 char* payload_data = payload->data();
2624 test_stream.GetBytes(payload_data, kPayloadSize);
2626 scoped_ptr<SpdyFrame> partial_data_frame(
2627 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2628 scoped_ptr<SpdyFrame> finish_data_frame(
2629 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2631 scoped_ptr<SpdyFrame> resp1(
2632 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2634 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2635 // bytes.
2636 MockRead reads[] = {
2637 CreateMockRead(*resp1, 1),
2638 MockRead(ASYNC, ERR_IO_PENDING, 2),
2639 CreateMockRead(*partial_data_frame, 3),
2640 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2641 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2642 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2643 MockRead(ASYNC, 0, 7) // EOF
2646 // Create SpdySession and SpdyStream and send the request.
2647 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2648 session_deps_.socket_factory->AddSocketDataProvider(&data);
2650 CreateNetworkSession();
2652 base::WeakPtr<SpdySession> session =
2653 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2655 GURL url1(kDefaultURL);
2656 base::WeakPtr<SpdyStream> spdy_stream1 =
2657 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2658 session, url1, MEDIUM, BoundNetLog());
2659 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2660 EXPECT_EQ(0u, spdy_stream1->stream_id());
2661 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2662 spdy_stream1->SetDelegate(&delegate1);
2664 scoped_ptr<SpdyHeaderBlock> headers1(
2665 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2666 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2667 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2669 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2670 // post a task.
2671 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2673 // Run until 1st read.
2674 EXPECT_EQ(0u, delegate1.stream_id());
2675 base::RunLoop().RunUntilIdle();
2676 EXPECT_EQ(1u, delegate1.stream_id());
2677 EXPECT_EQ(0u, observer.executed_count());
2679 // Read all the data and verify SpdySession::DoReadLoop has not
2680 // posted a task.
2681 data.CompleteRead();
2682 base::RunLoop().RunUntilIdle();
2683 EXPECT_FALSE(spdy_stream1);
2685 // Verify task observer's executed_count is zero, which indicates DoRead read
2686 // all the available data.
2687 EXPECT_EQ(0u, observer.executed_count());
2688 EXPECT_TRUE(data.AllWriteDataConsumed());
2689 EXPECT_TRUE(data.AllReadDataConsumed());
2692 // Test that SpdySession::DoReadLoop yields if more than
2693 // |kYieldAfterDurationMilliseconds| has passed. This test uses a mock time
2694 // function that makes the response frame look very slow to read.
2695 TEST_P(SpdySessionTest, TestYieldingSlowReads) {
2696 session_deps_.host_resolver->set_synchronous_mode(true);
2697 session_deps_.time_func = SlowReads;
2699 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2701 scoped_ptr<SpdyFrame> req1(
2702 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2703 MockWrite writes[] = {
2704 CreateMockWrite(*req1, 0),
2707 scoped_ptr<SpdyFrame> resp1(
2708 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2710 MockRead reads[] = {
2711 CreateMockRead(*resp1, 1), MockRead(ASYNC, 0, 2) // EOF
2714 // Create SpdySession and SpdyStream and send the request.
2715 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2716 session_deps_.socket_factory->AddSocketDataProvider(&data);
2718 CreateNetworkSession();
2720 base::WeakPtr<SpdySession> session =
2721 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2723 GURL url1(kDefaultURL);
2724 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2725 SPDY_REQUEST_RESPONSE_STREAM, session, url1, MEDIUM, BoundNetLog());
2726 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2727 EXPECT_EQ(0u, spdy_stream1->stream_id());
2728 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2729 spdy_stream1->SetDelegate(&delegate1);
2731 scoped_ptr<SpdyHeaderBlock> headers1(
2732 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2733 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2734 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2736 // Set up the TaskObserver to verify that SpdySession::DoReadLoop posts a
2737 // task.
2738 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2740 EXPECT_EQ(0u, delegate1.stream_id());
2741 EXPECT_EQ(0u, observer.executed_count());
2743 // Read all the data and verify that SpdySession::DoReadLoop has posted a
2744 // task.
2745 base::RunLoop().RunUntilIdle();
2746 EXPECT_EQ(1u, delegate1.stream_id());
2747 EXPECT_FALSE(spdy_stream1);
2749 // Verify task that the observer's executed_count is 1, which indicates DoRead
2750 // has posted only one task and thus yielded though there is data available
2751 // for it to read.
2752 EXPECT_EQ(1u, observer.executed_count());
2753 EXPECT_TRUE(data.AllWriteDataConsumed());
2754 EXPECT_TRUE(data.AllReadDataConsumed());
2757 // Test that SpdySession::DoReadLoop yields while reading the
2758 // data. This test makes 32k + 1 bytes of data available on the socket
2759 // for reading. It then verifies that DoRead has yielded even though
2760 // there is data available for it to read (i.e, socket()->Read didn't
2761 // return ERR_IO_PENDING during socket reads).
2762 TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2763 session_deps_.host_resolver->set_synchronous_mode(true);
2765 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2767 scoped_ptr<SpdyFrame> req1(
2768 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2769 MockWrite writes[] = {
2770 CreateMockWrite(*req1, 0),
2773 // Build buffer of size kYieldAfterBytesRead / 4
2774 // (-spdy_data_frame_size).
2775 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
2776 const int kPayloadSize =
2777 kYieldAfterBytesRead / 4 - framer.GetControlFrameHeaderSize();
2778 TestDataStream test_stream;
2779 scoped_refptr<IOBuffer> payload(new IOBuffer(kPayloadSize));
2780 char* payload_data = payload->data();
2781 test_stream.GetBytes(payload_data, kPayloadSize);
2783 scoped_ptr<SpdyFrame> partial_data_frame(
2784 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2785 scoped_ptr<SpdyFrame> finish_data_frame(
2786 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2788 scoped_ptr<SpdyFrame> resp1(
2789 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2791 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2792 MockRead reads[] = {
2793 CreateMockRead(*resp1, 1),
2794 MockRead(ASYNC, ERR_IO_PENDING, 2),
2795 CreateMockRead(*partial_data_frame, 3),
2796 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2797 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2798 CreateMockRead(*partial_data_frame, 6, SYNCHRONOUS),
2799 CreateMockRead(*finish_data_frame, 7, SYNCHRONOUS),
2800 MockRead(ASYNC, 0, 8) // EOF
2803 // Create SpdySession and SpdyStream and send the request.
2804 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2805 session_deps_.socket_factory->AddSocketDataProvider(&data);
2807 CreateNetworkSession();
2809 base::WeakPtr<SpdySession> session =
2810 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2812 GURL url1(kDefaultURL);
2813 base::WeakPtr<SpdyStream> spdy_stream1 =
2814 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2815 session, url1, MEDIUM, BoundNetLog());
2816 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2817 EXPECT_EQ(0u, spdy_stream1->stream_id());
2818 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2819 spdy_stream1->SetDelegate(&delegate1);
2821 scoped_ptr<SpdyHeaderBlock> headers1(
2822 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2823 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2824 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2826 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a task.
2827 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2829 // Run until 1st read.
2830 EXPECT_EQ(0u, delegate1.stream_id());
2831 base::RunLoop().RunUntilIdle();
2832 EXPECT_EQ(1u, delegate1.stream_id());
2833 EXPECT_EQ(0u, observer.executed_count());
2835 // Read all the data and verify SpdySession::DoReadLoop has posted a task.
2836 data.CompleteRead();
2837 base::RunLoop().RunUntilIdle();
2838 EXPECT_FALSE(spdy_stream1);
2840 // Verify task observer's executed_count is 1, which indicates DoRead has
2841 // posted only one task and thus yielded though there is data available for it
2842 // to read.
2843 EXPECT_EQ(1u, observer.executed_count());
2844 EXPECT_TRUE(data.AllWriteDataConsumed());
2845 EXPECT_TRUE(data.AllReadDataConsumed());
2848 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2849 // + async, by doing the following MockReads.
2851 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2852 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2854 // The above reads 26K synchronously. Since that is less that 32K, we
2855 // will attempt to read again. However, that DoRead() will return
2856 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2857 // yield. When we come back, DoRead() will read the results from the
2858 // async read, and rest of the data synchronously.
2859 TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2860 session_deps_.host_resolver->set_synchronous_mode(true);
2862 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2864 scoped_ptr<SpdyFrame> req1(
2865 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2866 MockWrite writes[] = {
2867 CreateMockWrite(*req1, 0),
2870 // Build buffer of size kYieldAfterBytesRead / 4
2871 // (-spdy_data_frame_size).
2872 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
2873 TestDataStream test_stream;
2874 const int kEightKPayloadSize =
2875 kYieldAfterBytesRead / 4 - framer.GetControlFrameHeaderSize();
2876 scoped_refptr<IOBuffer> eightk_payload(new IOBuffer(kEightKPayloadSize));
2877 char* eightk_payload_data = eightk_payload->data();
2878 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2880 // Build buffer of 2k size.
2881 TestDataStream test_stream2;
2882 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2883 scoped_refptr<IOBuffer> twok_payload(new IOBuffer(kTwoKPayloadSize));
2884 char* twok_payload_data = twok_payload->data();
2885 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2887 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2888 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2889 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2890 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2891 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2892 1, "h", 1, DATA_FLAG_FIN));
2894 scoped_ptr<SpdyFrame> resp1(
2895 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2897 MockRead reads[] = {
2898 CreateMockRead(*resp1, 1),
2899 MockRead(ASYNC, ERR_IO_PENDING, 2),
2900 CreateMockRead(*eightk_data_frame, 3),
2901 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2902 CreateMockRead(*eightk_data_frame, 5, SYNCHRONOUS),
2903 CreateMockRead(*twok_data_frame, 6, SYNCHRONOUS),
2904 CreateMockRead(*eightk_data_frame, 7, ASYNC),
2905 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2906 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2907 CreateMockRead(*eightk_data_frame, 10, SYNCHRONOUS),
2908 CreateMockRead(*twok_data_frame, 11, SYNCHRONOUS),
2909 CreateMockRead(*finish_data_frame, 12, SYNCHRONOUS),
2910 MockRead(ASYNC, 0, 13) // EOF
2913 // Create SpdySession and SpdyStream and send the request.
2914 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2915 session_deps_.socket_factory->AddSocketDataProvider(&data);
2917 CreateNetworkSession();
2919 base::WeakPtr<SpdySession> session =
2920 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2922 GURL url1(kDefaultURL);
2923 base::WeakPtr<SpdyStream> spdy_stream1 =
2924 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2925 session, url1, MEDIUM, BoundNetLog());
2926 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2927 EXPECT_EQ(0u, spdy_stream1->stream_id());
2928 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2929 spdy_stream1->SetDelegate(&delegate1);
2931 scoped_ptr<SpdyHeaderBlock> headers1(
2932 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2933 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2934 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2936 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2937 // posting of tasks.
2938 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2940 // Run until 1st read.
2941 EXPECT_EQ(0u, delegate1.stream_id());
2942 base::RunLoop().RunUntilIdle();
2943 EXPECT_EQ(1u, delegate1.stream_id());
2944 EXPECT_EQ(0u, observer.executed_count());
2946 // Read all the data and verify SpdySession::DoReadLoop has posted a
2947 // task.
2948 data.CompleteRead();
2949 base::RunLoop().RunUntilIdle();
2950 EXPECT_FALSE(spdy_stream1);
2952 // Verify task observer's executed_count is 1, which indicates DoRead has
2953 // posted only one task and thus yielded though there is data available for
2954 // it to read.
2955 EXPECT_EQ(1u, observer.executed_count());
2956 EXPECT_TRUE(data.AllWriteDataConsumed());
2957 EXPECT_TRUE(data.AllReadDataConsumed());
2960 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2961 // nothing blows up.
2962 TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
2963 session_deps_.host_resolver->set_synchronous_mode(true);
2965 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2967 scoped_ptr<SpdyFrame> req1(
2968 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2969 MockWrite writes[] = {
2970 CreateMockWrite(*req1, 0),
2973 scoped_ptr<SpdyFrame> resp1(
2974 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2975 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2976 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
2978 MockRead reads[] = {
2979 CreateMockRead(*resp1, 1),
2980 MockRead(ASYNC, ERR_IO_PENDING, 2),
2981 CreateMockRead(*body1, 3),
2982 CreateMockRead(*goaway, 4),
2985 // Create SpdySession and SpdyStream and send the request.
2986 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2987 session_deps_.socket_factory->AddSocketDataProvider(&data);
2989 CreateNetworkSession();
2991 base::WeakPtr<SpdySession> session =
2992 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2994 GURL url1(kDefaultURL);
2995 base::WeakPtr<SpdyStream> spdy_stream1 =
2996 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2997 session, url1, MEDIUM, BoundNetLog());
2998 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2999 spdy_stream1->SetDelegate(&delegate1);
3000 ASSERT_TRUE(spdy_stream1.get() != nullptr);
3001 EXPECT_EQ(0u, spdy_stream1->stream_id());
3003 scoped_ptr<SpdyHeaderBlock> headers1(
3004 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3005 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
3006 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3008 // Run until 1st read.
3009 EXPECT_EQ(0u, spdy_stream1->stream_id());
3010 base::RunLoop().RunUntilIdle();
3011 EXPECT_EQ(1u, spdy_stream1->stream_id());
3013 // Run until GoAway.
3014 data.CompleteRead();
3015 base::RunLoop().RunUntilIdle();
3016 EXPECT_FALSE(spdy_stream1);
3017 EXPECT_TRUE(data.AllWriteDataConsumed());
3018 EXPECT_TRUE(data.AllReadDataConsumed());
3019 EXPECT_FALSE(session);
3022 // Within this framework, a SpdySession should be initialized with
3023 // flow control disabled for protocol version 2, with flow control
3024 // enabled only for streams for protocol version 3, and with flow
3025 // control enabled for streams and sessions for higher versions.
3026 TEST_P(SpdySessionTest, ProtocolNegotiation) {
3027 session_deps_.host_resolver->set_synchronous_mode(true);
3029 MockRead reads[] = {
3030 MockRead(SYNCHRONOUS, 0, 0) // EOF
3032 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
3033 session_deps_.socket_factory->AddSocketDataProvider(&data);
3035 CreateNetworkSession();
3036 base::WeakPtr<SpdySession> session =
3037 CreateFakeSpdySession(spdy_session_pool_, key_);
3039 EXPECT_EQ(spdy_util_.spdy_version(),
3040 session->buffered_spdy_framer_->protocol_version());
3041 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3042 session->flow_control_state());
3043 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3044 session->session_send_window_size_);
3045 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3046 session->session_recv_window_size_);
3047 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3050 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3051 // pointers to the idle session are currently held.
3052 TEST_P(SpdySessionTest, CloseOneIdleConnection) {
3053 ClientSocketPoolManager::set_max_sockets_per_group(
3054 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3055 ClientSocketPoolManager::set_max_sockets_per_pool(
3056 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3058 MockRead reads[] = {
3059 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3061 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
3062 session_deps_.socket_factory->AddSocketDataProvider(&data);
3063 session_deps_.socket_factory->AddSocketDataProvider(&data);
3065 CreateNetworkSession();
3067 TransportClientSocketPool* pool =
3068 http_session_->GetTransportSocketPool(
3069 HttpNetworkSession::NORMAL_SOCKET_POOL);
3071 // Create an idle SPDY session.
3072 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3073 PRIVACY_MODE_DISABLED);
3074 base::WeakPtr<SpdySession> session1 =
3075 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3076 EXPECT_FALSE(pool->IsStalled());
3078 // Trying to create a new connection should cause the pool to be stalled, and
3079 // post a task asynchronously to try and close the session.
3080 TestCompletionCallback callback2;
3081 HostPortPair host_port2("2.com", 80);
3082 scoped_refptr<TransportSocketParams> params2(
3083 new TransportSocketParams(
3084 host_port2, false, false, OnHostResolutionCallback(),
3085 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3086 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3087 EXPECT_EQ(ERR_IO_PENDING,
3088 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3089 callback2.callback(), pool, BoundNetLog()));
3090 EXPECT_TRUE(pool->IsStalled());
3092 // The socket pool should close the connection asynchronously and establish a
3093 // new connection.
3094 EXPECT_EQ(OK, callback2.WaitForResult());
3095 EXPECT_FALSE(pool->IsStalled());
3096 EXPECT_FALSE(session1);
3099 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3100 // pointers to the idle session are currently held, in the case the SPDY session
3101 // has an alias.
3102 TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
3103 ClientSocketPoolManager::set_max_sockets_per_group(
3104 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3105 ClientSocketPoolManager::set_max_sockets_per_pool(
3106 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3108 MockRead reads[] = {
3109 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3111 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
3112 session_deps_.socket_factory->AddSocketDataProvider(&data);
3113 session_deps_.socket_factory->AddSocketDataProvider(&data);
3115 session_deps_.host_resolver->set_synchronous_mode(true);
3116 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3117 "1.com", "192.168.0.2", std::string());
3118 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3119 "2.com", "192.168.0.2", std::string());
3120 // Not strictly needed.
3121 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3122 "3.com", "192.168.0.3", std::string());
3124 CreateNetworkSession();
3126 TransportClientSocketPool* pool =
3127 http_session_->GetTransportSocketPool(
3128 HttpNetworkSession::NORMAL_SOCKET_POOL);
3130 // Create an idle SPDY session.
3131 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3132 PRIVACY_MODE_DISABLED);
3133 base::WeakPtr<SpdySession> session1 =
3134 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3135 EXPECT_FALSE(pool->IsStalled());
3137 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3138 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3139 PRIVACY_MODE_DISABLED);
3140 HostResolver::RequestInfo info(key2.host_port_pair());
3141 AddressList addresses;
3142 // Pre-populate the DNS cache, since a synchronous resolution is required in
3143 // order to create the alias.
3144 session_deps_.host_resolver->Resolve(info, DEFAULT_PRIORITY, &addresses,
3145 CompletionCallback(), nullptr,
3146 BoundNetLog());
3147 // Get a session for |key2|, which should return the session created earlier.
3148 base::WeakPtr<SpdySession> session2 =
3149 spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3150 ASSERT_EQ(session1.get(), session2.get());
3151 EXPECT_FALSE(pool->IsStalled());
3153 // Trying to create a new connection should cause the pool to be stalled, and
3154 // post a task asynchronously to try and close the session.
3155 TestCompletionCallback callback3;
3156 HostPortPair host_port3("3.com", 80);
3157 scoped_refptr<TransportSocketParams> params3(
3158 new TransportSocketParams(
3159 host_port3, false, false, OnHostResolutionCallback(),
3160 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3161 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3162 EXPECT_EQ(ERR_IO_PENDING,
3163 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3164 callback3.callback(), pool, BoundNetLog()));
3165 EXPECT_TRUE(pool->IsStalled());
3167 // The socket pool should close the connection asynchronously and establish a
3168 // new connection.
3169 EXPECT_EQ(OK, callback3.WaitForResult());
3170 EXPECT_FALSE(pool->IsStalled());
3171 EXPECT_FALSE(session1);
3172 EXPECT_FALSE(session2);
3175 // Tests that when a SPDY session becomes idle, it closes itself if there is
3176 // a lower layer pool stalled on the per-pool socket limit.
3177 TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3178 ClientSocketPoolManager::set_max_sockets_per_group(
3179 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3180 ClientSocketPoolManager::set_max_sockets_per_pool(
3181 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3183 MockRead reads[] = {
3184 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3186 scoped_ptr<SpdyFrame> req1(
3187 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
3188 scoped_ptr<SpdyFrame> cancel1(
3189 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3190 MockWrite writes[] = {
3191 CreateMockWrite(*req1, 1),
3192 CreateMockWrite(*cancel1, 1),
3194 StaticSocketDataProvider data(reads, arraysize(reads),
3195 writes, arraysize(writes));
3196 session_deps_.socket_factory->AddSocketDataProvider(&data);
3198 MockRead http_reads[] = {
3199 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3201 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
3203 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3206 CreateNetworkSession();
3208 TransportClientSocketPool* pool =
3209 http_session_->GetTransportSocketPool(
3210 HttpNetworkSession::NORMAL_SOCKET_POOL);
3212 // Create a SPDY session.
3213 GURL url1(kDefaultURL);
3214 SpdySessionKey key1(HostPortPair(url1.host(), 80),
3215 ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3216 base::WeakPtr<SpdySession> session1 =
3217 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3218 EXPECT_FALSE(pool->IsStalled());
3220 // Create a stream using the session, and send a request.
3222 TestCompletionCallback callback1;
3223 base::WeakPtr<SpdyStream> spdy_stream1 =
3224 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3225 session1, url1, DEFAULT_PRIORITY,
3226 BoundNetLog());
3227 ASSERT_TRUE(spdy_stream1.get());
3228 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3229 spdy_stream1->SetDelegate(&delegate1);
3231 scoped_ptr<SpdyHeaderBlock> headers1(
3232 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3233 EXPECT_EQ(ERR_IO_PENDING,
3234 spdy_stream1->SendRequestHeaders(
3235 headers1.Pass(), NO_MORE_DATA_TO_SEND));
3236 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3238 base::RunLoop().RunUntilIdle();
3240 // Trying to create a new connection should cause the pool to be stalled, and
3241 // post a task asynchronously to try and close the session.
3242 TestCompletionCallback callback2;
3243 HostPortPair host_port2("2.com", 80);
3244 scoped_refptr<TransportSocketParams> params2(
3245 new TransportSocketParams(
3246 host_port2, false, false, OnHostResolutionCallback(),
3247 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3248 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3249 EXPECT_EQ(ERR_IO_PENDING,
3250 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3251 callback2.callback(), pool, BoundNetLog()));
3252 EXPECT_TRUE(pool->IsStalled());
3254 // Running the message loop should cause the socket pool to ask the SPDY
3255 // session to close an idle socket, but since the socket is in use, nothing
3256 // happens.
3257 base::RunLoop().RunUntilIdle();
3258 EXPECT_TRUE(pool->IsStalled());
3259 EXPECT_FALSE(callback2.have_result());
3261 // Cancelling the request should result in the session's socket being
3262 // closed, since the pool is stalled.
3263 ASSERT_TRUE(spdy_stream1.get());
3264 spdy_stream1->Cancel();
3265 base::RunLoop().RunUntilIdle();
3266 ASSERT_FALSE(pool->IsStalled());
3267 EXPECT_EQ(OK, callback2.WaitForResult());
3270 // Verify that SpdySessionKey and therefore SpdySession is different when
3271 // privacy mode is enabled or disabled.
3272 TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3273 CreateNetworkSession();
3275 HostPortPair host_port_pair("www.example.org", 443);
3276 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3277 PRIVACY_MODE_ENABLED);
3278 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3279 PRIVACY_MODE_DISABLED);
3281 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3282 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3284 // Add SpdySession with PrivacyMode Enabled to the pool.
3285 base::WeakPtr<SpdySession> session_privacy_enabled =
3286 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3288 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3289 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3291 // Add SpdySession with PrivacyMode Disabled to the pool.
3292 base::WeakPtr<SpdySession> session_privacy_disabled =
3293 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3295 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3296 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3298 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3299 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3300 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3302 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3303 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3304 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3307 // Delegate that creates another stream when its stream is closed.
3308 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3309 public:
3310 StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3311 const base::WeakPtr<SpdySession>& session)
3312 : StreamDelegateDoNothing(stream),
3313 session_(session) {}
3315 ~StreamCreatingDelegate() override {}
3317 void OnClose(int status) override {
3318 GURL url(kDefaultURL);
3319 ignore_result(
3320 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3321 session_, url, MEDIUM, BoundNetLog()));
3324 private:
3325 const base::WeakPtr<SpdySession> session_;
3328 // Create another stream in response to a stream being reset. Nothing
3329 // should blow up. This is a regression test for
3330 // http://crbug.com/263690 .
3331 TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3332 session_deps_.host_resolver->set_synchronous_mode(true);
3334 scoped_ptr<SpdyFrame> req(
3335 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
3336 MockWrite writes[] = {
3337 CreateMockWrite(*req, 0),
3340 scoped_ptr<SpdyFrame> rst(
3341 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3342 MockRead reads[] = {
3343 MockRead(ASYNC, ERR_IO_PENDING, 1),
3344 CreateMockRead(*rst, 2),
3345 MockRead(ASYNC, ERR_IO_PENDING, 3),
3346 MockRead(ASYNC, 0, 4) // EOF
3348 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3349 session_deps_.socket_factory->AddSocketDataProvider(&data);
3351 CreateNetworkSession();
3353 base::WeakPtr<SpdySession> session =
3354 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3356 GURL url(kDefaultURL);
3357 base::WeakPtr<SpdyStream> spdy_stream =
3358 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3359 session, url, MEDIUM, BoundNetLog());
3360 ASSERT_TRUE(spdy_stream.get() != nullptr);
3361 EXPECT_EQ(0u, spdy_stream->stream_id());
3363 StreamCreatingDelegate delegate(spdy_stream, session);
3364 spdy_stream->SetDelegate(&delegate);
3366 scoped_ptr<SpdyHeaderBlock> headers(
3367 spdy_util_.ConstructGetHeaderBlock(url.spec()));
3368 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3369 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3371 EXPECT_EQ(0u, spdy_stream->stream_id());
3373 base::RunLoop().RunUntilIdle();
3375 EXPECT_EQ(1u, spdy_stream->stream_id());
3377 // Cause the stream to be reset, which should cause another stream
3378 // to be created.
3379 data.CompleteRead();
3380 base::RunLoop().RunUntilIdle();
3382 EXPECT_FALSE(spdy_stream);
3383 EXPECT_TRUE(delegate.StreamIsClosed());
3384 EXPECT_EQ(0u, session->num_active_streams());
3385 EXPECT_EQ(1u, session->num_created_streams());
3387 data.CompleteRead();
3388 base::RunLoop().RunUntilIdle();
3389 EXPECT_FALSE(session);
3392 // The tests below are only for SPDY/3 and above.
3394 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3395 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3396 // gets sent.
3397 SettingsMap new_settings;
3398 int32 window_size = 1;
3399 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3400 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3402 // Set up the socket so we read a SETTINGS frame that sets
3403 // INITIAL_WINDOW_SIZE.
3404 scoped_ptr<SpdyFrame> settings_frame(
3405 spdy_util_.ConstructSpdySettings(new_settings));
3406 MockRead reads[] = {
3407 CreateMockRead(*settings_frame, 0),
3408 MockRead(ASYNC, ERR_IO_PENDING, 1),
3409 MockRead(ASYNC, 0, 2) // EOF
3412 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3413 MockWrite writes[] = {
3414 CreateMockWrite(*settings_ack, 3),
3417 session_deps_.host_resolver->set_synchronous_mode(true);
3419 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3420 session_deps_.socket_factory->AddSocketDataProvider(&data);
3422 CreateNetworkSession();
3424 base::WeakPtr<SpdySession> session =
3425 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3426 base::WeakPtr<SpdyStream> spdy_stream1 =
3427 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3428 session, test_url_, MEDIUM, BoundNetLog());
3429 ASSERT_TRUE(spdy_stream1.get() != nullptr);
3430 TestCompletionCallback callback1;
3431 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3433 // Process the SETTINGS frame.
3434 base::RunLoop().RunUntilIdle();
3435 EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3436 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3438 // Release the first one, this will allow the second to be created.
3439 spdy_stream1->Cancel();
3440 EXPECT_FALSE(spdy_stream1);
3442 base::WeakPtr<SpdyStream> spdy_stream2 =
3443 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3444 session, test_url_, MEDIUM, BoundNetLog());
3445 ASSERT_TRUE(spdy_stream2.get() != nullptr);
3446 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3447 spdy_stream2->Cancel();
3448 EXPECT_FALSE(spdy_stream2);
3450 EXPECT_TRUE(session);
3451 data.CompleteRead();
3452 base::RunLoop().RunUntilIdle();
3453 EXPECT_FALSE(session);
3456 // The tests below are only for SPDY/3.1 and above.
3458 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3459 // adjust the session receive window size. In addition,
3460 // SpdySession::IncreaseRecvWindowSize should trigger
3461 // sending a WINDOW_UPDATE frame for a large enough delta.
3462 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3463 if (GetParam() < kProtoSPDY31)
3464 return;
3466 session_deps_.host_resolver->set_synchronous_mode(true);
3468 const int32 initial_window_size =
3469 SpdySession::GetDefaultInitialWindowSize(GetParam());
3470 const int32 delta_window_size = 100;
3472 MockRead reads[] = {
3473 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
3475 scoped_ptr<SpdyFrame> window_update(spdy_util_.ConstructSpdyWindowUpdate(
3476 kSessionFlowControlStreamId, initial_window_size + delta_window_size));
3477 MockWrite writes[] = {
3478 CreateMockWrite(*window_update, 0),
3480 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3481 session_deps_.socket_factory->AddSocketDataProvider(&data);
3483 CreateNetworkSession();
3484 base::WeakPtr<SpdySession> session =
3485 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3486 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3487 session->flow_control_state());
3489 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3490 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3492 session->IncreaseRecvWindowSize(delta_window_size);
3493 EXPECT_EQ(initial_window_size + delta_window_size,
3494 session->session_recv_window_size_);
3495 EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3497 // Should trigger sending a WINDOW_UPDATE frame.
3498 session->IncreaseRecvWindowSize(initial_window_size);
3499 EXPECT_EQ(initial_window_size + delta_window_size + initial_window_size,
3500 session->session_recv_window_size_);
3501 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3503 base::RunLoop().RunUntilIdle();
3505 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3506 session->in_io_loop_ = true;
3507 session->DecreaseRecvWindowSize(initial_window_size + delta_window_size +
3508 initial_window_size);
3509 session->in_io_loop_ = false;
3510 EXPECT_EQ(0, session->session_recv_window_size_);
3511 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3513 EXPECT_TRUE(session);
3514 data.CompleteRead();
3515 base::RunLoop().RunUntilIdle();
3516 EXPECT_FALSE(session);
3519 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3520 // adjust the session send window size when the "enable_spdy_31" flag
3521 // is set.
3522 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3523 if (GetParam() < kProtoSPDY31)
3524 return;
3526 session_deps_.host_resolver->set_synchronous_mode(true);
3528 MockRead reads[] = {
3529 MockRead(SYNCHRONOUS, 0, 0) // EOF
3531 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
3532 session_deps_.socket_factory->AddSocketDataProvider(&data);
3534 CreateNetworkSession();
3535 base::WeakPtr<SpdySession> session =
3536 CreateFakeSpdySession(spdy_session_pool_, key_);
3537 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3538 session->flow_control_state());
3540 const int32 initial_window_size =
3541 SpdySession::GetDefaultInitialWindowSize(GetParam());
3542 const int32 delta_window_size = 100;
3544 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3546 session->IncreaseSendWindowSize(delta_window_size);
3547 EXPECT_EQ(initial_window_size + delta_window_size,
3548 session->session_send_window_size_);
3550 session->DecreaseSendWindowSize(delta_window_size);
3551 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3554 // Incoming data for an inactive stream should not cause the session
3555 // receive window size to decrease, but it should cause the unacked
3556 // bytes to increase.
3557 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3558 if (GetParam() < kProtoSPDY31)
3559 return;
3561 session_deps_.host_resolver->set_synchronous_mode(true);
3563 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3564 MockRead reads[] = {
3565 CreateMockRead(*resp, 0),
3566 MockRead(ASYNC, ERR_IO_PENDING, 1),
3567 MockRead(ASYNC, 0, 2) // EOF
3569 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
3570 session_deps_.socket_factory->AddSocketDataProvider(&data);
3572 CreateNetworkSession();
3573 base::WeakPtr<SpdySession> session =
3574 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3575 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3576 session->flow_control_state());
3578 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3579 session->session_recv_window_size_);
3580 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3582 base::RunLoop().RunUntilIdle();
3584 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3585 session->session_recv_window_size_);
3586 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3588 EXPECT_TRUE(session);
3589 data.CompleteRead();
3590 base::RunLoop().RunUntilIdle();
3591 EXPECT_FALSE(session);
3594 // The frame header is not included in flow control, but frame payload
3595 // (including optional pad length and padding) is.
3596 TEST_P(SpdySessionTest, SessionFlowControlPadding) {
3597 // Padding only exists in HTTP/2.
3598 if (GetParam() < kProtoHTTP2MinimumVersion)
3599 return;
3601 session_deps_.host_resolver->set_synchronous_mode(true);
3603 const int padding_length = 42;
3604 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(
3605 1, kUploadData, kUploadDataSize, false, padding_length));
3606 MockRead reads[] = {
3607 CreateMockRead(*resp, 0),
3608 MockRead(ASYNC, ERR_IO_PENDING, 1),
3609 MockRead(ASYNC, 0, 2) // EOF
3611 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
3612 session_deps_.socket_factory->AddSocketDataProvider(&data);
3614 CreateNetworkSession();
3615 base::WeakPtr<SpdySession> session =
3616 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3617 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3618 session->flow_control_state());
3620 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3621 session->session_recv_window_size_);
3622 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3624 base::RunLoop().RunUntilIdle();
3626 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3627 session->session_recv_window_size_);
3628 EXPECT_EQ(kUploadDataSize + padding_length,
3629 session->session_unacked_recv_window_bytes_);
3631 data.CompleteRead();
3632 base::RunLoop().RunUntilIdle();
3633 EXPECT_FALSE(session);
3636 // Peer sends more data than stream level receiving flow control window.
3637 TEST_P(SpdySessionTest, StreamFlowControlTooMuchData) {
3638 const int32 stream_max_recv_window_size = 1024;
3639 const int32 data_frame_size = 2 * stream_max_recv_window_size;
3641 scoped_ptr<SpdyFrame> req(
3642 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
3643 scoped_ptr<SpdyFrame> rst(
3644 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
3645 MockWrite writes[] = {
3646 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
3649 scoped_ptr<SpdyFrame> resp(
3650 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3651 const std::string payload(data_frame_size, 'a');
3652 scoped_ptr<SpdyFrame> data_frame(spdy_util_.ConstructSpdyBodyFrame(
3653 1, payload.data(), data_frame_size, false));
3654 MockRead reads[] = {
3655 CreateMockRead(*resp, 1),
3656 MockRead(ASYNC, ERR_IO_PENDING, 2),
3657 CreateMockRead(*data_frame, 3),
3658 MockRead(ASYNC, ERR_IO_PENDING, 5),
3659 MockRead(ASYNC, 0, 6),
3662 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3663 session_deps_.socket_factory->AddSocketDataProvider(&data);
3664 CreateNetworkSession();
3666 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
3667 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
3668 base::WeakPtr<SpdySession> session =
3669 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3670 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
3672 GURL url(kDefaultURL);
3673 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
3674 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
3675 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3677 test::StreamDelegateDoNothing delegate(spdy_stream);
3678 spdy_stream->SetDelegate(&delegate);
3680 scoped_ptr<SpdyHeaderBlock> headers(
3681 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3682 EXPECT_EQ(ERR_IO_PENDING, spdy_stream->SendRequestHeaders(
3683 headers.Pass(), NO_MORE_DATA_TO_SEND));
3685 // Request and response.
3686 base::RunLoop().RunUntilIdle();
3687 EXPECT_EQ(1u, spdy_stream->stream_id());
3689 // Too large data frame causes flow control error, should close stream.
3690 data.CompleteRead();
3691 base::RunLoop().RunUntilIdle();
3692 EXPECT_FALSE(spdy_stream);
3694 EXPECT_TRUE(session);
3695 data.CompleteRead();
3696 base::RunLoop().RunUntilIdle();
3697 EXPECT_FALSE(session);
3700 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3701 // deltas in the receiving window size when checking incoming frames for flow
3702 // control errors at session level.
3703 TEST_P(SpdySessionTest, SessionFlowControlTooMuchDataTwoDataFrames) {
3704 if (GetParam() < kProtoSPDY31)
3705 return;
3707 const int32 session_max_recv_window_size = 500;
3708 const int32 first_data_frame_size = 200;
3709 const int32 second_data_frame_size = 400;
3711 // First data frame should not trigger a WINDOW_UPDATE.
3712 ASSERT_GT(session_max_recv_window_size / 2, first_data_frame_size);
3713 // Second data frame would be fine had there been a WINDOW_UPDATE.
3714 ASSERT_GT(session_max_recv_window_size, second_data_frame_size);
3715 // But in fact, the two data frames together overflow the receiving window at
3716 // session level.
3717 ASSERT_LT(session_max_recv_window_size,
3718 first_data_frame_size + second_data_frame_size);
3720 session_deps_.host_resolver->set_synchronous_mode(true);
3722 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3723 0, GOAWAY_FLOW_CONTROL_ERROR,
3724 "delta_window_size is 400 in DecreaseRecvWindowSize, which is larger "
3725 "than the receive window size of 500"));
3726 MockWrite writes[] = {
3727 CreateMockWrite(*goaway, 4),
3730 const std::string first_data_frame(first_data_frame_size, 'a');
3731 scoped_ptr<SpdyFrame> first(spdy_util_.ConstructSpdyBodyFrame(
3732 1, first_data_frame.data(), first_data_frame_size, false));
3733 const std::string second_data_frame(second_data_frame_size, 'b');
3734 scoped_ptr<SpdyFrame> second(spdy_util_.ConstructSpdyBodyFrame(
3735 1, second_data_frame.data(), second_data_frame_size, false));
3736 MockRead reads[] = {
3737 CreateMockRead(*first, 0),
3738 MockRead(ASYNC, ERR_IO_PENDING, 1),
3739 CreateMockRead(*second, 2),
3740 MockRead(ASYNC, 0, 3),
3742 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3743 session_deps_.socket_factory->AddSocketDataProvider(&data);
3745 CreateNetworkSession();
3746 base::WeakPtr<SpdySession> session =
3747 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3748 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3749 session->flow_control_state());
3750 // Setting session level receiving window size to smaller than initial is not
3751 // possible via SpdySessionPoolPeer.
3752 session->session_recv_window_size_ = session_max_recv_window_size;
3754 // First data frame is immediately consumed and does not trigger
3755 // WINDOW_UPDATE.
3756 base::RunLoop().RunUntilIdle();
3757 EXPECT_EQ(first_data_frame_size, session->session_unacked_recv_window_bytes_);
3758 EXPECT_EQ(session_max_recv_window_size, session->session_recv_window_size_);
3759 EXPECT_EQ(SpdySession::STATE_AVAILABLE, session->availability_state_);
3761 // Second data frame overflows receiving window, causes session to close.
3762 data.CompleteRead();
3763 base::RunLoop().RunUntilIdle();
3764 EXPECT_EQ(SpdySession::STATE_DRAINING, session->availability_state_);
3767 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3768 // deltas in the receiving window size when checking incoming data frames for
3769 // flow control errors at stream level.
3770 TEST_P(SpdySessionTest, StreamFlowControlTooMuchDataTwoDataFrames) {
3771 if (GetParam() < kProtoSPDY3)
3772 return;
3774 const int32 stream_max_recv_window_size = 500;
3775 const int32 first_data_frame_size = 200;
3776 const int32 second_data_frame_size = 400;
3778 // First data frame should not trigger a WINDOW_UPDATE.
3779 ASSERT_GT(stream_max_recv_window_size / 2, first_data_frame_size);
3780 // Second data frame would be fine had there been a WINDOW_UPDATE.
3781 ASSERT_GT(stream_max_recv_window_size, second_data_frame_size);
3782 // But in fact, they should overflow the receiving window at stream level.
3783 ASSERT_LT(stream_max_recv_window_size,
3784 first_data_frame_size + second_data_frame_size);
3786 scoped_ptr<SpdyFrame> req(
3787 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
3788 scoped_ptr<SpdyFrame> rst(
3789 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
3790 MockWrite writes[] = {
3791 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 6),
3794 scoped_ptr<SpdyFrame> resp(
3795 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3796 const std::string first_data_frame(first_data_frame_size, 'a');
3797 scoped_ptr<SpdyFrame> first(spdy_util_.ConstructSpdyBodyFrame(
3798 1, first_data_frame.data(), first_data_frame_size, false));
3799 const std::string second_data_frame(second_data_frame_size, 'b');
3800 scoped_ptr<SpdyFrame> second(spdy_util_.ConstructSpdyBodyFrame(
3801 1, second_data_frame.data(), second_data_frame_size, false));
3802 MockRead reads[] = {
3803 CreateMockRead(*resp, 1),
3804 MockRead(ASYNC, ERR_IO_PENDING, 2),
3805 CreateMockRead(*first, 3),
3806 MockRead(ASYNC, ERR_IO_PENDING, 4),
3807 CreateMockRead(*second, 5),
3808 MockRead(ASYNC, ERR_IO_PENDING, 7),
3809 MockRead(ASYNC, 0, 8),
3812 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3813 session_deps_.socket_factory->AddSocketDataProvider(&data);
3815 CreateNetworkSession();
3816 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
3817 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
3819 base::WeakPtr<SpdySession> session =
3820 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3821 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
3823 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
3824 SPDY_REQUEST_RESPONSE_STREAM, session, test_url_, LOWEST, BoundNetLog());
3825 test::StreamDelegateDoNothing delegate(spdy_stream);
3826 spdy_stream->SetDelegate(&delegate);
3828 scoped_ptr<SpdyHeaderBlock> headers(
3829 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3830 EXPECT_EQ(ERR_IO_PENDING, spdy_stream->SendRequestHeaders(
3831 headers.Pass(), NO_MORE_DATA_TO_SEND));
3833 // Request and response.
3834 base::RunLoop().RunUntilIdle();
3835 EXPECT_TRUE(spdy_stream->IsLocallyClosed());
3836 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3838 // First data frame.
3839 data.CompleteRead();
3840 base::RunLoop().RunUntilIdle();
3841 EXPECT_TRUE(spdy_stream->IsLocallyClosed());
3842 EXPECT_EQ(stream_max_recv_window_size - first_data_frame_size,
3843 spdy_stream->recv_window_size());
3845 // Consume first data frame. This does not trigger a WINDOW_UPDATE.
3846 std::string received_data = delegate.TakeReceivedData();
3847 EXPECT_EQ(static_cast<size_t>(first_data_frame_size), received_data.size());
3848 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3850 // Second data frame overflows receiving window, causes the stream to close.
3851 data.CompleteRead();
3852 base::RunLoop().RunUntilIdle();
3853 EXPECT_FALSE(spdy_stream.get());
3855 // RST_STREAM
3856 EXPECT_TRUE(session);
3857 data.CompleteRead();
3858 base::RunLoop().RunUntilIdle();
3859 EXPECT_FALSE(session);
3862 // A delegate that drops any received data.
3863 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3864 public:
3865 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3866 base::StringPiece data)
3867 : StreamDelegateSendImmediate(stream, data) {}
3869 ~DropReceivedDataDelegate() override {}
3871 // Drop any received data.
3872 void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override {}
3875 // Send data back and forth but use a delegate that drops its received
3876 // data. The receive window should still increase to its original
3877 // value, i.e. we shouldn't "leak" receive window bytes.
3878 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3879 if (GetParam() < kProtoSPDY31)
3880 return;
3882 const char kStreamUrl[] = "http://www.example.org/";
3884 const int32 msg_data_size = 100;
3885 const std::string msg_data(msg_data_size, 'a');
3887 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3888 kStreamUrl, 1, msg_data_size, MEDIUM, nullptr, 0));
3889 scoped_ptr<SpdyFrame> msg(
3890 spdy_util_.ConstructSpdyBodyFrame(
3891 1, msg_data.data(), msg_data_size, false));
3892 MockWrite writes[] = {
3893 CreateMockWrite(*req, 0),
3894 CreateMockWrite(*msg, 2),
3897 scoped_ptr<SpdyFrame> resp(
3898 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3899 scoped_ptr<SpdyFrame> echo(
3900 spdy_util_.ConstructSpdyBodyFrame(
3901 1, msg_data.data(), msg_data_size, false));
3902 scoped_ptr<SpdyFrame> window_update(
3903 spdy_util_.ConstructSpdyWindowUpdate(
3904 kSessionFlowControlStreamId, msg_data_size));
3905 MockRead reads[] = {
3906 CreateMockRead(*resp, 1),
3907 CreateMockRead(*echo, 3),
3908 MockRead(ASYNC, ERR_IO_PENDING, 4),
3909 MockRead(ASYNC, 0, 5) // EOF
3912 // Create SpdySession and SpdyStream and send the request.
3913 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3914 session_deps_.host_resolver->set_synchronous_mode(true);
3915 session_deps_.socket_factory->AddSocketDataProvider(&data);
3917 CreateNetworkSession();
3919 base::WeakPtr<SpdySession> session =
3920 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3922 GURL url(kStreamUrl);
3923 base::WeakPtr<SpdyStream> stream =
3924 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3925 session, url, MEDIUM, BoundNetLog());
3926 ASSERT_TRUE(stream.get() != nullptr);
3927 EXPECT_EQ(0u, stream->stream_id());
3929 DropReceivedDataDelegate delegate(stream, msg_data);
3930 stream->SetDelegate(&delegate);
3932 scoped_ptr<SpdyHeaderBlock> headers(
3933 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3934 EXPECT_EQ(ERR_IO_PENDING,
3935 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3936 EXPECT_TRUE(stream->HasUrlFromHeaders());
3938 const int32 initial_window_size =
3939 SpdySession::GetDefaultInitialWindowSize(GetParam());
3940 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3941 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3943 base::RunLoop().RunUntilIdle();
3945 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3946 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3948 stream->Close();
3949 EXPECT_FALSE(stream);
3951 EXPECT_EQ(OK, delegate.WaitForClose());
3953 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3954 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3956 data.CompleteRead();
3957 base::RunLoop().RunUntilIdle();
3958 EXPECT_FALSE(session);
3961 // Send data back and forth but close the stream before its data frame
3962 // can be written to the socket. The send window should then increase
3963 // to its original value, i.e. we shouldn't "leak" send window bytes.
3964 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3965 if (GetParam() < kProtoSPDY31)
3966 return;
3968 const char kStreamUrl[] = "http://www.example.org/";
3970 const int32 msg_data_size = 100;
3971 const std::string msg_data(msg_data_size, 'a');
3973 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3974 kStreamUrl, 1, msg_data_size, MEDIUM, nullptr, 0));
3975 MockWrite writes[] = {
3976 CreateMockWrite(*req, 0),
3979 scoped_ptr<SpdyFrame> resp(
3980 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3981 MockRead reads[] = {
3982 MockRead(ASYNC, ERR_IO_PENDING, 1),
3983 CreateMockRead(*resp, 2),
3984 MockRead(ASYNC, 0, 3) // EOF
3987 // Create SpdySession and SpdyStream and send the request.
3988 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3989 session_deps_.host_resolver->set_synchronous_mode(true);
3990 session_deps_.socket_factory->AddSocketDataProvider(&data);
3992 CreateNetworkSession();
3994 base::WeakPtr<SpdySession> session =
3995 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3997 GURL url(kStreamUrl);
3998 base::WeakPtr<SpdyStream> stream =
3999 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
4000 session, url, MEDIUM, BoundNetLog());
4001 ASSERT_TRUE(stream.get() != nullptr);
4002 EXPECT_EQ(0u, stream->stream_id());
4004 test::StreamDelegateSendImmediate delegate(stream, msg_data);
4005 stream->SetDelegate(&delegate);
4007 scoped_ptr<SpdyHeaderBlock> headers(
4008 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
4009 EXPECT_EQ(ERR_IO_PENDING,
4010 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4011 EXPECT_TRUE(stream->HasUrlFromHeaders());
4013 const int32 initial_window_size =
4014 SpdySession::GetDefaultInitialWindowSize(GetParam());
4015 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
4017 // Write request.
4018 base::RunLoop().RunUntilIdle();
4020 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
4022 // Read response, but do not run the message loop, so that the body is not
4023 // written to the socket.
4024 data.CompleteRead();
4026 EXPECT_EQ(initial_window_size - msg_data_size,
4027 session->session_send_window_size_);
4029 // Closing the stream should increase the session's send window.
4030 stream->Close();
4031 EXPECT_FALSE(stream);
4033 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
4035 EXPECT_EQ(OK, delegate.WaitForClose());
4037 base::RunLoop().RunUntilIdle();
4038 EXPECT_FALSE(session);
4040 EXPECT_TRUE(data.AllWriteDataConsumed());
4041 EXPECT_TRUE(data.AllReadDataConsumed());
4044 // Send data back and forth; the send and receive windows should
4045 // change appropriately.
4046 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
4047 if (GetParam() < kProtoSPDY31)
4048 return;
4050 const char kStreamUrl[] = "http://www.example.org/";
4052 const int32 msg_data_size = 100;
4053 const std::string msg_data(msg_data_size, 'a');
4055 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
4056 kStreamUrl, 1, msg_data_size, MEDIUM, nullptr, 0));
4057 scoped_ptr<SpdyFrame> msg(
4058 spdy_util_.ConstructSpdyBodyFrame(
4059 1, msg_data.data(), msg_data_size, false));
4060 MockWrite writes[] = {
4061 CreateMockWrite(*req, 0),
4062 CreateMockWrite(*msg, 2),
4065 scoped_ptr<SpdyFrame> resp(
4066 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4067 scoped_ptr<SpdyFrame> echo(
4068 spdy_util_.ConstructSpdyBodyFrame(
4069 1, msg_data.data(), msg_data_size, false));
4070 scoped_ptr<SpdyFrame> window_update(
4071 spdy_util_.ConstructSpdyWindowUpdate(
4072 kSessionFlowControlStreamId, msg_data_size));
4073 MockRead reads[] = {
4074 CreateMockRead(*resp, 1),
4075 MockRead(ASYNC, ERR_IO_PENDING, 3),
4076 CreateMockRead(*echo, 4),
4077 MockRead(ASYNC, ERR_IO_PENDING, 5),
4078 CreateMockRead(*window_update, 6),
4079 MockRead(ASYNC, ERR_IO_PENDING, 7),
4080 MockRead(ASYNC, 0, 8) // EOF
4083 // Create SpdySession and SpdyStream and send the request.
4084 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4085 session_deps_.host_resolver->set_synchronous_mode(true);
4086 session_deps_.socket_factory->AddSocketDataProvider(&data);
4088 CreateNetworkSession();
4090 base::WeakPtr<SpdySession> session =
4091 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4093 GURL url(kStreamUrl);
4094 base::WeakPtr<SpdyStream> stream =
4095 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
4096 session, url, MEDIUM, BoundNetLog());
4097 ASSERT_TRUE(stream.get() != nullptr);
4098 EXPECT_EQ(0u, stream->stream_id());
4100 test::StreamDelegateSendImmediate delegate(stream, msg_data);
4101 stream->SetDelegate(&delegate);
4103 scoped_ptr<SpdyHeaderBlock> headers(
4104 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
4105 EXPECT_EQ(ERR_IO_PENDING,
4106 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4107 EXPECT_TRUE(stream->HasUrlFromHeaders());
4109 const int32 initial_window_size =
4110 SpdySession::GetDefaultInitialWindowSize(GetParam());
4111 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
4112 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
4113 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
4115 // Send request and message.
4116 base::RunLoop().RunUntilIdle();
4118 EXPECT_EQ(initial_window_size - msg_data_size,
4119 session->session_send_window_size_);
4120 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
4121 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
4123 // Read echo.
4124 data.CompleteRead();
4125 base::RunLoop().RunUntilIdle();
4127 EXPECT_EQ(initial_window_size - msg_data_size,
4128 session->session_send_window_size_);
4129 EXPECT_EQ(initial_window_size - msg_data_size,
4130 session->session_recv_window_size_);
4131 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
4133 // Read window update.
4134 data.CompleteRead();
4135 base::RunLoop().RunUntilIdle();
4137 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
4138 EXPECT_EQ(initial_window_size - msg_data_size,
4139 session->session_recv_window_size_);
4140 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
4142 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
4144 // Draining the delegate's read queue should increase the session's
4145 // receive window.
4146 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
4147 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
4148 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
4150 stream->Close();
4151 EXPECT_FALSE(stream);
4153 EXPECT_EQ(OK, delegate.WaitForClose());
4155 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
4156 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
4157 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
4159 data.CompleteRead();
4160 base::RunLoop().RunUntilIdle();
4161 EXPECT_FALSE(session);
4164 // Given a stall function and an unstall function, runs a test to make
4165 // sure that a stream resumes after unstall.
4166 void SpdySessionTest::RunResumeAfterUnstallTest(
4167 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
4168 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
4169 unstall_function) {
4170 const char kStreamUrl[] = "http://www.example.org/";
4171 GURL url(kStreamUrl);
4173 session_deps_.host_resolver->set_synchronous_mode(true);
4175 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
4176 kStreamUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4177 scoped_ptr<SpdyFrame> body(
4178 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4179 MockWrite writes[] = {
4180 CreateMockWrite(*req, 0),
4181 CreateMockWrite(*body, 1),
4184 scoped_ptr<SpdyFrame> resp(
4185 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4186 scoped_ptr<SpdyFrame> echo(
4187 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4188 MockRead reads[] = {
4189 CreateMockRead(*resp, 2), MockRead(ASYNC, 0, 3) // EOF
4192 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4193 session_deps_.socket_factory->AddSocketDataProvider(&data);
4195 CreateNetworkSession();
4196 base::WeakPtr<SpdySession> session =
4197 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4198 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4199 session->flow_control_state());
4201 base::WeakPtr<SpdyStream> stream =
4202 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4203 session, url, LOWEST, BoundNetLog());
4204 ASSERT_TRUE(stream.get() != nullptr);
4206 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
4207 stream->SetDelegate(&delegate);
4209 EXPECT_FALSE(stream->HasUrlFromHeaders());
4210 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4212 scoped_ptr<SpdyHeaderBlock> headers(
4213 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4214 EXPECT_EQ(ERR_IO_PENDING,
4215 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4216 EXPECT_TRUE(stream->HasUrlFromHeaders());
4217 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
4219 stall_function.Run(session.get(), stream.get());
4221 base::RunLoop().RunUntilIdle();
4223 EXPECT_TRUE(stream->send_stalled_by_flow_control());
4225 unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
4227 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4229 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
4231 EXPECT_TRUE(delegate.send_headers_completed());
4232 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
4233 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
4234 EXPECT_FALSE(session);
4235 EXPECT_TRUE(data.AllWriteDataConsumed());
4238 // Run the resume-after-unstall test with all possible stall and
4239 // unstall sequences.
4241 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
4242 if (GetParam() < kProtoSPDY31)
4243 return;
4245 RunResumeAfterUnstallTest(
4246 base::Bind(&SpdySessionTest::StallSessionOnly,
4247 base::Unretained(this)),
4248 base::Bind(&SpdySessionTest::UnstallSessionOnly,
4249 base::Unretained(this)));
4252 // Equivalent to
4253 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4254 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
4255 if (GetParam() < kProtoSPDY31)
4256 return;
4258 RunResumeAfterUnstallTest(
4259 base::Bind(&SpdySessionTest::StallStreamOnly,
4260 base::Unretained(this)),
4261 base::Bind(&SpdySessionTest::UnstallStreamOnly,
4262 base::Unretained(this)));
4265 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4266 if (GetParam() < kProtoSPDY31)
4267 return;
4269 RunResumeAfterUnstallTest(
4270 base::Bind(&SpdySessionTest::StallSessionStream,
4271 base::Unretained(this)),
4272 base::Bind(&SpdySessionTest::UnstallSessionStream,
4273 base::Unretained(this)));
4276 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4277 if (GetParam() < kProtoSPDY31)
4278 return;
4280 RunResumeAfterUnstallTest(
4281 base::Bind(&SpdySessionTest::StallStreamSession,
4282 base::Unretained(this)),
4283 base::Bind(&SpdySessionTest::UnstallSessionStream,
4284 base::Unretained(this)));
4287 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4288 if (GetParam() < kProtoSPDY31)
4289 return;
4291 RunResumeAfterUnstallTest(
4292 base::Bind(&SpdySessionTest::StallStreamSession,
4293 base::Unretained(this)),
4294 base::Bind(&SpdySessionTest::UnstallStreamSession,
4295 base::Unretained(this)));
4298 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4299 if (GetParam() < kProtoSPDY31)
4300 return;
4302 RunResumeAfterUnstallTest(
4303 base::Bind(&SpdySessionTest::StallSessionStream,
4304 base::Unretained(this)),
4305 base::Bind(&SpdySessionTest::UnstallStreamSession,
4306 base::Unretained(this)));
4309 // Cause a stall by reducing the flow control send window to 0. The
4310 // streams should resume in priority order when that window is then
4311 // increased.
4312 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4313 if (GetParam() < kProtoSPDY31)
4314 return;
4316 const char kStreamUrl[] = "http://www.example.org/";
4317 GURL url(kStreamUrl);
4319 session_deps_.host_resolver->set_synchronous_mode(true);
4321 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4322 kStreamUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4323 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4324 kStreamUrl, 3, kBodyDataSize, MEDIUM, nullptr, 0));
4325 scoped_ptr<SpdyFrame> body1(
4326 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4327 scoped_ptr<SpdyFrame> body2(
4328 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4329 MockWrite writes[] = {
4330 CreateMockWrite(*req1, 0),
4331 CreateMockWrite(*req2, 1),
4332 CreateMockWrite(*body2, 2),
4333 CreateMockWrite(*body1, 3),
4336 scoped_ptr<SpdyFrame> resp1(
4337 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4338 scoped_ptr<SpdyFrame> resp2(
4339 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
4340 MockRead reads[] = {
4341 CreateMockRead(*resp1, 4),
4342 CreateMockRead(*resp2, 5),
4343 MockRead(ASYNC, 0, 6) // EOF
4346 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4347 session_deps_.socket_factory->AddSocketDataProvider(&data);
4349 CreateNetworkSession();
4350 base::WeakPtr<SpdySession> session =
4351 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4352 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4353 session->flow_control_state());
4355 base::WeakPtr<SpdyStream> stream1 =
4356 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4357 session, url, LOWEST, BoundNetLog());
4358 ASSERT_TRUE(stream1.get() != nullptr);
4360 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4361 stream1->SetDelegate(&delegate1);
4363 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4365 base::WeakPtr<SpdyStream> stream2 =
4366 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4367 session, url, MEDIUM, BoundNetLog());
4368 ASSERT_TRUE(stream2.get() != nullptr);
4370 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4371 stream2->SetDelegate(&delegate2);
4373 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4375 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4376 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4378 StallSessionSend(session.get());
4380 scoped_ptr<SpdyHeaderBlock> headers1(
4381 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4382 EXPECT_EQ(ERR_IO_PENDING,
4383 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4384 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4385 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4387 base::RunLoop().RunUntilIdle();
4388 EXPECT_EQ(1u, stream1->stream_id());
4389 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4391 scoped_ptr<SpdyHeaderBlock> headers2(
4392 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4393 EXPECT_EQ(ERR_IO_PENDING,
4394 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4395 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4396 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4398 base::RunLoop().RunUntilIdle();
4399 EXPECT_EQ(3u, stream2->stream_id());
4400 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4402 // This should unstall only stream2.
4403 UnstallSessionSend(session.get(), kBodyDataSize);
4405 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4406 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4408 base::RunLoop().RunUntilIdle();
4410 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4411 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4413 // This should then unstall stream1.
4414 UnstallSessionSend(session.get(), kBodyDataSize);
4416 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4417 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4419 base::RunLoop().RunUntilIdle();
4421 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4422 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4424 EXPECT_TRUE(delegate1.send_headers_completed());
4425 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4426 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4428 EXPECT_TRUE(delegate2.send_headers_completed());
4429 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4430 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4432 EXPECT_FALSE(session);
4433 EXPECT_TRUE(data.AllWriteDataConsumed());
4434 EXPECT_TRUE(data.AllReadDataConsumed());
4437 // Delegate that closes a given stream after sending its body.
4438 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4439 public:
4440 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4441 base::StringPiece data)
4442 : StreamDelegateWithBody(stream, data) {}
4444 ~StreamClosingDelegate() override {}
4446 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4447 stream_to_close_ = stream_to_close;
4450 void OnDataSent() override {
4451 test::StreamDelegateWithBody::OnDataSent();
4452 if (stream_to_close_.get()) {
4453 stream_to_close_->Close();
4454 EXPECT_FALSE(stream_to_close_);
4458 private:
4459 base::WeakPtr<SpdyStream> stream_to_close_;
4462 // Cause a stall by reducing the flow control send window to
4463 // 0. Unstalling the session should properly handle deleted streams.
4464 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4465 if (GetParam() < kProtoSPDY31)
4466 return;
4468 const char kStreamUrl[] = "http://www.example.org/";
4469 GURL url(kStreamUrl);
4471 session_deps_.host_resolver->set_synchronous_mode(true);
4473 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4474 kStreamUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4475 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4476 kStreamUrl, 3, kBodyDataSize, LOWEST, nullptr, 0));
4477 scoped_ptr<SpdyFrame> req3(spdy_util_.ConstructSpdyPost(
4478 kStreamUrl, 5, kBodyDataSize, LOWEST, nullptr, 0));
4479 scoped_ptr<SpdyFrame> body2(
4480 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4481 MockWrite writes[] = {
4482 CreateMockWrite(*req1, 0),
4483 CreateMockWrite(*req2, 1),
4484 CreateMockWrite(*req3, 2),
4485 CreateMockWrite(*body2, 3),
4488 scoped_ptr<SpdyFrame> resp2(
4489 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
4490 MockRead reads[] = {
4491 CreateMockRead(*resp2, 4),
4492 MockRead(ASYNC, ERR_IO_PENDING, 5),
4493 MockRead(ASYNC, 0, 6) // EOF
4496 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4497 session_deps_.socket_factory->AddSocketDataProvider(&data);
4499 CreateNetworkSession();
4500 base::WeakPtr<SpdySession> session =
4501 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4502 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4503 session->flow_control_state());
4505 base::WeakPtr<SpdyStream> stream1 =
4506 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4507 session, url, LOWEST, BoundNetLog());
4508 ASSERT_TRUE(stream1.get() != nullptr);
4510 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4511 stream1->SetDelegate(&delegate1);
4513 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4515 base::WeakPtr<SpdyStream> stream2 =
4516 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4517 session, url, LOWEST, BoundNetLog());
4518 ASSERT_TRUE(stream2.get() != nullptr);
4520 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4521 stream2->SetDelegate(&delegate2);
4523 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4525 base::WeakPtr<SpdyStream> stream3 =
4526 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4527 session, url, LOWEST, BoundNetLog());
4528 ASSERT_TRUE(stream3.get() != nullptr);
4530 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4531 stream3->SetDelegate(&delegate3);
4533 EXPECT_FALSE(stream3->HasUrlFromHeaders());
4535 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4536 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4537 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4539 StallSessionSend(session.get());
4541 scoped_ptr<SpdyHeaderBlock> headers1(
4542 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4543 EXPECT_EQ(ERR_IO_PENDING,
4544 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4545 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4546 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4548 base::RunLoop().RunUntilIdle();
4549 EXPECT_EQ(1u, stream1->stream_id());
4550 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4552 scoped_ptr<SpdyHeaderBlock> headers2(
4553 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4554 EXPECT_EQ(ERR_IO_PENDING,
4555 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4556 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4557 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4559 base::RunLoop().RunUntilIdle();
4560 EXPECT_EQ(3u, stream2->stream_id());
4561 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4563 scoped_ptr<SpdyHeaderBlock> headers3(
4564 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4565 EXPECT_EQ(ERR_IO_PENDING,
4566 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4567 EXPECT_TRUE(stream3->HasUrlFromHeaders());
4568 EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4570 base::RunLoop().RunUntilIdle();
4571 EXPECT_EQ(5u, stream3->stream_id());
4572 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4574 SpdyStreamId stream_id1 = stream1->stream_id();
4575 SpdyStreamId stream_id2 = stream2->stream_id();
4576 SpdyStreamId stream_id3 = stream3->stream_id();
4578 // Close stream1 preemptively.
4579 session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4580 EXPECT_FALSE(stream1);
4582 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4583 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4584 EXPECT_TRUE(session->IsStreamActive(stream_id3));
4586 // Unstall stream2, which should then close stream3.
4587 delegate2.set_stream_to_close(stream3);
4588 UnstallSessionSend(session.get(), kBodyDataSize);
4590 base::RunLoop().RunUntilIdle();
4591 EXPECT_FALSE(stream3);
4593 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4594 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4595 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4596 EXPECT_FALSE(session->IsStreamActive(stream_id3));
4598 data.CompleteRead();
4599 base::RunLoop().RunUntilIdle();
4600 EXPECT_FALSE(stream2);
4601 EXPECT_FALSE(session);
4603 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4604 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4605 EXPECT_EQ(OK, delegate3.WaitForClose());
4607 EXPECT_TRUE(delegate1.send_headers_completed());
4608 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4610 EXPECT_TRUE(delegate2.send_headers_completed());
4611 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4612 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4614 EXPECT_TRUE(delegate3.send_headers_completed());
4615 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4617 EXPECT_TRUE(data.AllWriteDataConsumed());
4620 // Cause a stall by reducing the flow control send window to
4621 // 0. Unstalling the session should properly handle the session itself
4622 // being closed.
4623 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4624 if (GetParam() < kProtoSPDY31)
4625 return;
4627 const char kStreamUrl[] = "http://www.example.org/";
4628 GURL url(kStreamUrl);
4630 session_deps_.host_resolver->set_synchronous_mode(true);
4632 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4633 kStreamUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4634 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4635 kStreamUrl, 3, kBodyDataSize, LOWEST, nullptr, 0));
4636 scoped_ptr<SpdyFrame> body1(
4637 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4638 MockWrite writes[] = {
4639 CreateMockWrite(*req1, 0),
4640 CreateMockWrite(*req2, 1),
4643 MockRead reads[] = {
4644 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
4647 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4648 session_deps_.socket_factory->AddSocketDataProvider(&data);
4650 CreateNetworkSession();
4651 base::WeakPtr<SpdySession> session =
4652 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4653 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4654 session->flow_control_state());
4656 base::WeakPtr<SpdyStream> stream1 =
4657 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4658 session, url, LOWEST, BoundNetLog());
4659 ASSERT_TRUE(stream1.get() != nullptr);
4661 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4662 stream1->SetDelegate(&delegate1);
4664 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4666 base::WeakPtr<SpdyStream> stream2 =
4667 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4668 session, url, LOWEST, BoundNetLog());
4669 ASSERT_TRUE(stream2.get() != nullptr);
4671 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4672 stream2->SetDelegate(&delegate2);
4674 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4676 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4677 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4679 StallSessionSend(session.get());
4681 scoped_ptr<SpdyHeaderBlock> headers1(
4682 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4683 EXPECT_EQ(ERR_IO_PENDING,
4684 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4685 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4686 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4688 base::RunLoop().RunUntilIdle();
4689 EXPECT_EQ(1u, stream1->stream_id());
4690 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4692 scoped_ptr<SpdyHeaderBlock> headers2(
4693 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4694 EXPECT_EQ(ERR_IO_PENDING,
4695 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4696 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4697 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4699 base::RunLoop().RunUntilIdle();
4700 EXPECT_EQ(3u, stream2->stream_id());
4701 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4703 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4705 // Unstall stream1.
4706 UnstallSessionSend(session.get(), kBodyDataSize);
4708 // Close the session (since we can't do it from within the delegate
4709 // method, since it's in the stream's loop).
4710 session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4711 data.CompleteRead();
4712 base::RunLoop().RunUntilIdle();
4713 EXPECT_FALSE(session);
4715 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4717 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4718 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4720 EXPECT_TRUE(delegate1.send_headers_completed());
4721 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4723 EXPECT_TRUE(delegate2.send_headers_completed());
4724 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4726 EXPECT_TRUE(data.AllWriteDataConsumed());
4729 TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4730 if (GetParam() < kProtoSPDY31)
4731 return;
4733 scoped_ptr<SpdyFrame> req(
4734 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4735 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4736 0, GOAWAY_FLOW_CONTROL_ERROR,
4737 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4738 "the receive window size of 1"));
4739 MockWrite writes[] = {
4740 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 4),
4743 scoped_ptr<SpdyFrame> resp(
4744 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4745 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4746 MockRead reads[] = {
4747 MockRead(ASYNC, ERR_IO_PENDING, 1),
4748 CreateMockRead(*resp, 2),
4749 CreateMockRead(*body, 3),
4752 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4753 session_deps_.socket_factory->AddSocketDataProvider(&data);
4755 CreateNetworkSession();
4757 base::WeakPtr<SpdySession> session =
4758 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4760 GURL url(kDefaultURL);
4761 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4762 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
4763 ASSERT_TRUE(spdy_stream.get() != nullptr);
4764 test::StreamDelegateDoNothing delegate(spdy_stream);
4765 spdy_stream->SetDelegate(&delegate);
4767 scoped_ptr<SpdyHeaderBlock> headers(
4768 spdy_util_.ConstructGetHeaderBlock(url.spec()));
4769 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4771 // Write request.
4772 base::RunLoop().RunUntilIdle();
4774 // Put session on the edge of overflowing it's recv window.
4775 session->session_recv_window_size_ = 1;
4777 // Read response headers & body. Body overflows the session window, and a
4778 // goaway is written.
4779 data.CompleteRead();
4780 base::RunLoop().RunUntilIdle();
4782 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4783 EXPECT_FALSE(session);
4786 TEST_P(SpdySessionTest, SplitHeaders) {
4787 GURL kStreamUrl("http://www.example.org/foo.dat");
4788 SpdyHeaderBlock headers;
4789 spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4790 headers["alpha"] = "beta";
4792 SpdyHeaderBlock request_headers;
4793 SpdyHeaderBlock response_headers;
4795 SplitPushedHeadersToRequestAndResponse(
4796 headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4798 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4799 std::string alpha_val =
4800 (it == response_headers.end()) ? std::string() : it->second;
4801 EXPECT_EQ("beta", alpha_val);
4803 GURL request_url =
4804 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4805 EXPECT_EQ(kStreamUrl, request_url);
4808 // Regression. Sorta. Push streams and client streams were sharing a single
4809 // limit for a long time.
4810 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4811 SettingsMap new_settings;
4812 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4813 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4814 scoped_ptr<SpdyFrame> settings_frame(
4815 spdy_util_.ConstructSpdySettings(new_settings));
4816 scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4817 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4818 MockRead reads[] = {
4819 CreateMockRead(*settings_frame, 0),
4820 MockRead(ASYNC, ERR_IO_PENDING, 3),
4821 CreateMockRead(*pushed, 4),
4822 MockRead(ASYNC, ERR_IO_PENDING, 5),
4823 MockRead(ASYNC, 0, 6),
4826 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4827 scoped_ptr<SpdyFrame> req(
4828 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4829 MockWrite writes[] = {
4830 CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4833 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4834 session_deps_.socket_factory->AddSocketDataProvider(&data);
4836 CreateNetworkSession();
4838 base::WeakPtr<SpdySession> session =
4839 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4841 // Read the settings frame.
4842 base::RunLoop().RunUntilIdle();
4844 GURL url1(kDefaultURL);
4845 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4846 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4847 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4848 EXPECT_EQ(0u, spdy_stream1->stream_id());
4849 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4850 spdy_stream1->SetDelegate(&delegate1);
4852 EXPECT_EQ(0u, session->num_active_streams());
4853 EXPECT_EQ(1u, session->num_created_streams());
4854 EXPECT_EQ(0u, session->num_pushed_streams());
4855 EXPECT_EQ(0u, session->num_active_pushed_streams());
4857 scoped_ptr<SpdyHeaderBlock> headers(
4858 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4859 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4860 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4862 // Run until 1st stream is activated.
4863 EXPECT_EQ(0u, delegate1.stream_id());
4864 base::RunLoop().RunUntilIdle();
4865 EXPECT_EQ(1u, delegate1.stream_id());
4866 EXPECT_EQ(1u, session->num_active_streams());
4867 EXPECT_EQ(0u, session->num_created_streams());
4868 EXPECT_EQ(0u, session->num_pushed_streams());
4869 EXPECT_EQ(0u, session->num_active_pushed_streams());
4871 // Run until pushed stream is created.
4872 data.CompleteRead();
4873 base::RunLoop().RunUntilIdle();
4874 EXPECT_EQ(2u, session->num_active_streams());
4875 EXPECT_EQ(0u, session->num_created_streams());
4876 EXPECT_EQ(1u, session->num_pushed_streams());
4877 EXPECT_EQ(1u, session->num_active_pushed_streams());
4879 // Second stream should not be stalled, although we have 2 active streams, but
4880 // one of them is push stream and should not be taken into account when we
4881 // create streams on the client.
4882 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4883 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4884 EXPECT_TRUE(spdy_stream2);
4885 EXPECT_EQ(2u, session->num_active_streams());
4886 EXPECT_EQ(1u, session->num_created_streams());
4887 EXPECT_EQ(1u, session->num_pushed_streams());
4888 EXPECT_EQ(1u, session->num_active_pushed_streams());
4890 // Read EOF.
4891 data.CompleteRead();
4892 base::RunLoop().RunUntilIdle();
4893 EXPECT_FALSE(session);
4896 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4897 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4898 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4899 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4900 nullptr, 0, 4, 1, "http://www.example.org/b.dat"));
4901 MockRead reads[] = {
4902 MockRead(ASYNC, ERR_IO_PENDING, 1),
4903 CreateMockRead(*push_a, 2),
4904 MockRead(ASYNC, ERR_IO_PENDING, 3),
4905 CreateMockRead(*push_b, 4),
4906 MockRead(ASYNC, ERR_IO_PENDING, 6),
4907 MockRead(ASYNC, 0, 7),
4910 scoped_ptr<SpdyFrame> req(
4911 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4912 scoped_ptr<SpdyFrame> rst(
4913 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4914 MockWrite writes[] = {
4915 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
4918 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4919 session_deps_.socket_factory->AddSocketDataProvider(&data);
4921 CreateNetworkSession();
4923 base::WeakPtr<SpdySession> session =
4924 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4925 session->set_max_concurrent_pushed_streams(1);
4927 GURL url1(kDefaultURL);
4928 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4929 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4930 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4931 EXPECT_EQ(0u, spdy_stream1->stream_id());
4932 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4933 spdy_stream1->SetDelegate(&delegate1);
4935 EXPECT_EQ(0u, session->num_active_streams());
4936 EXPECT_EQ(1u, session->num_created_streams());
4937 EXPECT_EQ(0u, session->num_pushed_streams());
4938 EXPECT_EQ(0u, session->num_active_pushed_streams());
4940 scoped_ptr<SpdyHeaderBlock> headers(
4941 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4942 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4943 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4945 // Run until 1st stream is activated.
4946 EXPECT_EQ(0u, delegate1.stream_id());
4947 base::RunLoop().RunUntilIdle();
4948 EXPECT_EQ(1u, delegate1.stream_id());
4949 EXPECT_EQ(1u, session->num_active_streams());
4950 EXPECT_EQ(0u, session->num_created_streams());
4951 EXPECT_EQ(0u, session->num_pushed_streams());
4952 EXPECT_EQ(0u, session->num_active_pushed_streams());
4954 // Run until pushed stream is created.
4955 data.CompleteRead();
4956 base::RunLoop().RunUntilIdle();
4957 EXPECT_EQ(2u, session->num_active_streams());
4958 EXPECT_EQ(0u, session->num_created_streams());
4959 EXPECT_EQ(1u, session->num_pushed_streams());
4960 EXPECT_EQ(1u, session->num_active_pushed_streams());
4962 // Reset incoming pushed stream.
4963 data.CompleteRead();
4964 base::RunLoop().RunUntilIdle();
4965 EXPECT_EQ(2u, session->num_active_streams());
4966 EXPECT_EQ(0u, session->num_created_streams());
4967 EXPECT_EQ(1u, session->num_pushed_streams());
4968 EXPECT_EQ(1u, session->num_active_pushed_streams());
4970 // Read EOF.
4971 data.CompleteRead();
4972 base::RunLoop().RunUntilIdle();
4973 EXPECT_FALSE(session);
4976 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4977 // Streams in reserved remote state exist only in HTTP/2.
4978 if (spdy_util_.spdy_version() < HTTP2)
4979 return;
4981 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4982 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4983 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4984 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/b.dat",
4985 push_headers.get());
4986 scoped_ptr<SpdyFrame> push_b(
4987 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4988 scoped_ptr<SpdyFrame> headers_b(
4989 spdy_util_.ConstructSpdyPushHeaders(4, nullptr, 0));
4990 MockRead reads[] = {
4991 MockRead(ASYNC, ERR_IO_PENDING, 1),
4992 CreateMockRead(*push_a, 2),
4993 MockRead(ASYNC, ERR_IO_PENDING, 3),
4994 CreateMockRead(*push_b, 4),
4995 MockRead(ASYNC, ERR_IO_PENDING, 5),
4996 CreateMockRead(*headers_b, 6),
4997 MockRead(ASYNC, ERR_IO_PENDING, 8),
4998 MockRead(ASYNC, 0, 9),
5001 scoped_ptr<SpdyFrame> req(
5002 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
5003 scoped_ptr<SpdyFrame> rst(
5004 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
5005 MockWrite writes[] = {
5006 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 7),
5009 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
5010 session_deps_.socket_factory->AddSocketDataProvider(&data);
5012 CreateNetworkSession();
5014 base::WeakPtr<SpdySession> session =
5015 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
5016 session->set_max_concurrent_pushed_streams(1);
5018 GURL url1(kDefaultURL);
5019 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
5020 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
5021 ASSERT_TRUE(spdy_stream1.get() != nullptr);
5022 EXPECT_EQ(0u, spdy_stream1->stream_id());
5023 test::StreamDelegateDoNothing delegate1(spdy_stream1);
5024 spdy_stream1->SetDelegate(&delegate1);
5026 EXPECT_EQ(0u, session->num_active_streams());
5027 EXPECT_EQ(1u, session->num_created_streams());
5028 EXPECT_EQ(0u, session->num_pushed_streams());
5029 EXPECT_EQ(0u, session->num_active_pushed_streams());
5031 scoped_ptr<SpdyHeaderBlock> headers(
5032 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
5033 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
5034 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
5036 // Run until 1st stream is activated.
5037 EXPECT_EQ(0u, delegate1.stream_id());
5038 base::RunLoop().RunUntilIdle();
5039 EXPECT_EQ(1u, delegate1.stream_id());
5040 EXPECT_EQ(1u, session->num_active_streams());
5041 EXPECT_EQ(0u, session->num_created_streams());
5042 EXPECT_EQ(0u, session->num_pushed_streams());
5043 EXPECT_EQ(0u, session->num_active_pushed_streams());
5045 // Run until pushed stream is created.
5046 data.CompleteRead();
5047 base::RunLoop().RunUntilIdle();
5048 EXPECT_EQ(2u, session->num_active_streams());
5049 EXPECT_EQ(0u, session->num_created_streams());
5050 EXPECT_EQ(1u, session->num_pushed_streams());
5051 EXPECT_EQ(1u, session->num_active_pushed_streams());
5053 // Accept promised stream. It should not count towards pushed stream limit.
5054 data.CompleteRead();
5055 base::RunLoop().RunUntilIdle();
5056 EXPECT_EQ(3u, session->num_active_streams());
5057 EXPECT_EQ(0u, session->num_created_streams());
5058 EXPECT_EQ(2u, session->num_pushed_streams());
5059 EXPECT_EQ(1u, session->num_active_pushed_streams());
5061 // Reset last pushed stream upon headers reception as it is going to be 2nd,
5062 // while we accept only one.
5063 data.CompleteRead();
5064 base::RunLoop().RunUntilIdle();
5065 EXPECT_EQ(2u, session->num_active_streams());
5066 EXPECT_EQ(0u, session->num_created_streams());
5067 EXPECT_EQ(1u, session->num_pushed_streams());
5068 EXPECT_EQ(1u, session->num_active_pushed_streams());
5070 // Read EOF.
5071 data.CompleteRead();
5072 base::RunLoop().RunUntilIdle();
5073 EXPECT_FALSE(session);
5076 TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
5077 // Streams in reserved remote state exist only in HTTP/2.
5078 if (spdy_util_.spdy_version() < HTTP2)
5079 return;
5081 const char kPushedUrl[] = "http://www.example.org/a.dat";
5082 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
5083 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
5084 scoped_ptr<SpdyFrame> push_promise(
5085 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
5086 scoped_ptr<SpdyFrame> headers_frame(
5087 spdy_util_.ConstructSpdyPushHeaders(2, nullptr, 0));
5088 MockRead reads[] = {
5089 MockRead(ASYNC, ERR_IO_PENDING, 1),
5090 CreateMockRead(*push_promise, 2),
5091 MockRead(ASYNC, ERR_IO_PENDING, 3),
5092 CreateMockRead(*headers_frame, 4),
5093 MockRead(ASYNC, ERR_IO_PENDING, 6),
5094 MockRead(ASYNC, 0, 7),
5097 scoped_ptr<SpdyFrame> req(
5098 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
5099 scoped_ptr<SpdyFrame> rst(
5100 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
5101 MockWrite writes[] = {
5102 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
5105 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
5106 session_deps_.socket_factory->AddSocketDataProvider(&data);
5108 CreateNetworkSession();
5110 base::WeakPtr<SpdySession> session =
5111 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
5113 GURL url1(kDefaultURL);
5114 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
5115 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
5116 ASSERT_TRUE(spdy_stream1.get() != nullptr);
5117 EXPECT_EQ(0u, spdy_stream1->stream_id());
5118 test::StreamDelegateDoNothing delegate1(spdy_stream1);
5119 spdy_stream1->SetDelegate(&delegate1);
5121 EXPECT_EQ(0u, session->num_active_streams());
5122 EXPECT_EQ(1u, session->num_created_streams());
5123 EXPECT_EQ(0u, session->num_pushed_streams());
5124 EXPECT_EQ(0u, session->num_active_pushed_streams());
5126 scoped_ptr<SpdyHeaderBlock> headers(
5127 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
5128 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
5129 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
5131 // Run until 1st stream is activated.
5132 EXPECT_EQ(0u, delegate1.stream_id());
5133 base::RunLoop().RunUntilIdle();
5134 EXPECT_EQ(1u, delegate1.stream_id());
5135 EXPECT_EQ(1u, session->num_active_streams());
5136 EXPECT_EQ(0u, session->num_created_streams());
5137 EXPECT_EQ(0u, session->num_pushed_streams());
5138 EXPECT_EQ(0u, session->num_active_pushed_streams());
5140 // Run until pushed stream is created.
5141 data.CompleteRead();
5142 base::RunLoop().RunUntilIdle();
5143 EXPECT_EQ(2u, session->num_active_streams());
5144 EXPECT_EQ(0u, session->num_created_streams());
5145 EXPECT_EQ(1u, session->num_pushed_streams());
5146 EXPECT_EQ(0u, session->num_active_pushed_streams());
5148 base::WeakPtr<SpdyStream> pushed_stream;
5149 int rv =
5150 session->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
5151 ASSERT_EQ(OK, rv);
5152 ASSERT_TRUE(pushed_stream.get() != nullptr);
5153 test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
5154 pushed_stream->SetDelegate(&delegate2);
5156 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
5157 // that all our counters are in consistent state.
5158 data.CompleteRead();
5159 base::RunLoop().RunUntilIdle();
5160 EXPECT_EQ(1u, session->num_active_streams());
5161 EXPECT_EQ(0u, session->num_created_streams());
5162 EXPECT_EQ(0u, session->num_pushed_streams());
5163 EXPECT_EQ(0u, session->num_active_pushed_streams());
5165 // Read EOF.
5166 data.CompleteRead();
5167 base::RunLoop().RunUntilIdle();
5168 EXPECT_TRUE(data.AllWriteDataConsumed());
5169 EXPECT_TRUE(data.AllReadDataConsumed());
5172 TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
5173 session_deps_.host_resolver->set_synchronous_mode(true);
5175 MockRead reads[] = {
5176 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
5179 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
5180 session_deps_.socket_factory->AddSocketDataProvider(&data);
5182 CreateNetworkSession();
5183 base::WeakPtr<SpdySession> session =
5184 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
5186 session->stream_hi_water_mark_ = 5;
5187 // Low client (odd) ids are fine.
5188 EXPECT_TRUE(session->OnUnknownFrame(3, 0));
5189 // Client id exceeding watermark.
5190 EXPECT_FALSE(session->OnUnknownFrame(9, 0));
5192 session->last_accepted_push_stream_id_ = 6;
5193 // Low server (even) ids are fine.
5194 EXPECT_TRUE(session->OnUnknownFrame(2, 0));
5195 // Server id exceeding last accepted id.
5196 EXPECT_FALSE(session->OnUnknownFrame(8, 0));
5199 TEST(MapFramerErrorToProtocolError, MapsValues) {
5200 CHECK_EQ(
5201 SPDY_ERROR_INVALID_CONTROL_FRAME,
5202 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
5203 CHECK_EQ(
5204 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
5205 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
5206 CHECK_EQ(
5207 SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
5208 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
5209 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
5210 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
5213 TEST(MapFramerErrorToNetError, MapsValue) {
5214 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
5215 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
5216 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5217 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
5218 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5219 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
5220 CHECK_EQ(
5221 ERR_SPDY_FRAME_SIZE_ERROR,
5222 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
5225 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
5226 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
5227 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
5228 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
5229 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
5230 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
5231 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
5232 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY,
5233 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY));
5234 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED,
5235 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED));
5238 TEST(MapNetErrorToGoAwayStatus, MapsValue) {
5239 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
5240 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
5241 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
5242 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
5243 CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
5244 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
5245 CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
5246 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
5247 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
5248 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
5249 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
5252 TEST(CanPoolTest, CanPool) {
5253 // Load a cert that is valid for:
5254 // www.example.org
5255 // mail.example.org
5256 // www.example.com
5258 TransportSecurityState tss;
5259 SSLInfo ssl_info;
5260 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5261 "spdy_pooling.pem");
5263 EXPECT_TRUE(SpdySession::CanPool(
5264 &tss, ssl_info, "www.example.org", "www.example.org"));
5265 EXPECT_TRUE(SpdySession::CanPool(
5266 &tss, ssl_info, "www.example.org", "mail.example.org"));
5267 EXPECT_TRUE(SpdySession::CanPool(
5268 &tss, ssl_info, "www.example.org", "mail.example.com"));
5269 EXPECT_FALSE(SpdySession::CanPool(
5270 &tss, ssl_info, "www.example.org", "mail.google.com"));
5273 TEST(CanPoolTest, CanNotPoolWithCertErrors) {
5274 // Load a cert that is valid for:
5275 // www.example.org
5276 // mail.example.org
5277 // www.example.com
5279 TransportSecurityState tss;
5280 SSLInfo ssl_info;
5281 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5282 "spdy_pooling.pem");
5283 ssl_info.cert_status = CERT_STATUS_REVOKED;
5285 EXPECT_FALSE(SpdySession::CanPool(
5286 &tss, ssl_info, "www.example.org", "mail.example.org"));
5289 TEST(CanPoolTest, CanNotPoolWithClientCerts) {
5290 // Load a cert that is valid for:
5291 // www.example.org
5292 // mail.example.org
5293 // www.example.com
5295 TransportSecurityState tss;
5296 SSLInfo ssl_info;
5297 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5298 "spdy_pooling.pem");
5299 ssl_info.client_cert_sent = true;
5301 EXPECT_FALSE(SpdySession::CanPool(
5302 &tss, ssl_info, "www.example.org", "mail.example.org"));
5305 TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
5306 // Load a cert that is valid for:
5307 // www.example.org
5308 // mail.example.org
5309 // www.example.com
5311 TransportSecurityState tss;
5312 SSLInfo ssl_info;
5313 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5314 "spdy_pooling.pem");
5315 ssl_info.channel_id_sent = true;
5317 EXPECT_TRUE(SpdySession::CanPool(
5318 &tss, ssl_info, "www.example.org", "mail.example.org"));
5319 EXPECT_FALSE(SpdySession::CanPool(
5320 &tss, ssl_info, "www.example.org", "www.example.com"));
5323 TEST(CanPoolTest, CanNotPoolWithBadPins) {
5324 uint8 primary_pin = 1;
5325 uint8 backup_pin = 2;
5326 uint8 bad_pin = 3;
5327 TransportSecurityState tss;
5328 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5330 SSLInfo ssl_info;
5331 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5332 "spdy_pooling.pem");
5333 ssl_info.is_issued_by_known_root = true;
5334 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
5336 EXPECT_FALSE(SpdySession::CanPool(
5337 &tss, ssl_info, "www.example.org", "mail.example.org"));
5340 TEST(CanPoolTest, CanPoolWithAcceptablePins) {
5341 uint8 primary_pin = 1;
5342 uint8 backup_pin = 2;
5343 TransportSecurityState tss;
5344 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5346 SSLInfo ssl_info;
5347 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5348 "spdy_pooling.pem");
5349 ssl_info.is_issued_by_known_root = true;
5350 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
5352 EXPECT_TRUE(SpdySession::CanPool(
5353 &tss, ssl_info, "www.example.org", "mail.example.org"));
5356 } // namespace net