Revert "Reland c91b178b07b0d - Delete dead signin code (SigninGlobalError)"
[chromium-blink-merge.git] / net / spdy / spdy_session_unittest.cc
blob5fd0dc06a81cf158de6cb5fb815db5789c82744c
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 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3393 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3394 // gets sent.
3395 SettingsMap new_settings;
3396 int32 window_size = 1;
3397 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3398 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3400 // Set up the socket so we read a SETTINGS frame that sets
3401 // INITIAL_WINDOW_SIZE.
3402 scoped_ptr<SpdyFrame> settings_frame(
3403 spdy_util_.ConstructSpdySettings(new_settings));
3404 MockRead reads[] = {
3405 CreateMockRead(*settings_frame, 0),
3406 MockRead(ASYNC, ERR_IO_PENDING, 1),
3407 MockRead(ASYNC, 0, 2) // EOF
3410 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3411 MockWrite writes[] = {
3412 CreateMockWrite(*settings_ack, 3),
3415 session_deps_.host_resolver->set_synchronous_mode(true);
3417 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3418 session_deps_.socket_factory->AddSocketDataProvider(&data);
3420 CreateNetworkSession();
3422 base::WeakPtr<SpdySession> session =
3423 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3424 base::WeakPtr<SpdyStream> spdy_stream1 =
3425 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3426 session, test_url_, MEDIUM, BoundNetLog());
3427 ASSERT_TRUE(spdy_stream1.get() != nullptr);
3428 TestCompletionCallback callback1;
3429 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3431 // Process the SETTINGS frame.
3432 base::RunLoop().RunUntilIdle();
3433 EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3434 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3436 // Release the first one, this will allow the second to be created.
3437 spdy_stream1->Cancel();
3438 EXPECT_FALSE(spdy_stream1);
3440 base::WeakPtr<SpdyStream> spdy_stream2 =
3441 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3442 session, test_url_, MEDIUM, BoundNetLog());
3443 ASSERT_TRUE(spdy_stream2.get() != nullptr);
3444 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3445 spdy_stream2->Cancel();
3446 EXPECT_FALSE(spdy_stream2);
3448 EXPECT_TRUE(session);
3449 data.CompleteRead();
3450 base::RunLoop().RunUntilIdle();
3451 EXPECT_FALSE(session);
3454 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3455 // adjust the session receive window size. In addition,
3456 // SpdySession::IncreaseRecvWindowSize should trigger
3457 // sending a WINDOW_UPDATE frame for a large enough delta.
3458 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3459 session_deps_.host_resolver->set_synchronous_mode(true);
3461 const int32 initial_window_size =
3462 SpdySession::GetDefaultInitialWindowSize(GetParam());
3463 const int32 delta_window_size = 100;
3465 MockRead reads[] = {
3466 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
3468 scoped_ptr<SpdyFrame> window_update(spdy_util_.ConstructSpdyWindowUpdate(
3469 kSessionFlowControlStreamId, initial_window_size + delta_window_size));
3470 MockWrite writes[] = {
3471 CreateMockWrite(*window_update, 0),
3473 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3474 session_deps_.socket_factory->AddSocketDataProvider(&data);
3476 CreateNetworkSession();
3477 base::WeakPtr<SpdySession> session =
3478 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3479 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3480 session->flow_control_state());
3482 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3483 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3485 session->IncreaseRecvWindowSize(delta_window_size);
3486 EXPECT_EQ(initial_window_size + delta_window_size,
3487 session->session_recv_window_size_);
3488 EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3490 // Should trigger sending a WINDOW_UPDATE frame.
3491 session->IncreaseRecvWindowSize(initial_window_size);
3492 EXPECT_EQ(initial_window_size + delta_window_size + initial_window_size,
3493 session->session_recv_window_size_);
3494 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3496 base::RunLoop().RunUntilIdle();
3498 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3499 session->in_io_loop_ = true;
3500 session->DecreaseRecvWindowSize(initial_window_size + delta_window_size +
3501 initial_window_size);
3502 session->in_io_loop_ = false;
3503 EXPECT_EQ(0, session->session_recv_window_size_);
3504 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3506 EXPECT_TRUE(session);
3507 data.CompleteRead();
3508 base::RunLoop().RunUntilIdle();
3509 EXPECT_FALSE(session);
3512 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3513 // adjust the session send window size when the "enable_spdy_31" flag
3514 // is set.
3515 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3516 session_deps_.host_resolver->set_synchronous_mode(true);
3518 MockRead reads[] = {
3519 MockRead(SYNCHRONOUS, 0, 0) // EOF
3521 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
3522 session_deps_.socket_factory->AddSocketDataProvider(&data);
3524 CreateNetworkSession();
3525 base::WeakPtr<SpdySession> session =
3526 CreateFakeSpdySession(spdy_session_pool_, key_);
3527 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3528 session->flow_control_state());
3530 const int32 initial_window_size =
3531 SpdySession::GetDefaultInitialWindowSize(GetParam());
3532 const int32 delta_window_size = 100;
3534 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3536 session->IncreaseSendWindowSize(delta_window_size);
3537 EXPECT_EQ(initial_window_size + delta_window_size,
3538 session->session_send_window_size_);
3540 session->DecreaseSendWindowSize(delta_window_size);
3541 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3544 // Incoming data for an inactive stream should not cause the session
3545 // receive window size to decrease, but it should cause the unacked
3546 // bytes to increase.
3547 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3548 session_deps_.host_resolver->set_synchronous_mode(true);
3550 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3551 MockRead reads[] = {
3552 CreateMockRead(*resp, 0),
3553 MockRead(ASYNC, ERR_IO_PENDING, 1),
3554 MockRead(ASYNC, 0, 2) // EOF
3556 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
3557 session_deps_.socket_factory->AddSocketDataProvider(&data);
3559 CreateNetworkSession();
3560 base::WeakPtr<SpdySession> session =
3561 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3562 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3563 session->flow_control_state());
3565 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3566 session->session_recv_window_size_);
3567 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3569 base::RunLoop().RunUntilIdle();
3571 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3572 session->session_recv_window_size_);
3573 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3575 EXPECT_TRUE(session);
3576 data.CompleteRead();
3577 base::RunLoop().RunUntilIdle();
3578 EXPECT_FALSE(session);
3581 // The frame header is not included in flow control, but frame payload
3582 // (including optional pad length and padding) is.
3583 TEST_P(SpdySessionTest, SessionFlowControlPadding) {
3584 // Padding only exists in HTTP/2.
3585 if (GetParam() < kProtoHTTP2MinimumVersion)
3586 return;
3588 session_deps_.host_resolver->set_synchronous_mode(true);
3590 const int padding_length = 42;
3591 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(
3592 1, kUploadData, kUploadDataSize, false, padding_length));
3593 MockRead reads[] = {
3594 CreateMockRead(*resp, 0),
3595 MockRead(ASYNC, ERR_IO_PENDING, 1),
3596 MockRead(ASYNC, 0, 2) // EOF
3598 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
3599 session_deps_.socket_factory->AddSocketDataProvider(&data);
3601 CreateNetworkSession();
3602 base::WeakPtr<SpdySession> session =
3603 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3604 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3605 session->flow_control_state());
3607 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3608 session->session_recv_window_size_);
3609 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3611 base::RunLoop().RunUntilIdle();
3613 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3614 session->session_recv_window_size_);
3615 EXPECT_EQ(kUploadDataSize + padding_length,
3616 session->session_unacked_recv_window_bytes_);
3618 data.CompleteRead();
3619 base::RunLoop().RunUntilIdle();
3620 EXPECT_FALSE(session);
3623 // Peer sends more data than stream level receiving flow control window.
3624 TEST_P(SpdySessionTest, StreamFlowControlTooMuchData) {
3625 const int32 stream_max_recv_window_size = 1024;
3626 const int32 data_frame_size = 2 * stream_max_recv_window_size;
3628 scoped_ptr<SpdyFrame> req(
3629 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
3630 scoped_ptr<SpdyFrame> rst(
3631 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
3632 MockWrite writes[] = {
3633 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
3636 scoped_ptr<SpdyFrame> resp(
3637 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3638 const std::string payload(data_frame_size, 'a');
3639 scoped_ptr<SpdyFrame> data_frame(spdy_util_.ConstructSpdyBodyFrame(
3640 1, payload.data(), data_frame_size, false));
3641 MockRead reads[] = {
3642 CreateMockRead(*resp, 1),
3643 MockRead(ASYNC, ERR_IO_PENDING, 2),
3644 CreateMockRead(*data_frame, 3),
3645 MockRead(ASYNC, ERR_IO_PENDING, 5),
3646 MockRead(ASYNC, 0, 6),
3649 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3650 session_deps_.socket_factory->AddSocketDataProvider(&data);
3651 CreateNetworkSession();
3653 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
3654 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
3655 base::WeakPtr<SpdySession> session =
3656 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3657 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
3659 GURL url(kDefaultURL);
3660 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
3661 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
3662 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3664 test::StreamDelegateDoNothing delegate(spdy_stream);
3665 spdy_stream->SetDelegate(&delegate);
3667 scoped_ptr<SpdyHeaderBlock> headers(
3668 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3669 EXPECT_EQ(ERR_IO_PENDING, spdy_stream->SendRequestHeaders(
3670 headers.Pass(), NO_MORE_DATA_TO_SEND));
3672 // Request and response.
3673 base::RunLoop().RunUntilIdle();
3674 EXPECT_EQ(1u, spdy_stream->stream_id());
3676 // Too large data frame causes flow control error, should close stream.
3677 data.CompleteRead();
3678 base::RunLoop().RunUntilIdle();
3679 EXPECT_FALSE(spdy_stream);
3681 EXPECT_TRUE(session);
3682 data.CompleteRead();
3683 base::RunLoop().RunUntilIdle();
3684 EXPECT_FALSE(session);
3687 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3688 // deltas in the receiving window size when checking incoming frames for flow
3689 // control errors at session level.
3690 TEST_P(SpdySessionTest, SessionFlowControlTooMuchDataTwoDataFrames) {
3691 const int32 session_max_recv_window_size = 500;
3692 const int32 first_data_frame_size = 200;
3693 const int32 second_data_frame_size = 400;
3695 // First data frame should not trigger a WINDOW_UPDATE.
3696 ASSERT_GT(session_max_recv_window_size / 2, first_data_frame_size);
3697 // Second data frame would be fine had there been a WINDOW_UPDATE.
3698 ASSERT_GT(session_max_recv_window_size, second_data_frame_size);
3699 // But in fact, the two data frames together overflow the receiving window at
3700 // session level.
3701 ASSERT_LT(session_max_recv_window_size,
3702 first_data_frame_size + second_data_frame_size);
3704 session_deps_.host_resolver->set_synchronous_mode(true);
3706 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3707 0, GOAWAY_FLOW_CONTROL_ERROR,
3708 "delta_window_size is 400 in DecreaseRecvWindowSize, which is larger "
3709 "than the receive window size of 500"));
3710 MockWrite writes[] = {
3711 CreateMockWrite(*goaway, 4),
3714 const std::string first_data_frame(first_data_frame_size, 'a');
3715 scoped_ptr<SpdyFrame> first(spdy_util_.ConstructSpdyBodyFrame(
3716 1, first_data_frame.data(), first_data_frame_size, false));
3717 const std::string second_data_frame(second_data_frame_size, 'b');
3718 scoped_ptr<SpdyFrame> second(spdy_util_.ConstructSpdyBodyFrame(
3719 1, second_data_frame.data(), second_data_frame_size, false));
3720 MockRead reads[] = {
3721 CreateMockRead(*first, 0),
3722 MockRead(ASYNC, ERR_IO_PENDING, 1),
3723 CreateMockRead(*second, 2),
3724 MockRead(ASYNC, 0, 3),
3726 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3727 session_deps_.socket_factory->AddSocketDataProvider(&data);
3729 CreateNetworkSession();
3730 base::WeakPtr<SpdySession> session =
3731 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3732 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3733 session->flow_control_state());
3734 // Setting session level receiving window size to smaller than initial is not
3735 // possible via SpdySessionPoolPeer.
3736 session->session_recv_window_size_ = session_max_recv_window_size;
3738 // First data frame is immediately consumed and does not trigger
3739 // WINDOW_UPDATE.
3740 base::RunLoop().RunUntilIdle();
3741 EXPECT_EQ(first_data_frame_size, session->session_unacked_recv_window_bytes_);
3742 EXPECT_EQ(session_max_recv_window_size, session->session_recv_window_size_);
3743 EXPECT_EQ(SpdySession::STATE_AVAILABLE, session->availability_state_);
3745 // Second data frame overflows receiving window, causes session to close.
3746 data.CompleteRead();
3747 base::RunLoop().RunUntilIdle();
3748 EXPECT_EQ(SpdySession::STATE_DRAINING, session->availability_state_);
3751 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3752 // deltas in the receiving window size when checking incoming data frames for
3753 // flow control errors at stream level.
3754 TEST_P(SpdySessionTest, StreamFlowControlTooMuchDataTwoDataFrames) {
3755 const int32 stream_max_recv_window_size = 500;
3756 const int32 first_data_frame_size = 200;
3757 const int32 second_data_frame_size = 400;
3759 // First data frame should not trigger a WINDOW_UPDATE.
3760 ASSERT_GT(stream_max_recv_window_size / 2, first_data_frame_size);
3761 // Second data frame would be fine had there been a WINDOW_UPDATE.
3762 ASSERT_GT(stream_max_recv_window_size, second_data_frame_size);
3763 // But in fact, they should overflow the receiving window at stream level.
3764 ASSERT_LT(stream_max_recv_window_size,
3765 first_data_frame_size + second_data_frame_size);
3767 scoped_ptr<SpdyFrame> req(
3768 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
3769 scoped_ptr<SpdyFrame> rst(
3770 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
3771 MockWrite writes[] = {
3772 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 6),
3775 scoped_ptr<SpdyFrame> resp(
3776 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3777 const std::string first_data_frame(first_data_frame_size, 'a');
3778 scoped_ptr<SpdyFrame> first(spdy_util_.ConstructSpdyBodyFrame(
3779 1, first_data_frame.data(), first_data_frame_size, false));
3780 const std::string second_data_frame(second_data_frame_size, 'b');
3781 scoped_ptr<SpdyFrame> second(spdy_util_.ConstructSpdyBodyFrame(
3782 1, second_data_frame.data(), second_data_frame_size, false));
3783 MockRead reads[] = {
3784 CreateMockRead(*resp, 1),
3785 MockRead(ASYNC, ERR_IO_PENDING, 2),
3786 CreateMockRead(*first, 3),
3787 MockRead(ASYNC, ERR_IO_PENDING, 4),
3788 CreateMockRead(*second, 5),
3789 MockRead(ASYNC, ERR_IO_PENDING, 7),
3790 MockRead(ASYNC, 0, 8),
3793 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3794 session_deps_.socket_factory->AddSocketDataProvider(&data);
3796 CreateNetworkSession();
3797 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
3798 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
3800 base::WeakPtr<SpdySession> session =
3801 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3802 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
3804 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
3805 SPDY_REQUEST_RESPONSE_STREAM, session, test_url_, LOWEST, BoundNetLog());
3806 test::StreamDelegateDoNothing delegate(spdy_stream);
3807 spdy_stream->SetDelegate(&delegate);
3809 scoped_ptr<SpdyHeaderBlock> headers(
3810 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3811 EXPECT_EQ(ERR_IO_PENDING, spdy_stream->SendRequestHeaders(
3812 headers.Pass(), NO_MORE_DATA_TO_SEND));
3814 // Request and response.
3815 base::RunLoop().RunUntilIdle();
3816 EXPECT_TRUE(spdy_stream->IsLocallyClosed());
3817 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3819 // First data frame.
3820 data.CompleteRead();
3821 base::RunLoop().RunUntilIdle();
3822 EXPECT_TRUE(spdy_stream->IsLocallyClosed());
3823 EXPECT_EQ(stream_max_recv_window_size - first_data_frame_size,
3824 spdy_stream->recv_window_size());
3826 // Consume first data frame. This does not trigger a WINDOW_UPDATE.
3827 std::string received_data = delegate.TakeReceivedData();
3828 EXPECT_EQ(static_cast<size_t>(first_data_frame_size), received_data.size());
3829 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3831 // Second data frame overflows receiving window, causes the stream to close.
3832 data.CompleteRead();
3833 base::RunLoop().RunUntilIdle();
3834 EXPECT_FALSE(spdy_stream.get());
3836 // RST_STREAM
3837 EXPECT_TRUE(session);
3838 data.CompleteRead();
3839 base::RunLoop().RunUntilIdle();
3840 EXPECT_FALSE(session);
3843 // A delegate that drops any received data.
3844 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3845 public:
3846 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3847 base::StringPiece data)
3848 : StreamDelegateSendImmediate(stream, data) {}
3850 ~DropReceivedDataDelegate() override {}
3852 // Drop any received data.
3853 void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override {}
3856 // Send data back and forth but use a delegate that drops its received
3857 // data. The receive window should still increase to its original
3858 // value, i.e. we shouldn't "leak" receive window bytes.
3859 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3860 const char kStreamUrl[] = "http://www.example.org/";
3862 const int32 msg_data_size = 100;
3863 const std::string msg_data(msg_data_size, 'a');
3865 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3866 kStreamUrl, 1, msg_data_size, MEDIUM, nullptr, 0));
3867 scoped_ptr<SpdyFrame> msg(
3868 spdy_util_.ConstructSpdyBodyFrame(
3869 1, msg_data.data(), msg_data_size, false));
3870 MockWrite writes[] = {
3871 CreateMockWrite(*req, 0),
3872 CreateMockWrite(*msg, 2),
3875 scoped_ptr<SpdyFrame> resp(
3876 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3877 scoped_ptr<SpdyFrame> echo(
3878 spdy_util_.ConstructSpdyBodyFrame(
3879 1, msg_data.data(), msg_data_size, false));
3880 scoped_ptr<SpdyFrame> window_update(
3881 spdy_util_.ConstructSpdyWindowUpdate(
3882 kSessionFlowControlStreamId, msg_data_size));
3883 MockRead reads[] = {
3884 CreateMockRead(*resp, 1),
3885 CreateMockRead(*echo, 3),
3886 MockRead(ASYNC, ERR_IO_PENDING, 4),
3887 MockRead(ASYNC, 0, 5) // EOF
3890 // Create SpdySession and SpdyStream and send the request.
3891 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3892 session_deps_.host_resolver->set_synchronous_mode(true);
3893 session_deps_.socket_factory->AddSocketDataProvider(&data);
3895 CreateNetworkSession();
3897 base::WeakPtr<SpdySession> session =
3898 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3900 GURL url(kStreamUrl);
3901 base::WeakPtr<SpdyStream> stream =
3902 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3903 session, url, MEDIUM, BoundNetLog());
3904 ASSERT_TRUE(stream.get() != nullptr);
3905 EXPECT_EQ(0u, stream->stream_id());
3907 DropReceivedDataDelegate delegate(stream, msg_data);
3908 stream->SetDelegate(&delegate);
3910 scoped_ptr<SpdyHeaderBlock> headers(
3911 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3912 EXPECT_EQ(ERR_IO_PENDING,
3913 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3914 EXPECT_TRUE(stream->HasUrlFromHeaders());
3916 const int32 initial_window_size =
3917 SpdySession::GetDefaultInitialWindowSize(GetParam());
3918 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3919 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3921 base::RunLoop().RunUntilIdle();
3923 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3924 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3926 stream->Close();
3927 EXPECT_FALSE(stream);
3929 EXPECT_EQ(OK, delegate.WaitForClose());
3931 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3932 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3934 data.CompleteRead();
3935 base::RunLoop().RunUntilIdle();
3936 EXPECT_FALSE(session);
3939 // Send data back and forth but close the stream before its data frame
3940 // can be written to the socket. The send window should then increase
3941 // to its original value, i.e. we shouldn't "leak" send window bytes.
3942 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3943 const char kStreamUrl[] = "http://www.example.org/";
3945 const int32 msg_data_size = 100;
3946 const std::string msg_data(msg_data_size, 'a');
3948 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3949 kStreamUrl, 1, msg_data_size, MEDIUM, nullptr, 0));
3950 MockWrite writes[] = {
3951 CreateMockWrite(*req, 0),
3954 scoped_ptr<SpdyFrame> resp(
3955 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3956 MockRead reads[] = {
3957 MockRead(ASYNC, ERR_IO_PENDING, 1),
3958 CreateMockRead(*resp, 2),
3959 MockRead(ASYNC, 0, 3) // EOF
3962 // Create SpdySession and SpdyStream and send the request.
3963 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3964 session_deps_.host_resolver->set_synchronous_mode(true);
3965 session_deps_.socket_factory->AddSocketDataProvider(&data);
3967 CreateNetworkSession();
3969 base::WeakPtr<SpdySession> session =
3970 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3972 GURL url(kStreamUrl);
3973 base::WeakPtr<SpdyStream> stream =
3974 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3975 session, url, MEDIUM, BoundNetLog());
3976 ASSERT_TRUE(stream.get() != nullptr);
3977 EXPECT_EQ(0u, stream->stream_id());
3979 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3980 stream->SetDelegate(&delegate);
3982 scoped_ptr<SpdyHeaderBlock> headers(
3983 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3984 EXPECT_EQ(ERR_IO_PENDING,
3985 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3986 EXPECT_TRUE(stream->HasUrlFromHeaders());
3988 const int32 initial_window_size =
3989 SpdySession::GetDefaultInitialWindowSize(GetParam());
3990 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3992 // Write request.
3993 base::RunLoop().RunUntilIdle();
3995 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3997 // Read response, but do not run the message loop, so that the body is not
3998 // written to the socket.
3999 data.CompleteRead();
4001 EXPECT_EQ(initial_window_size - msg_data_size,
4002 session->session_send_window_size_);
4004 // Closing the stream should increase the session's send window.
4005 stream->Close();
4006 EXPECT_FALSE(stream);
4008 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
4010 EXPECT_EQ(OK, delegate.WaitForClose());
4012 base::RunLoop().RunUntilIdle();
4013 EXPECT_FALSE(session);
4015 EXPECT_TRUE(data.AllWriteDataConsumed());
4016 EXPECT_TRUE(data.AllReadDataConsumed());
4019 // Send data back and forth; the send and receive windows should
4020 // change appropriately.
4021 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
4022 const char kStreamUrl[] = "http://www.example.org/";
4024 const int32 msg_data_size = 100;
4025 const std::string msg_data(msg_data_size, 'a');
4027 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
4028 kStreamUrl, 1, msg_data_size, MEDIUM, nullptr, 0));
4029 scoped_ptr<SpdyFrame> msg(
4030 spdy_util_.ConstructSpdyBodyFrame(
4031 1, msg_data.data(), msg_data_size, false));
4032 MockWrite writes[] = {
4033 CreateMockWrite(*req, 0),
4034 CreateMockWrite(*msg, 2),
4037 scoped_ptr<SpdyFrame> resp(
4038 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4039 scoped_ptr<SpdyFrame> echo(
4040 spdy_util_.ConstructSpdyBodyFrame(
4041 1, msg_data.data(), msg_data_size, false));
4042 scoped_ptr<SpdyFrame> window_update(
4043 spdy_util_.ConstructSpdyWindowUpdate(
4044 kSessionFlowControlStreamId, msg_data_size));
4045 MockRead reads[] = {
4046 CreateMockRead(*resp, 1),
4047 MockRead(ASYNC, ERR_IO_PENDING, 3),
4048 CreateMockRead(*echo, 4),
4049 MockRead(ASYNC, ERR_IO_PENDING, 5),
4050 CreateMockRead(*window_update, 6),
4051 MockRead(ASYNC, ERR_IO_PENDING, 7),
4052 MockRead(ASYNC, 0, 8) // EOF
4055 // Create SpdySession and SpdyStream and send the request.
4056 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4057 session_deps_.host_resolver->set_synchronous_mode(true);
4058 session_deps_.socket_factory->AddSocketDataProvider(&data);
4060 CreateNetworkSession();
4062 base::WeakPtr<SpdySession> session =
4063 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4065 GURL url(kStreamUrl);
4066 base::WeakPtr<SpdyStream> stream =
4067 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
4068 session, url, MEDIUM, BoundNetLog());
4069 ASSERT_TRUE(stream.get() != nullptr);
4070 EXPECT_EQ(0u, stream->stream_id());
4072 test::StreamDelegateSendImmediate delegate(stream, msg_data);
4073 stream->SetDelegate(&delegate);
4075 scoped_ptr<SpdyHeaderBlock> headers(
4076 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
4077 EXPECT_EQ(ERR_IO_PENDING,
4078 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4079 EXPECT_TRUE(stream->HasUrlFromHeaders());
4081 const int32 initial_window_size =
4082 SpdySession::GetDefaultInitialWindowSize(GetParam());
4083 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
4084 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
4085 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
4087 // Send request and message.
4088 base::RunLoop().RunUntilIdle();
4090 EXPECT_EQ(initial_window_size - msg_data_size,
4091 session->session_send_window_size_);
4092 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
4093 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
4095 // Read echo.
4096 data.CompleteRead();
4097 base::RunLoop().RunUntilIdle();
4099 EXPECT_EQ(initial_window_size - msg_data_size,
4100 session->session_send_window_size_);
4101 EXPECT_EQ(initial_window_size - msg_data_size,
4102 session->session_recv_window_size_);
4103 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
4105 // Read window update.
4106 data.CompleteRead();
4107 base::RunLoop().RunUntilIdle();
4109 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
4110 EXPECT_EQ(initial_window_size - msg_data_size,
4111 session->session_recv_window_size_);
4112 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
4114 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
4116 // Draining the delegate's read queue should increase the session's
4117 // receive window.
4118 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
4119 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
4120 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
4122 stream->Close();
4123 EXPECT_FALSE(stream);
4125 EXPECT_EQ(OK, delegate.WaitForClose());
4127 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
4128 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
4129 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
4131 data.CompleteRead();
4132 base::RunLoop().RunUntilIdle();
4133 EXPECT_FALSE(session);
4136 // Given a stall function and an unstall function, runs a test to make
4137 // sure that a stream resumes after unstall.
4138 void SpdySessionTest::RunResumeAfterUnstallTest(
4139 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
4140 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
4141 unstall_function) {
4142 const char kStreamUrl[] = "http://www.example.org/";
4143 GURL url(kStreamUrl);
4145 session_deps_.host_resolver->set_synchronous_mode(true);
4147 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
4148 kStreamUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4149 scoped_ptr<SpdyFrame> body(
4150 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4151 MockWrite writes[] = {
4152 CreateMockWrite(*req, 0),
4153 CreateMockWrite(*body, 1),
4156 scoped_ptr<SpdyFrame> resp(
4157 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4158 scoped_ptr<SpdyFrame> echo(
4159 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4160 MockRead reads[] = {
4161 CreateMockRead(*resp, 2), MockRead(ASYNC, 0, 3) // EOF
4164 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4165 session_deps_.socket_factory->AddSocketDataProvider(&data);
4167 CreateNetworkSession();
4168 base::WeakPtr<SpdySession> session =
4169 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4170 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4171 session->flow_control_state());
4173 base::WeakPtr<SpdyStream> stream =
4174 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4175 session, url, LOWEST, BoundNetLog());
4176 ASSERT_TRUE(stream.get() != nullptr);
4178 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
4179 stream->SetDelegate(&delegate);
4181 EXPECT_FALSE(stream->HasUrlFromHeaders());
4182 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4184 scoped_ptr<SpdyHeaderBlock> headers(
4185 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4186 EXPECT_EQ(ERR_IO_PENDING,
4187 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4188 EXPECT_TRUE(stream->HasUrlFromHeaders());
4189 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
4191 stall_function.Run(session.get(), stream.get());
4193 base::RunLoop().RunUntilIdle();
4195 EXPECT_TRUE(stream->send_stalled_by_flow_control());
4197 unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
4199 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4201 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
4203 EXPECT_TRUE(delegate.send_headers_completed());
4204 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
4205 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
4206 EXPECT_FALSE(session);
4207 EXPECT_TRUE(data.AllWriteDataConsumed());
4210 // Run the resume-after-unstall test with all possible stall and
4211 // unstall sequences.
4213 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
4214 RunResumeAfterUnstallTest(
4215 base::Bind(&SpdySessionTest::StallSessionOnly,
4216 base::Unretained(this)),
4217 base::Bind(&SpdySessionTest::UnstallSessionOnly,
4218 base::Unretained(this)));
4221 // Equivalent to
4222 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4223 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
4224 RunResumeAfterUnstallTest(
4225 base::Bind(&SpdySessionTest::StallStreamOnly,
4226 base::Unretained(this)),
4227 base::Bind(&SpdySessionTest::UnstallStreamOnly,
4228 base::Unretained(this)));
4231 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4232 RunResumeAfterUnstallTest(
4233 base::Bind(&SpdySessionTest::StallSessionStream,
4234 base::Unretained(this)),
4235 base::Bind(&SpdySessionTest::UnstallSessionStream,
4236 base::Unretained(this)));
4239 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4240 RunResumeAfterUnstallTest(
4241 base::Bind(&SpdySessionTest::StallStreamSession,
4242 base::Unretained(this)),
4243 base::Bind(&SpdySessionTest::UnstallSessionStream,
4244 base::Unretained(this)));
4247 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4248 RunResumeAfterUnstallTest(
4249 base::Bind(&SpdySessionTest::StallStreamSession,
4250 base::Unretained(this)),
4251 base::Bind(&SpdySessionTest::UnstallStreamSession,
4252 base::Unretained(this)));
4255 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4256 RunResumeAfterUnstallTest(
4257 base::Bind(&SpdySessionTest::StallSessionStream,
4258 base::Unretained(this)),
4259 base::Bind(&SpdySessionTest::UnstallStreamSession,
4260 base::Unretained(this)));
4263 // Cause a stall by reducing the flow control send window to 0. The
4264 // streams should resume in priority order when that window is then
4265 // increased.
4266 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4267 const char kStreamUrl[] = "http://www.example.org/";
4268 GURL url(kStreamUrl);
4270 session_deps_.host_resolver->set_synchronous_mode(true);
4272 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4273 kStreamUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4274 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4275 kStreamUrl, 3, kBodyDataSize, MEDIUM, nullptr, 0));
4276 scoped_ptr<SpdyFrame> body1(
4277 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4278 scoped_ptr<SpdyFrame> body2(
4279 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4280 MockWrite writes[] = {
4281 CreateMockWrite(*req1, 0),
4282 CreateMockWrite(*req2, 1),
4283 CreateMockWrite(*body2, 2),
4284 CreateMockWrite(*body1, 3),
4287 scoped_ptr<SpdyFrame> resp1(
4288 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4289 scoped_ptr<SpdyFrame> resp2(
4290 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
4291 MockRead reads[] = {
4292 CreateMockRead(*resp1, 4),
4293 CreateMockRead(*resp2, 5),
4294 MockRead(ASYNC, 0, 6) // EOF
4297 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4298 session_deps_.socket_factory->AddSocketDataProvider(&data);
4300 CreateNetworkSession();
4301 base::WeakPtr<SpdySession> session =
4302 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4303 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4304 session->flow_control_state());
4306 base::WeakPtr<SpdyStream> stream1 =
4307 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4308 session, url, LOWEST, BoundNetLog());
4309 ASSERT_TRUE(stream1.get() != nullptr);
4311 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4312 stream1->SetDelegate(&delegate1);
4314 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4316 base::WeakPtr<SpdyStream> stream2 =
4317 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4318 session, url, MEDIUM, BoundNetLog());
4319 ASSERT_TRUE(stream2.get() != nullptr);
4321 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4322 stream2->SetDelegate(&delegate2);
4324 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4326 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4327 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4329 StallSessionSend(session.get());
4331 scoped_ptr<SpdyHeaderBlock> headers1(
4332 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4333 EXPECT_EQ(ERR_IO_PENDING,
4334 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4335 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4336 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4338 base::RunLoop().RunUntilIdle();
4339 EXPECT_EQ(1u, stream1->stream_id());
4340 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4342 scoped_ptr<SpdyHeaderBlock> headers2(
4343 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4344 EXPECT_EQ(ERR_IO_PENDING,
4345 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4346 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4347 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4349 base::RunLoop().RunUntilIdle();
4350 EXPECT_EQ(3u, stream2->stream_id());
4351 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4353 // This should unstall only stream2.
4354 UnstallSessionSend(session.get(), kBodyDataSize);
4356 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4357 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4359 base::RunLoop().RunUntilIdle();
4361 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4362 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4364 // This should then unstall stream1.
4365 UnstallSessionSend(session.get(), kBodyDataSize);
4367 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4368 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4370 base::RunLoop().RunUntilIdle();
4372 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4373 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4375 EXPECT_TRUE(delegate1.send_headers_completed());
4376 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4377 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4379 EXPECT_TRUE(delegate2.send_headers_completed());
4380 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4381 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4383 EXPECT_FALSE(session);
4384 EXPECT_TRUE(data.AllWriteDataConsumed());
4385 EXPECT_TRUE(data.AllReadDataConsumed());
4388 // Delegate that closes a given stream after sending its body.
4389 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4390 public:
4391 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4392 base::StringPiece data)
4393 : StreamDelegateWithBody(stream, data) {}
4395 ~StreamClosingDelegate() override {}
4397 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4398 stream_to_close_ = stream_to_close;
4401 void OnDataSent() override {
4402 test::StreamDelegateWithBody::OnDataSent();
4403 if (stream_to_close_.get()) {
4404 stream_to_close_->Close();
4405 EXPECT_FALSE(stream_to_close_);
4409 private:
4410 base::WeakPtr<SpdyStream> stream_to_close_;
4413 // Cause a stall by reducing the flow control send window to
4414 // 0. Unstalling the session should properly handle deleted streams.
4415 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4416 const char kStreamUrl[] = "http://www.example.org/";
4417 GURL url(kStreamUrl);
4419 session_deps_.host_resolver->set_synchronous_mode(true);
4421 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4422 kStreamUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4423 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4424 kStreamUrl, 3, kBodyDataSize, LOWEST, nullptr, 0));
4425 scoped_ptr<SpdyFrame> req3(spdy_util_.ConstructSpdyPost(
4426 kStreamUrl, 5, kBodyDataSize, LOWEST, nullptr, 0));
4427 scoped_ptr<SpdyFrame> body2(
4428 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4429 MockWrite writes[] = {
4430 CreateMockWrite(*req1, 0),
4431 CreateMockWrite(*req2, 1),
4432 CreateMockWrite(*req3, 2),
4433 CreateMockWrite(*body2, 3),
4436 scoped_ptr<SpdyFrame> resp2(
4437 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
4438 MockRead reads[] = {
4439 CreateMockRead(*resp2, 4),
4440 MockRead(ASYNC, ERR_IO_PENDING, 5),
4441 MockRead(ASYNC, 0, 6) // EOF
4444 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4445 session_deps_.socket_factory->AddSocketDataProvider(&data);
4447 CreateNetworkSession();
4448 base::WeakPtr<SpdySession> session =
4449 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4450 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4451 session->flow_control_state());
4453 base::WeakPtr<SpdyStream> stream1 =
4454 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4455 session, url, LOWEST, BoundNetLog());
4456 ASSERT_TRUE(stream1.get() != nullptr);
4458 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4459 stream1->SetDelegate(&delegate1);
4461 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4463 base::WeakPtr<SpdyStream> stream2 =
4464 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4465 session, url, LOWEST, BoundNetLog());
4466 ASSERT_TRUE(stream2.get() != nullptr);
4468 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4469 stream2->SetDelegate(&delegate2);
4471 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4473 base::WeakPtr<SpdyStream> stream3 =
4474 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4475 session, url, LOWEST, BoundNetLog());
4476 ASSERT_TRUE(stream3.get() != nullptr);
4478 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4479 stream3->SetDelegate(&delegate3);
4481 EXPECT_FALSE(stream3->HasUrlFromHeaders());
4483 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4484 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4485 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4487 StallSessionSend(session.get());
4489 scoped_ptr<SpdyHeaderBlock> headers1(
4490 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4491 EXPECT_EQ(ERR_IO_PENDING,
4492 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4493 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4494 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4496 base::RunLoop().RunUntilIdle();
4497 EXPECT_EQ(1u, stream1->stream_id());
4498 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4500 scoped_ptr<SpdyHeaderBlock> headers2(
4501 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4502 EXPECT_EQ(ERR_IO_PENDING,
4503 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4504 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4505 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4507 base::RunLoop().RunUntilIdle();
4508 EXPECT_EQ(3u, stream2->stream_id());
4509 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4511 scoped_ptr<SpdyHeaderBlock> headers3(
4512 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4513 EXPECT_EQ(ERR_IO_PENDING,
4514 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4515 EXPECT_TRUE(stream3->HasUrlFromHeaders());
4516 EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4518 base::RunLoop().RunUntilIdle();
4519 EXPECT_EQ(5u, stream3->stream_id());
4520 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4522 SpdyStreamId stream_id1 = stream1->stream_id();
4523 SpdyStreamId stream_id2 = stream2->stream_id();
4524 SpdyStreamId stream_id3 = stream3->stream_id();
4526 // Close stream1 preemptively.
4527 session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4528 EXPECT_FALSE(stream1);
4530 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4531 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4532 EXPECT_TRUE(session->IsStreamActive(stream_id3));
4534 // Unstall stream2, which should then close stream3.
4535 delegate2.set_stream_to_close(stream3);
4536 UnstallSessionSend(session.get(), kBodyDataSize);
4538 base::RunLoop().RunUntilIdle();
4539 EXPECT_FALSE(stream3);
4541 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4542 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4543 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4544 EXPECT_FALSE(session->IsStreamActive(stream_id3));
4546 data.CompleteRead();
4547 base::RunLoop().RunUntilIdle();
4548 EXPECT_FALSE(stream2);
4549 EXPECT_FALSE(session);
4551 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4552 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4553 EXPECT_EQ(OK, delegate3.WaitForClose());
4555 EXPECT_TRUE(delegate1.send_headers_completed());
4556 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4558 EXPECT_TRUE(delegate2.send_headers_completed());
4559 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4560 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4562 EXPECT_TRUE(delegate3.send_headers_completed());
4563 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4565 EXPECT_TRUE(data.AllWriteDataConsumed());
4568 // Cause a stall by reducing the flow control send window to
4569 // 0. Unstalling the session should properly handle the session itself
4570 // being closed.
4571 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4572 const char kStreamUrl[] = "http://www.example.org/";
4573 GURL url(kStreamUrl);
4575 session_deps_.host_resolver->set_synchronous_mode(true);
4577 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4578 kStreamUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4579 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4580 kStreamUrl, 3, kBodyDataSize, LOWEST, nullptr, 0));
4581 scoped_ptr<SpdyFrame> body1(
4582 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4583 MockWrite writes[] = {
4584 CreateMockWrite(*req1, 0),
4585 CreateMockWrite(*req2, 1),
4588 MockRead reads[] = {
4589 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
4592 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4593 session_deps_.socket_factory->AddSocketDataProvider(&data);
4595 CreateNetworkSession();
4596 base::WeakPtr<SpdySession> session =
4597 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4598 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4599 session->flow_control_state());
4601 base::WeakPtr<SpdyStream> stream1 =
4602 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4603 session, url, LOWEST, BoundNetLog());
4604 ASSERT_TRUE(stream1.get() != nullptr);
4606 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4607 stream1->SetDelegate(&delegate1);
4609 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4611 base::WeakPtr<SpdyStream> stream2 =
4612 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4613 session, url, LOWEST, BoundNetLog());
4614 ASSERT_TRUE(stream2.get() != nullptr);
4616 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4617 stream2->SetDelegate(&delegate2);
4619 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4621 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4622 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4624 StallSessionSend(session.get());
4626 scoped_ptr<SpdyHeaderBlock> headers1(
4627 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4628 EXPECT_EQ(ERR_IO_PENDING,
4629 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4630 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4631 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4633 base::RunLoop().RunUntilIdle();
4634 EXPECT_EQ(1u, stream1->stream_id());
4635 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4637 scoped_ptr<SpdyHeaderBlock> headers2(
4638 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4639 EXPECT_EQ(ERR_IO_PENDING,
4640 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4641 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4642 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4644 base::RunLoop().RunUntilIdle();
4645 EXPECT_EQ(3u, stream2->stream_id());
4646 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4648 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4650 // Unstall stream1.
4651 UnstallSessionSend(session.get(), kBodyDataSize);
4653 // Close the session (since we can't do it from within the delegate
4654 // method, since it's in the stream's loop).
4655 session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4656 data.CompleteRead();
4657 base::RunLoop().RunUntilIdle();
4658 EXPECT_FALSE(session);
4660 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4662 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4663 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4665 EXPECT_TRUE(delegate1.send_headers_completed());
4666 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4668 EXPECT_TRUE(delegate2.send_headers_completed());
4669 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4671 EXPECT_TRUE(data.AllWriteDataConsumed());
4674 TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4675 scoped_ptr<SpdyFrame> req(
4676 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4677 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4678 0, GOAWAY_FLOW_CONTROL_ERROR,
4679 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4680 "the receive window size of 1"));
4681 MockWrite writes[] = {
4682 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 4),
4685 scoped_ptr<SpdyFrame> resp(
4686 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4687 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4688 MockRead reads[] = {
4689 MockRead(ASYNC, ERR_IO_PENDING, 1),
4690 CreateMockRead(*resp, 2),
4691 CreateMockRead(*body, 3),
4694 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4695 session_deps_.socket_factory->AddSocketDataProvider(&data);
4697 CreateNetworkSession();
4699 base::WeakPtr<SpdySession> session =
4700 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4702 GURL url(kDefaultURL);
4703 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4704 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
4705 ASSERT_TRUE(spdy_stream.get() != nullptr);
4706 test::StreamDelegateDoNothing delegate(spdy_stream);
4707 spdy_stream->SetDelegate(&delegate);
4709 scoped_ptr<SpdyHeaderBlock> headers(
4710 spdy_util_.ConstructGetHeaderBlock(url.spec()));
4711 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4713 // Write request.
4714 base::RunLoop().RunUntilIdle();
4716 // Put session on the edge of overflowing it's recv window.
4717 session->session_recv_window_size_ = 1;
4719 // Read response headers & body. Body overflows the session window, and a
4720 // goaway is written.
4721 data.CompleteRead();
4722 base::RunLoop().RunUntilIdle();
4724 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4725 EXPECT_FALSE(session);
4728 TEST_P(SpdySessionTest, SplitHeaders) {
4729 GURL kStreamUrl("http://www.example.org/foo.dat");
4730 SpdyHeaderBlock headers;
4731 spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4732 headers["alpha"] = "beta";
4734 SpdyHeaderBlock request_headers;
4735 SpdyHeaderBlock response_headers;
4737 SplitPushedHeadersToRequestAndResponse(
4738 headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4740 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4741 std::string alpha_val =
4742 (it == response_headers.end()) ? std::string() : it->second;
4743 EXPECT_EQ("beta", alpha_val);
4745 GURL request_url =
4746 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4747 EXPECT_EQ(kStreamUrl, request_url);
4750 // Regression. Sorta. Push streams and client streams were sharing a single
4751 // limit for a long time.
4752 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4753 SettingsMap new_settings;
4754 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4755 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4756 scoped_ptr<SpdyFrame> settings_frame(
4757 spdy_util_.ConstructSpdySettings(new_settings));
4758 scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4759 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4760 MockRead reads[] = {
4761 CreateMockRead(*settings_frame, 0),
4762 MockRead(ASYNC, ERR_IO_PENDING, 3),
4763 CreateMockRead(*pushed, 4),
4764 MockRead(ASYNC, ERR_IO_PENDING, 5),
4765 MockRead(ASYNC, 0, 6),
4768 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4769 scoped_ptr<SpdyFrame> req(
4770 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4771 MockWrite writes[] = {
4772 CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4775 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4776 session_deps_.socket_factory->AddSocketDataProvider(&data);
4778 CreateNetworkSession();
4780 base::WeakPtr<SpdySession> session =
4781 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4783 // Read the settings frame.
4784 base::RunLoop().RunUntilIdle();
4786 GURL url1(kDefaultURL);
4787 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4788 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4789 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4790 EXPECT_EQ(0u, spdy_stream1->stream_id());
4791 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4792 spdy_stream1->SetDelegate(&delegate1);
4794 EXPECT_EQ(0u, session->num_active_streams());
4795 EXPECT_EQ(1u, session->num_created_streams());
4796 EXPECT_EQ(0u, session->num_pushed_streams());
4797 EXPECT_EQ(0u, session->num_active_pushed_streams());
4799 scoped_ptr<SpdyHeaderBlock> headers(
4800 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4801 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4802 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4804 // Run until 1st stream is activated.
4805 EXPECT_EQ(0u, delegate1.stream_id());
4806 base::RunLoop().RunUntilIdle();
4807 EXPECT_EQ(1u, delegate1.stream_id());
4808 EXPECT_EQ(1u, session->num_active_streams());
4809 EXPECT_EQ(0u, session->num_created_streams());
4810 EXPECT_EQ(0u, session->num_pushed_streams());
4811 EXPECT_EQ(0u, session->num_active_pushed_streams());
4813 // Run until pushed stream is created.
4814 data.CompleteRead();
4815 base::RunLoop().RunUntilIdle();
4816 EXPECT_EQ(2u, session->num_active_streams());
4817 EXPECT_EQ(0u, session->num_created_streams());
4818 EXPECT_EQ(1u, session->num_pushed_streams());
4819 EXPECT_EQ(1u, session->num_active_pushed_streams());
4821 // Second stream should not be stalled, although we have 2 active streams, but
4822 // one of them is push stream and should not be taken into account when we
4823 // create streams on the client.
4824 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4825 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4826 EXPECT_TRUE(spdy_stream2);
4827 EXPECT_EQ(2u, session->num_active_streams());
4828 EXPECT_EQ(1u, session->num_created_streams());
4829 EXPECT_EQ(1u, session->num_pushed_streams());
4830 EXPECT_EQ(1u, session->num_active_pushed_streams());
4832 // Read EOF.
4833 data.CompleteRead();
4834 base::RunLoop().RunUntilIdle();
4835 EXPECT_FALSE(session);
4838 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4839 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4840 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4841 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4842 nullptr, 0, 4, 1, "http://www.example.org/b.dat"));
4843 MockRead reads[] = {
4844 MockRead(ASYNC, ERR_IO_PENDING, 1),
4845 CreateMockRead(*push_a, 2),
4846 MockRead(ASYNC, ERR_IO_PENDING, 3),
4847 CreateMockRead(*push_b, 4),
4848 MockRead(ASYNC, ERR_IO_PENDING, 6),
4849 MockRead(ASYNC, 0, 7),
4852 scoped_ptr<SpdyFrame> req(
4853 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4854 scoped_ptr<SpdyFrame> rst(
4855 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4856 MockWrite writes[] = {
4857 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
4860 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4861 session_deps_.socket_factory->AddSocketDataProvider(&data);
4863 CreateNetworkSession();
4865 base::WeakPtr<SpdySession> session =
4866 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4867 session->set_max_concurrent_pushed_streams(1);
4869 GURL url1(kDefaultURL);
4870 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4871 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4872 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4873 EXPECT_EQ(0u, spdy_stream1->stream_id());
4874 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4875 spdy_stream1->SetDelegate(&delegate1);
4877 EXPECT_EQ(0u, session->num_active_streams());
4878 EXPECT_EQ(1u, session->num_created_streams());
4879 EXPECT_EQ(0u, session->num_pushed_streams());
4880 EXPECT_EQ(0u, session->num_active_pushed_streams());
4882 scoped_ptr<SpdyHeaderBlock> headers(
4883 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4884 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4885 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4887 // Run until 1st stream is activated.
4888 EXPECT_EQ(0u, delegate1.stream_id());
4889 base::RunLoop().RunUntilIdle();
4890 EXPECT_EQ(1u, delegate1.stream_id());
4891 EXPECT_EQ(1u, session->num_active_streams());
4892 EXPECT_EQ(0u, session->num_created_streams());
4893 EXPECT_EQ(0u, session->num_pushed_streams());
4894 EXPECT_EQ(0u, session->num_active_pushed_streams());
4896 // Run until pushed stream is created.
4897 data.CompleteRead();
4898 base::RunLoop().RunUntilIdle();
4899 EXPECT_EQ(2u, session->num_active_streams());
4900 EXPECT_EQ(0u, session->num_created_streams());
4901 EXPECT_EQ(1u, session->num_pushed_streams());
4902 EXPECT_EQ(1u, session->num_active_pushed_streams());
4904 // Reset incoming pushed stream.
4905 data.CompleteRead();
4906 base::RunLoop().RunUntilIdle();
4907 EXPECT_EQ(2u, session->num_active_streams());
4908 EXPECT_EQ(0u, session->num_created_streams());
4909 EXPECT_EQ(1u, session->num_pushed_streams());
4910 EXPECT_EQ(1u, session->num_active_pushed_streams());
4912 // Read EOF.
4913 data.CompleteRead();
4914 base::RunLoop().RunUntilIdle();
4915 EXPECT_FALSE(session);
4918 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4919 // Streams in reserved remote state exist only in HTTP/2.
4920 if (spdy_util_.spdy_version() < HTTP2)
4921 return;
4923 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4924 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4925 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4926 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/b.dat",
4927 push_headers.get());
4928 scoped_ptr<SpdyFrame> push_b(
4929 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4930 scoped_ptr<SpdyFrame> headers_b(
4931 spdy_util_.ConstructSpdyPushHeaders(4, nullptr, 0));
4932 MockRead reads[] = {
4933 MockRead(ASYNC, ERR_IO_PENDING, 1),
4934 CreateMockRead(*push_a, 2),
4935 MockRead(ASYNC, ERR_IO_PENDING, 3),
4936 CreateMockRead(*push_b, 4),
4937 MockRead(ASYNC, ERR_IO_PENDING, 5),
4938 CreateMockRead(*headers_b, 6),
4939 MockRead(ASYNC, ERR_IO_PENDING, 8),
4940 MockRead(ASYNC, 0, 9),
4943 scoped_ptr<SpdyFrame> req(
4944 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4945 scoped_ptr<SpdyFrame> rst(
4946 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4947 MockWrite writes[] = {
4948 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 7),
4951 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4952 session_deps_.socket_factory->AddSocketDataProvider(&data);
4954 CreateNetworkSession();
4956 base::WeakPtr<SpdySession> session =
4957 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4958 session->set_max_concurrent_pushed_streams(1);
4960 GURL url1(kDefaultURL);
4961 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4962 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4963 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4964 EXPECT_EQ(0u, spdy_stream1->stream_id());
4965 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4966 spdy_stream1->SetDelegate(&delegate1);
4968 EXPECT_EQ(0u, session->num_active_streams());
4969 EXPECT_EQ(1u, session->num_created_streams());
4970 EXPECT_EQ(0u, session->num_pushed_streams());
4971 EXPECT_EQ(0u, session->num_active_pushed_streams());
4973 scoped_ptr<SpdyHeaderBlock> headers(
4974 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4975 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4976 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4978 // Run until 1st stream is activated.
4979 EXPECT_EQ(0u, delegate1.stream_id());
4980 base::RunLoop().RunUntilIdle();
4981 EXPECT_EQ(1u, delegate1.stream_id());
4982 EXPECT_EQ(1u, session->num_active_streams());
4983 EXPECT_EQ(0u, session->num_created_streams());
4984 EXPECT_EQ(0u, session->num_pushed_streams());
4985 EXPECT_EQ(0u, session->num_active_pushed_streams());
4987 // Run until pushed stream is created.
4988 data.CompleteRead();
4989 base::RunLoop().RunUntilIdle();
4990 EXPECT_EQ(2u, session->num_active_streams());
4991 EXPECT_EQ(0u, session->num_created_streams());
4992 EXPECT_EQ(1u, session->num_pushed_streams());
4993 EXPECT_EQ(1u, session->num_active_pushed_streams());
4995 // Accept promised stream. It should not count towards pushed stream limit.
4996 data.CompleteRead();
4997 base::RunLoop().RunUntilIdle();
4998 EXPECT_EQ(3u, session->num_active_streams());
4999 EXPECT_EQ(0u, session->num_created_streams());
5000 EXPECT_EQ(2u, session->num_pushed_streams());
5001 EXPECT_EQ(1u, session->num_active_pushed_streams());
5003 // Reset last pushed stream upon headers reception as it is going to be 2nd,
5004 // while we accept only one.
5005 data.CompleteRead();
5006 base::RunLoop().RunUntilIdle();
5007 EXPECT_EQ(2u, session->num_active_streams());
5008 EXPECT_EQ(0u, session->num_created_streams());
5009 EXPECT_EQ(1u, session->num_pushed_streams());
5010 EXPECT_EQ(1u, session->num_active_pushed_streams());
5012 // Read EOF.
5013 data.CompleteRead();
5014 base::RunLoop().RunUntilIdle();
5015 EXPECT_FALSE(session);
5018 TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
5019 // Streams in reserved remote state exist only in HTTP/2.
5020 if (spdy_util_.spdy_version() < HTTP2)
5021 return;
5023 const char kPushedUrl[] = "http://www.example.org/a.dat";
5024 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
5025 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
5026 scoped_ptr<SpdyFrame> push_promise(
5027 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
5028 scoped_ptr<SpdyFrame> headers_frame(
5029 spdy_util_.ConstructSpdyPushHeaders(2, nullptr, 0));
5030 MockRead reads[] = {
5031 MockRead(ASYNC, ERR_IO_PENDING, 1),
5032 CreateMockRead(*push_promise, 2),
5033 MockRead(ASYNC, ERR_IO_PENDING, 3),
5034 CreateMockRead(*headers_frame, 4),
5035 MockRead(ASYNC, ERR_IO_PENDING, 6),
5036 MockRead(ASYNC, 0, 7),
5039 scoped_ptr<SpdyFrame> req(
5040 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
5041 scoped_ptr<SpdyFrame> rst(
5042 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
5043 MockWrite writes[] = {
5044 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
5047 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
5048 session_deps_.socket_factory->AddSocketDataProvider(&data);
5050 CreateNetworkSession();
5052 base::WeakPtr<SpdySession> session =
5053 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
5055 GURL url1(kDefaultURL);
5056 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
5057 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
5058 ASSERT_TRUE(spdy_stream1.get() != nullptr);
5059 EXPECT_EQ(0u, spdy_stream1->stream_id());
5060 test::StreamDelegateDoNothing delegate1(spdy_stream1);
5061 spdy_stream1->SetDelegate(&delegate1);
5063 EXPECT_EQ(0u, session->num_active_streams());
5064 EXPECT_EQ(1u, session->num_created_streams());
5065 EXPECT_EQ(0u, session->num_pushed_streams());
5066 EXPECT_EQ(0u, session->num_active_pushed_streams());
5068 scoped_ptr<SpdyHeaderBlock> headers(
5069 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
5070 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
5071 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
5073 // Run until 1st stream is activated.
5074 EXPECT_EQ(0u, delegate1.stream_id());
5075 base::RunLoop().RunUntilIdle();
5076 EXPECT_EQ(1u, delegate1.stream_id());
5077 EXPECT_EQ(1u, session->num_active_streams());
5078 EXPECT_EQ(0u, session->num_created_streams());
5079 EXPECT_EQ(0u, session->num_pushed_streams());
5080 EXPECT_EQ(0u, session->num_active_pushed_streams());
5082 // Run until pushed stream is created.
5083 data.CompleteRead();
5084 base::RunLoop().RunUntilIdle();
5085 EXPECT_EQ(2u, session->num_active_streams());
5086 EXPECT_EQ(0u, session->num_created_streams());
5087 EXPECT_EQ(1u, session->num_pushed_streams());
5088 EXPECT_EQ(0u, session->num_active_pushed_streams());
5090 base::WeakPtr<SpdyStream> pushed_stream;
5091 int rv =
5092 session->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
5093 ASSERT_EQ(OK, rv);
5094 ASSERT_TRUE(pushed_stream.get() != nullptr);
5095 test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
5096 pushed_stream->SetDelegate(&delegate2);
5098 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
5099 // that all our counters are in consistent state.
5100 data.CompleteRead();
5101 base::RunLoop().RunUntilIdle();
5102 EXPECT_EQ(1u, session->num_active_streams());
5103 EXPECT_EQ(0u, session->num_created_streams());
5104 EXPECT_EQ(0u, session->num_pushed_streams());
5105 EXPECT_EQ(0u, session->num_active_pushed_streams());
5107 // Read EOF.
5108 data.CompleteRead();
5109 base::RunLoop().RunUntilIdle();
5110 EXPECT_TRUE(data.AllWriteDataConsumed());
5111 EXPECT_TRUE(data.AllReadDataConsumed());
5114 TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
5115 session_deps_.host_resolver->set_synchronous_mode(true);
5117 MockRead reads[] = {
5118 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
5121 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
5122 session_deps_.socket_factory->AddSocketDataProvider(&data);
5124 CreateNetworkSession();
5125 base::WeakPtr<SpdySession> session =
5126 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
5128 session->stream_hi_water_mark_ = 5;
5129 // Low client (odd) ids are fine.
5130 EXPECT_TRUE(session->OnUnknownFrame(3, 0));
5131 // Client id exceeding watermark.
5132 EXPECT_FALSE(session->OnUnknownFrame(9, 0));
5134 session->last_accepted_push_stream_id_ = 6;
5135 // Low server (even) ids are fine.
5136 EXPECT_TRUE(session->OnUnknownFrame(2, 0));
5137 // Server id exceeding last accepted id.
5138 EXPECT_FALSE(session->OnUnknownFrame(8, 0));
5141 TEST(MapFramerErrorToProtocolError, MapsValues) {
5142 CHECK_EQ(
5143 SPDY_ERROR_INVALID_CONTROL_FRAME,
5144 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
5145 CHECK_EQ(
5146 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
5147 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
5148 CHECK_EQ(
5149 SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
5150 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
5151 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
5152 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
5155 TEST(MapFramerErrorToNetError, MapsValue) {
5156 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
5157 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
5158 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5159 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
5160 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5161 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
5162 CHECK_EQ(
5163 ERR_SPDY_FRAME_SIZE_ERROR,
5164 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
5167 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
5168 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
5169 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
5170 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
5171 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
5172 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
5173 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
5174 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY,
5175 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY));
5176 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED,
5177 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED));
5180 TEST(MapNetErrorToGoAwayStatus, MapsValue) {
5181 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
5182 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
5183 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
5184 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
5185 CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
5186 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
5187 CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
5188 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
5189 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
5190 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
5191 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
5194 TEST(CanPoolTest, CanPool) {
5195 // Load a cert that is valid for:
5196 // www.example.org
5197 // mail.example.org
5198 // www.example.com
5200 TransportSecurityState tss;
5201 SSLInfo ssl_info;
5202 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5203 "spdy_pooling.pem");
5205 EXPECT_TRUE(SpdySession::CanPool(
5206 &tss, ssl_info, "www.example.org", "www.example.org"));
5207 EXPECT_TRUE(SpdySession::CanPool(
5208 &tss, ssl_info, "www.example.org", "mail.example.org"));
5209 EXPECT_TRUE(SpdySession::CanPool(
5210 &tss, ssl_info, "www.example.org", "mail.example.com"));
5211 EXPECT_FALSE(SpdySession::CanPool(
5212 &tss, ssl_info, "www.example.org", "mail.google.com"));
5215 TEST(CanPoolTest, CanNotPoolWithCertErrors) {
5216 // Load a cert that is valid for:
5217 // www.example.org
5218 // mail.example.org
5219 // www.example.com
5221 TransportSecurityState tss;
5222 SSLInfo ssl_info;
5223 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5224 "spdy_pooling.pem");
5225 ssl_info.cert_status = CERT_STATUS_REVOKED;
5227 EXPECT_FALSE(SpdySession::CanPool(
5228 &tss, ssl_info, "www.example.org", "mail.example.org"));
5231 TEST(CanPoolTest, CanNotPoolWithClientCerts) {
5232 // Load a cert that is valid for:
5233 // www.example.org
5234 // mail.example.org
5235 // www.example.com
5237 TransportSecurityState tss;
5238 SSLInfo ssl_info;
5239 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5240 "spdy_pooling.pem");
5241 ssl_info.client_cert_sent = true;
5243 EXPECT_FALSE(SpdySession::CanPool(
5244 &tss, ssl_info, "www.example.org", "mail.example.org"));
5247 TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
5248 // Load a cert that is valid for:
5249 // www.example.org
5250 // mail.example.org
5251 // www.example.com
5253 TransportSecurityState tss;
5254 SSLInfo ssl_info;
5255 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5256 "spdy_pooling.pem");
5257 ssl_info.channel_id_sent = true;
5259 EXPECT_TRUE(SpdySession::CanPool(
5260 &tss, ssl_info, "www.example.org", "mail.example.org"));
5261 EXPECT_FALSE(SpdySession::CanPool(
5262 &tss, ssl_info, "www.example.org", "www.example.com"));
5265 TEST(CanPoolTest, CanNotPoolWithBadPins) {
5266 uint8 primary_pin = 1;
5267 uint8 backup_pin = 2;
5268 uint8 bad_pin = 3;
5269 TransportSecurityState tss;
5270 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5272 SSLInfo ssl_info;
5273 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5274 "spdy_pooling.pem");
5275 ssl_info.is_issued_by_known_root = true;
5276 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
5278 EXPECT_FALSE(SpdySession::CanPool(
5279 &tss, ssl_info, "www.example.org", "mail.example.org"));
5282 TEST(CanPoolTest, CanPoolWithAcceptablePins) {
5283 uint8 primary_pin = 1;
5284 uint8 backup_pin = 2;
5285 TransportSecurityState tss;
5286 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5288 SSLInfo ssl_info;
5289 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5290 "spdy_pooling.pem");
5291 ssl_info.is_issued_by_known_root = true;
5292 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
5294 EXPECT_TRUE(SpdySession::CanPool(
5295 &tss, ssl_info, "www.example.org", "mail.example.org"));
5298 } // namespace net