Revert "Fix broken channel icon in chrome://help on CrOS" and try again
[chromium-blink-merge.git] / net / spdy / spdy_session_unittest.cc
blob7a9ce45ad2ba0628f097c43d54f26e5a29460aa2
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(SpdyStream* stream) { StallSessionSend(); }
66 void StallStreamOnly(SpdyStream* stream) { StallStreamSend(stream); }
68 void StallSessionStream(SpdyStream* stream) {
69 StallSessionSend();
70 StallStreamSend(stream);
73 void StallStreamSession(SpdyStream* stream) {
74 StallStreamSend(stream);
75 StallSessionSend();
78 void UnstallSessionOnly(SpdyStream* stream, int32 delta_window_size) {
79 UnstallSessionSend(delta_window_size);
82 void UnstallStreamOnly(SpdyStream* stream, int32 delta_window_size) {
83 UnstallStreamSend(stream, delta_window_size);
86 void UnstallSessionStream(SpdyStream* stream, int32 delta_window_size) {
87 UnstallSessionSend(delta_window_size);
88 UnstallStreamSend(stream, delta_window_size);
91 void UnstallStreamSession(SpdyStream* stream, int32 delta_window_size) {
92 UnstallStreamSend(stream, delta_window_size);
93 UnstallSessionSend(delta_window_size);
96 protected:
97 SpdySessionTest()
98 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
99 HttpNetworkSession::NORMAL_SOCKET_POOL)),
100 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
101 HttpNetworkSession::NORMAL_SOCKET_POOL)),
102 spdy_util_(GetParam()),
103 session_deps_(GetParam()),
104 spdy_session_pool_(nullptr),
105 test_url_(kTestUrl),
106 test_host_port_pair_(kTestHost, kTestPort),
107 key_(test_host_port_pair_,
108 ProxyServer::Direct(),
109 PRIVACY_MODE_DISABLED) {}
111 virtual ~SpdySessionTest() {
112 // Important to restore the per-pool limit first, since the pool limit must
113 // always be greater than group limit, and the tests reduce both limits.
114 ClientSocketPoolManager::set_max_sockets_per_pool(
115 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
116 ClientSocketPoolManager::set_max_sockets_per_group(
117 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
120 void SetUp() override {
121 g_time_delta = base::TimeDelta();
122 session_deps_.net_log = log_.bound().net_log();
125 void CreateNetworkSession() {
126 DCHECK(!http_session_);
127 DCHECK(!spdy_session_pool_);
128 http_session_ =
129 SpdySessionDependencies::SpdyCreateSession(&session_deps_);
130 spdy_session_pool_ = http_session_->spdy_session_pool();
133 void CreateInsecureSpdySession() {
134 DCHECK(!session_);
135 session_ =
136 ::net::CreateInsecureSpdySession(http_session_, key_, log_.bound());
139 void StallSessionSend() {
140 // Reduce the send window size to 0 to stall.
141 while (session_->session_send_window_size_ > 0) {
142 session_->DecreaseSendWindowSize(std::min(
143 kMaxSpdyFrameChunkSize, session_->session_send_window_size_));
147 void UnstallSessionSend(int32 delta_window_size) {
148 session_->IncreaseSendWindowSize(delta_window_size);
151 void StallStreamSend(SpdyStream* stream) {
152 // Reduce the send window size to 0 to stall.
153 while (stream->send_window_size() > 0) {
154 stream->DecreaseSendWindowSize(
155 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
159 void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) {
160 stream->IncreaseSendWindowSize(delta_window_size);
163 void RunResumeAfterUnstallTest(
164 const base::Callback<void(SpdyStream*)>& stall_function,
165 const base::Callback<void(SpdyStream*, int32)>& unstall_function);
167 // Original socket limits. Some tests set these. Safest to always restore
168 // them once each test has been run.
169 int old_max_group_sockets_;
170 int old_max_pool_sockets_;
172 SpdyTestUtil spdy_util_;
173 SpdySessionDependencies session_deps_;
174 scoped_refptr<HttpNetworkSession> http_session_;
175 base::WeakPtr<SpdySession> session_;
176 SpdySessionPool* spdy_session_pool_;
177 GURL test_url_;
178 HostPortPair test_host_port_pair_;
179 SpdySessionKey key_;
180 BoundTestNetLog log_;
183 INSTANTIATE_TEST_CASE_P(NextProto,
184 SpdySessionTest,
185 testing::Values(kProtoSPDY31,
186 kProtoHTTP2));
188 // Try to create a SPDY session that will fail during
189 // initialization. Nothing should blow up.
190 TEST_P(SpdySessionTest, InitialReadError) {
191 CreateNetworkSession();
193 session_ = TryCreateFakeSpdySessionExpectingFailure(spdy_session_pool_, key_,
194 ERR_CONNECTION_CLOSED);
195 EXPECT_TRUE(session_);
196 // Flush the read.
197 base::RunLoop().RunUntilIdle();
198 EXPECT_FALSE(session_);
201 namespace {
203 // A helper class that vends a callback that, when fired, destroys a
204 // given SpdyStreamRequest.
205 class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
206 public:
207 StreamRequestDestroyingCallback() {}
209 ~StreamRequestDestroyingCallback() override {}
211 void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) {
212 request_ = request.Pass();
215 CompletionCallback MakeCallback() {
216 return base::Bind(&StreamRequestDestroyingCallback::OnComplete,
217 base::Unretained(this));
220 private:
221 void OnComplete(int result) {
222 request_.reset();
223 SetResult(result);
226 scoped_ptr<SpdyStreamRequest> request_;
229 } // namespace
231 // Request kInitialMaxConcurrentStreams streams. Request two more
232 // streams, but have the callback for one destroy the second stream
233 // request. Close the session. Nothing should blow up. This is a
234 // regression test for http://crbug.com/250841 .
235 TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
236 session_deps_.host_resolver->set_synchronous_mode(true);
238 MockRead reads[] = {MockRead(ASYNC, 0, 0), };
240 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
241 session_deps_.socket_factory->AddSocketDataProvider(&data);
243 CreateNetworkSession();
244 CreateInsecureSpdySession();
246 // Create the maximum number of concurrent streams.
247 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
248 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
249 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
250 ASSERT_TRUE(spdy_stream != nullptr);
253 SpdyStreamRequest request1;
254 scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest);
256 StreamRequestDestroyingCallback callback1;
257 ASSERT_EQ(
258 ERR_IO_PENDING,
259 request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
260 MEDIUM, BoundNetLog(), callback1.MakeCallback()));
262 // |callback2| is never called.
263 TestCompletionCallback callback2;
264 ASSERT_EQ(ERR_IO_PENDING, request2->StartRequest(
265 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
266 MEDIUM, BoundNetLog(), callback2.callback()));
268 callback1.SetRequestToDestroy(request2.Pass());
270 session_->CloseSessionOnError(ERR_ABORTED, "Aborting session");
272 EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
275 // A session receiving a GOAWAY frame with no active streams should close.
276 TEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
277 session_deps_.host_resolver->set_synchronous_mode(true);
279 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
280 MockRead reads[] = {
281 CreateMockRead(*goaway, 0),
283 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
284 session_deps_.socket_factory->AddSocketDataProvider(&data);
286 CreateNetworkSession();
287 CreateInsecureSpdySession();
289 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
291 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
293 // Read and process the GOAWAY frame.
294 base::RunLoop().RunUntilIdle();
295 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
296 EXPECT_FALSE(session_);
299 // A session receiving a GOAWAY frame immediately with no active
300 // streams should then close.
301 TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
302 session_deps_.host_resolver->set_synchronous_mode(true);
304 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
305 MockRead reads[] = {
306 CreateMockRead(*goaway, 0, SYNCHRONOUS), MockRead(ASYNC, 0, 1) // EOF
308 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
309 session_deps_.socket_factory->AddSocketDataProvider(&data);
311 CreateNetworkSession();
313 session_ = TryCreateInsecureSpdySessionExpectingFailure(
314 http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
315 base::RunLoop().RunUntilIdle();
317 EXPECT_FALSE(session_);
318 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
319 EXPECT_FALSE(data.AllReadDataConsumed());
322 // A session receiving a GOAWAY frame with active streams should close
323 // when the last active stream is closed.
324 TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
325 session_deps_.host_resolver->set_synchronous_mode(true);
327 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
328 MockRead reads[] = {
329 MockRead(ASYNC, ERR_IO_PENDING, 2),
330 CreateMockRead(*goaway, 3),
331 MockRead(ASYNC, ERR_IO_PENDING, 4),
332 MockRead(ASYNC, 0, 5) // EOF
334 scoped_ptr<SpdyFrame> req1(
335 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
336 scoped_ptr<SpdyFrame> req2(
337 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
338 MockWrite writes[] = {
339 CreateMockWrite(*req1, 0),
340 CreateMockWrite(*req2, 1),
342 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
343 session_deps_.socket_factory->AddSocketDataProvider(&data);
345 CreateNetworkSession();
346 CreateInsecureSpdySession();
348 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
350 GURL url(kDefaultURL);
351 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
352 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
353 test::StreamDelegateDoNothing delegate1(spdy_stream1);
354 spdy_stream1->SetDelegate(&delegate1);
356 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
357 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
358 test::StreamDelegateDoNothing delegate2(spdy_stream2);
359 spdy_stream2->SetDelegate(&delegate2);
361 scoped_ptr<SpdyHeaderBlock> headers(
362 spdy_util_.ConstructGetHeaderBlock(url.spec()));
363 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
365 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
366 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
367 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
368 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
370 base::RunLoop().RunUntilIdle();
372 EXPECT_EQ(1u, spdy_stream1->stream_id());
373 EXPECT_EQ(3u, spdy_stream2->stream_id());
375 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
377 // Read and process the GOAWAY frame.
378 data.CompleteRead();
379 base::RunLoop().RunUntilIdle();
381 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
383 EXPECT_FALSE(session_->IsStreamActive(3));
384 EXPECT_FALSE(spdy_stream2);
385 EXPECT_TRUE(session_->IsStreamActive(1));
387 EXPECT_TRUE(session_->IsGoingAway());
389 // Should close the session.
390 spdy_stream1->Close();
391 EXPECT_FALSE(spdy_stream1);
393 EXPECT_TRUE(session_);
394 data.CompleteRead();
395 base::RunLoop().RunUntilIdle();
396 EXPECT_FALSE(session_);
399 // Have a session receive two GOAWAY frames, with the last one causing
400 // the last active stream to be closed. The session should then be
401 // closed after the second GOAWAY frame.
402 TEST_P(SpdySessionTest, GoAwayTwice) {
403 session_deps_.host_resolver->set_synchronous_mode(true);
405 scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
406 scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
407 MockRead reads[] = {
408 MockRead(ASYNC, ERR_IO_PENDING, 2),
409 CreateMockRead(*goaway1, 3),
410 MockRead(ASYNC, ERR_IO_PENDING, 4),
411 CreateMockRead(*goaway2, 5),
412 MockRead(ASYNC, ERR_IO_PENDING, 6),
413 MockRead(ASYNC, 0, 7) // EOF
415 scoped_ptr<SpdyFrame> req1(
416 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
417 scoped_ptr<SpdyFrame> req2(
418 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
419 MockWrite writes[] = {
420 CreateMockWrite(*req1, 0),
421 CreateMockWrite(*req2, 1),
423 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
424 session_deps_.socket_factory->AddSocketDataProvider(&data);
426 CreateNetworkSession();
427 CreateInsecureSpdySession();
429 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
431 GURL url(kDefaultURL);
432 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
433 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
434 test::StreamDelegateDoNothing delegate1(spdy_stream1);
435 spdy_stream1->SetDelegate(&delegate1);
437 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
438 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
439 test::StreamDelegateDoNothing delegate2(spdy_stream2);
440 spdy_stream2->SetDelegate(&delegate2);
442 scoped_ptr<SpdyHeaderBlock> headers(
443 spdy_util_.ConstructGetHeaderBlock(url.spec()));
444 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
446 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
447 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
448 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
449 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
451 base::RunLoop().RunUntilIdle();
453 EXPECT_EQ(1u, spdy_stream1->stream_id());
454 EXPECT_EQ(3u, spdy_stream2->stream_id());
456 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
458 // Read and process the first GOAWAY frame.
459 data.CompleteRead();
460 base::RunLoop().RunUntilIdle();
462 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
464 EXPECT_FALSE(session_->IsStreamActive(3));
465 EXPECT_FALSE(spdy_stream2);
466 EXPECT_TRUE(session_->IsStreamActive(1));
467 EXPECT_TRUE(session_->IsGoingAway());
469 // Read and process the second GOAWAY frame, which should close the
470 // session.
471 data.CompleteRead();
472 base::RunLoop().RunUntilIdle();
473 EXPECT_FALSE(session_);
476 // Have a session with active streams receive a GOAWAY frame and then
477 // close it. It should handle the close properly (i.e., not try to
478 // make itself unavailable in its pool twice).
479 TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
480 session_deps_.host_resolver->set_synchronous_mode(true);
482 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
483 MockRead reads[] = {
484 MockRead(ASYNC, ERR_IO_PENDING, 2),
485 CreateMockRead(*goaway, 3),
486 MockRead(ASYNC, ERR_IO_PENDING, 4),
487 MockRead(ASYNC, 0, 5) // EOF
489 scoped_ptr<SpdyFrame> req1(
490 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
491 scoped_ptr<SpdyFrame> req2(
492 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
493 MockWrite writes[] = {
494 CreateMockWrite(*req1, 0),
495 CreateMockWrite(*req2, 1),
497 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
498 session_deps_.socket_factory->AddSocketDataProvider(&data);
500 CreateNetworkSession();
501 CreateInsecureSpdySession();
503 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
505 GURL url(kDefaultURL);
506 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
507 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
508 test::StreamDelegateDoNothing delegate1(spdy_stream1);
509 spdy_stream1->SetDelegate(&delegate1);
511 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
512 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
513 test::StreamDelegateDoNothing delegate2(spdy_stream2);
514 spdy_stream2->SetDelegate(&delegate2);
516 scoped_ptr<SpdyHeaderBlock> headers(
517 spdy_util_.ConstructGetHeaderBlock(url.spec()));
518 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
520 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
521 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
522 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
523 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
525 base::RunLoop().RunUntilIdle();
527 EXPECT_EQ(1u, spdy_stream1->stream_id());
528 EXPECT_EQ(3u, spdy_stream2->stream_id());
530 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
532 // Read and process the GOAWAY frame.
533 data.CompleteRead();
534 base::RunLoop().RunUntilIdle();
536 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
538 EXPECT_FALSE(session_->IsStreamActive(3));
539 EXPECT_FALSE(spdy_stream2);
540 EXPECT_TRUE(session_->IsStreamActive(1));
541 EXPECT_TRUE(session_->IsGoingAway());
543 session_->CloseSessionOnError(ERR_ABORTED, "Aborting session");
544 EXPECT_FALSE(spdy_stream1);
546 data.CompleteRead();
547 base::RunLoop().RunUntilIdle();
548 EXPECT_FALSE(session_);
551 // Process a joint read buffer which causes the session to begin draining, and
552 // then processes a GOAWAY. The session should gracefully drain. Regression test
553 // for crbug.com/379469
554 TEST_P(SpdySessionTest, GoAwayWhileDraining) {
555 session_deps_.host_resolver->set_synchronous_mode(true);
557 scoped_ptr<SpdyFrame> req(
558 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
559 MockWrite writes[] = {
560 CreateMockWrite(*req, 0),
563 scoped_ptr<SpdyFrame> resp(
564 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
565 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
566 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
567 size_t joint_size = goaway->size() * 2 + body->size();
569 // Compose interleaved |goaway| and |body| frames into a single read.
570 scoped_ptr<char[]> buffer(new char[joint_size]);
572 size_t out = 0;
573 memcpy(&buffer[out], goaway->data(), goaway->size());
574 out += goaway->size();
575 memcpy(&buffer[out], body->data(), body->size());
576 out += body->size();
577 memcpy(&buffer[out], goaway->data(), goaway->size());
578 out += goaway->size();
579 ASSERT_EQ(out, joint_size);
581 SpdyFrame joint_frames(buffer.get(), joint_size, false);
583 MockRead reads[] = {
584 CreateMockRead(*resp, 1), CreateMockRead(joint_frames, 2),
585 MockRead(ASYNC, 0, 3) // EOF
588 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
589 session_deps_.socket_factory->AddSocketDataProvider(&data);
591 CreateNetworkSession();
592 CreateInsecureSpdySession();
594 GURL url(kDefaultURL);
595 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
596 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
597 test::StreamDelegateDoNothing delegate(spdy_stream);
598 spdy_stream->SetDelegate(&delegate);
600 scoped_ptr<SpdyHeaderBlock> headers(
601 spdy_util_.ConstructGetHeaderBlock(url.spec()));
602 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
603 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
605 base::RunLoop().RunUntilIdle();
607 // Stream and session closed gracefully.
608 EXPECT_TRUE(delegate.StreamIsClosed());
609 EXPECT_EQ(OK, delegate.WaitForClose());
610 EXPECT_EQ(kUploadData, delegate.TakeReceivedData());
611 EXPECT_FALSE(session_);
614 // Try to create a stream after receiving a GOAWAY frame. It should
615 // fail.
616 TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
617 session_deps_.host_resolver->set_synchronous_mode(true);
619 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
620 MockRead reads[] = {
621 MockRead(ASYNC, ERR_IO_PENDING, 1),
622 CreateMockRead(*goaway, 2),
623 MockRead(ASYNC, ERR_IO_PENDING, 3),
624 MockRead(ASYNC, 0, 4) // EOF
626 scoped_ptr<SpdyFrame> req(
627 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
628 MockWrite writes[] = {
629 CreateMockWrite(*req, 0),
631 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
632 session_deps_.socket_factory->AddSocketDataProvider(&data);
634 CreateNetworkSession();
635 CreateInsecureSpdySession();
637 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
639 GURL url(kDefaultURL);
640 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
641 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
642 test::StreamDelegateDoNothing delegate(spdy_stream);
643 spdy_stream->SetDelegate(&delegate);
645 scoped_ptr<SpdyHeaderBlock> headers(
646 spdy_util_.ConstructGetHeaderBlock(url.spec()));
647 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
648 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
650 base::RunLoop().RunUntilIdle();
652 EXPECT_EQ(1u, spdy_stream->stream_id());
654 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
656 // Read and process the GOAWAY frame.
657 data.CompleteRead();
658 base::RunLoop().RunUntilIdle();
660 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
661 EXPECT_TRUE(session_->IsStreamActive(1));
663 SpdyStreamRequest stream_request;
664 int rv =
665 stream_request.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, url,
666 MEDIUM, BoundNetLog(), CompletionCallback());
667 EXPECT_EQ(ERR_FAILED, rv);
669 EXPECT_TRUE(session_);
670 data.CompleteRead();
671 base::RunLoop().RunUntilIdle();
672 EXPECT_FALSE(session_);
675 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
676 // the stream being refused.
677 TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
678 session_deps_.host_resolver->set_synchronous_mode(true);
680 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
681 scoped_ptr<SpdyFrame> push(
682 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kDefaultURL));
683 MockRead reads[] = {
684 MockRead(ASYNC, ERR_IO_PENDING, 1),
685 CreateMockRead(*goaway, 2),
686 MockRead(ASYNC, ERR_IO_PENDING, 3),
687 CreateMockRead(*push, 4),
688 MockRead(ASYNC, 0, 6) // EOF
690 scoped_ptr<SpdyFrame> req(
691 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
692 scoped_ptr<SpdyFrame> rst(
693 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
694 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5)};
695 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
696 session_deps_.socket_factory->AddSocketDataProvider(&data);
698 CreateNetworkSession();
699 CreateInsecureSpdySession();
701 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
703 GURL url(kDefaultURL);
704 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
705 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
706 test::StreamDelegateDoNothing delegate(spdy_stream);
707 spdy_stream->SetDelegate(&delegate);
709 scoped_ptr<SpdyHeaderBlock> headers(
710 spdy_util_.ConstructGetHeaderBlock(url.spec()));
711 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
712 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
714 base::RunLoop().RunUntilIdle();
716 EXPECT_EQ(1u, spdy_stream->stream_id());
718 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
720 // Read and process the GOAWAY frame.
721 data.CompleteRead();
722 base::RunLoop().RunUntilIdle();
724 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
725 EXPECT_TRUE(session_->IsStreamActive(1));
727 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
728 // and EOF.
729 data.CompleteRead();
730 base::RunLoop().RunUntilIdle();
731 EXPECT_FALSE(session_);
734 // A session observing a network change with active streams should close
735 // when the last active stream is closed.
736 TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
737 session_deps_.host_resolver->set_synchronous_mode(true);
739 MockRead reads[] = {
740 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
742 scoped_ptr<SpdyFrame> req1(
743 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
744 MockWrite writes[] = {
745 CreateMockWrite(*req1, 0),
747 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
748 session_deps_.socket_factory->AddSocketDataProvider(&data);
750 CreateNetworkSession();
751 CreateInsecureSpdySession();
753 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
755 base::WeakPtr<SpdyStream> spdy_stream =
756 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
757 GURL(kDefaultURL), MEDIUM, BoundNetLog());
758 test::StreamDelegateDoNothing delegate(spdy_stream);
759 spdy_stream->SetDelegate(&delegate);
761 scoped_ptr<SpdyHeaderBlock> headers(
762 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
764 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
765 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
767 base::RunLoop().RunUntilIdle();
769 EXPECT_EQ(1u, spdy_stream->stream_id());
771 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
773 spdy_session_pool_->OnIPAddressChanged();
775 // The SpdySessionPool behavior differs based on how the OSs reacts to
776 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
777 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
778 // For OSs where the TCP connections will close upon relevant network
779 // changes, SpdySessionPool doesn't need to force them to close, so in these
780 // cases verify the session has become unavailable but remains open and the
781 // pre-existing stream is still active.
782 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
784 EXPECT_TRUE(session_->IsGoingAway());
786 EXPECT_TRUE(session_->IsStreamActive(1));
788 // Should close the session.
789 spdy_stream->Close();
790 #endif
791 EXPECT_FALSE(spdy_stream);
793 data.CompleteRead();
794 base::RunLoop().RunUntilIdle();
795 EXPECT_FALSE(session_);
798 TEST_P(SpdySessionTest, ClientPing) {
799 session_deps_.enable_ping = true;
800 session_deps_.host_resolver->set_synchronous_mode(true);
802 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
803 MockRead reads[] = {
804 CreateMockRead(*read_ping, 1),
805 MockRead(ASYNC, ERR_IO_PENDING, 2),
806 MockRead(ASYNC, 0, 3) // EOF
808 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
809 MockWrite writes[] = {
810 CreateMockWrite(*write_ping, 0),
812 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
813 session_deps_.socket_factory->AddSocketDataProvider(&data);
815 CreateNetworkSession();
816 CreateInsecureSpdySession();
818 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
819 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
820 ASSERT_TRUE(spdy_stream1.get() != nullptr);
821 test::StreamDelegateSendImmediate delegate(spdy_stream1, nullptr);
822 spdy_stream1->SetDelegate(&delegate);
824 base::TimeTicks before_ping_time = base::TimeTicks::Now();
826 session_->set_connection_at_risk_of_loss_time(
827 base::TimeDelta::FromSeconds(-1));
828 session_->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
830 session_->SendPrefacePingIfNoneInFlight();
832 base::RunLoop().RunUntilIdle();
834 session_->CheckPingStatus(before_ping_time);
836 EXPECT_EQ(0, session_->pings_in_flight());
837 EXPECT_GE(session_->next_ping_id(), 1U);
838 EXPECT_FALSE(session_->check_ping_status_pending());
839 EXPECT_GE(session_->last_activity_time(), before_ping_time);
841 data.CompleteRead();
842 base::RunLoop().RunUntilIdle();
844 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
846 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
847 EXPECT_FALSE(session_);
850 TEST_P(SpdySessionTest, ServerPing) {
851 session_deps_.host_resolver->set_synchronous_mode(true);
853 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
854 MockRead reads[] = {
855 CreateMockRead(*read_ping),
856 MockRead(SYNCHRONOUS, 0, 0) // EOF
858 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
859 MockWrite writes[] = {
860 CreateMockWrite(*write_ping),
862 StaticSocketDataProvider data(
863 reads, arraysize(reads), writes, arraysize(writes));
864 session_deps_.socket_factory->AddSocketDataProvider(&data);
866 CreateNetworkSession();
867 CreateInsecureSpdySession();
869 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
870 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
871 ASSERT_TRUE(spdy_stream1.get() != nullptr);
872 test::StreamDelegateSendImmediate delegate(spdy_stream1, nullptr);
873 spdy_stream1->SetDelegate(&delegate);
875 // Flush the read completion task.
876 base::RunLoop().RunUntilIdle();
878 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
880 EXPECT_FALSE(session_);
881 EXPECT_FALSE(spdy_stream1);
884 // Cause a ping to be sent out while producing a write. The write loop
885 // should handle this properly, i.e. another DoWriteLoop task should
886 // not be posted. This is a regression test for
887 // http://crbug.com/261043 .
888 TEST_P(SpdySessionTest, PingAndWriteLoop) {
889 session_deps_.enable_ping = true;
890 session_deps_.time_func = TheNearFuture;
892 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
893 scoped_ptr<SpdyFrame> req(
894 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
895 MockWrite writes[] = {
896 CreateMockWrite(*req, 0),
897 CreateMockWrite(*write_ping, 1),
900 MockRead reads[] = {
901 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
904 session_deps_.host_resolver->set_synchronous_mode(true);
906 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
907 session_deps_.socket_factory->AddSocketDataProvider(&data);
909 CreateNetworkSession();
910 CreateInsecureSpdySession();
912 GURL url(kDefaultURL);
913 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
914 SPDY_REQUEST_RESPONSE_STREAM, session_, url, LOWEST, BoundNetLog());
915 test::StreamDelegateDoNothing delegate(spdy_stream);
916 spdy_stream->SetDelegate(&delegate);
918 scoped_ptr<SpdyHeaderBlock> headers(
919 spdy_util_.ConstructGetHeaderBlock(url.spec()));
920 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
922 // Shift time so that a ping will be sent out.
923 g_time_delta = base::TimeDelta::FromSeconds(11);
925 base::RunLoop().RunUntilIdle();
926 session_->CloseSessionOnError(ERR_ABORTED, "Aborting");
928 data.CompleteRead();
929 base::RunLoop().RunUntilIdle();
930 EXPECT_FALSE(session_);
933 TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
934 const SpdyStreamId kLastStreamId = 0x7fffffff;
935 session_deps_.host_resolver->set_synchronous_mode(true);
937 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
938 // fixed to allow for two stream ID assignments, and three concurrent
939 // streams. Four streams are started, and two are activated. Verify the
940 // session goes away, and that the created (but not activated) and
941 // stalled streams are aborted. Also verify the activated streams complete,
942 // at which point the session closes.
944 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
945 nullptr, 0, false, kLastStreamId - 2, MEDIUM, true));
946 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
947 nullptr, 0, false, kLastStreamId, MEDIUM, true));
949 MockWrite writes[] = {
950 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
953 scoped_ptr<SpdyFrame> resp1(
954 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId - 2));
955 scoped_ptr<SpdyFrame> resp2(
956 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId));
958 scoped_ptr<SpdyFrame> body1(
959 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
960 scoped_ptr<SpdyFrame> body2(
961 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
963 MockRead reads[] = {
964 CreateMockRead(*resp1, 2),
965 CreateMockRead(*resp2, 3),
966 MockRead(ASYNC, ERR_IO_PENDING, 4),
967 CreateMockRead(*body1, 5),
968 CreateMockRead(*body2, 6),
969 MockRead(ASYNC, 0, 7) // EOF
972 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
973 session_deps_.socket_factory->AddSocketDataProvider(&data);
975 CreateNetworkSession();
976 CreateInsecureSpdySession();
978 // Fix stream_hi_water_mark_ to allow for two stream activations.
979 session_->stream_hi_water_mark_ = kLastStreamId - 2;
980 // Fix max_concurrent_streams to allow for three stream creations.
981 session_->max_concurrent_streams_ = 3;
983 // Create three streams synchronously, and begin a fourth (which is stalled).
984 GURL url(kDefaultURL);
985 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
986 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
987 test::StreamDelegateDoNothing delegate1(stream1);
988 stream1->SetDelegate(&delegate1);
990 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
991 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
992 test::StreamDelegateDoNothing delegate2(stream2);
993 stream2->SetDelegate(&delegate2);
995 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
996 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
997 test::StreamDelegateDoNothing delegate3(stream3);
998 stream3->SetDelegate(&delegate3);
1000 SpdyStreamRequest request4;
1001 TestCompletionCallback callback4;
1002 EXPECT_EQ(ERR_IO_PENDING,
1003 request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, url,
1004 MEDIUM, BoundNetLog(), callback4.callback()));
1006 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1007 EXPECT_EQ(0u, session_->num_active_streams());
1008 EXPECT_EQ(3u, session_->num_created_streams());
1009 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(MEDIUM));
1011 // Activate stream 1. One ID remains available.
1012 stream1->SendRequestHeaders(
1013 scoped_ptr<SpdyHeaderBlock>(
1014 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1015 NO_MORE_DATA_TO_SEND);
1016 base::RunLoop().RunUntilIdle();
1018 EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1019 EXPECT_EQ(1u, session_->num_active_streams());
1020 EXPECT_EQ(2u, session_->num_created_streams());
1021 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(MEDIUM));
1023 // Activate stream 2. ID space is exhausted.
1024 stream2->SendRequestHeaders(
1025 scoped_ptr<SpdyHeaderBlock>(
1026 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1027 NO_MORE_DATA_TO_SEND);
1028 base::RunLoop().RunUntilIdle();
1030 // Active streams remain active.
1031 EXPECT_EQ(kLastStreamId, stream2->stream_id());
1032 EXPECT_EQ(2u, session_->num_active_streams());
1034 // Session is going away. Created and stalled streams were aborted.
1035 EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session_->availability_state_);
1036 EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose());
1037 EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult());
1038 EXPECT_EQ(0u, session_->num_created_streams());
1039 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(MEDIUM));
1041 // Read responses on remaining active streams.
1042 data.CompleteRead();
1043 base::RunLoop().RunUntilIdle();
1044 EXPECT_EQ(OK, delegate1.WaitForClose());
1045 EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1046 EXPECT_EQ(OK, delegate2.WaitForClose());
1047 EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1049 // Session was destroyed.
1050 EXPECT_FALSE(session_);
1053 // Verifies that an unstalled pending stream creation racing with a new stream
1054 // creation doesn't violate the maximum stream concurrency. Regression test for
1055 // crbug.com/373858.
1056 TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) {
1057 session_deps_.host_resolver->set_synchronous_mode(true);
1059 MockRead reads[] = {
1060 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1063 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1064 session_deps_.socket_factory->AddSocketDataProvider(&data);
1066 CreateNetworkSession();
1067 CreateInsecureSpdySession();
1069 // Fix max_concurrent_streams to allow for one open stream.
1070 session_->max_concurrent_streams_ = 1;
1072 // Create two streams: one synchronously, and one which stalls.
1073 GURL url(kDefaultURL);
1074 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1075 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
1077 SpdyStreamRequest request2;
1078 TestCompletionCallback callback2;
1079 EXPECT_EQ(ERR_IO_PENDING,
1080 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, url,
1081 MEDIUM, BoundNetLog(), callback2.callback()));
1083 EXPECT_EQ(1u, session_->num_created_streams());
1084 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(MEDIUM));
1086 // Cancel the first stream. A callback to unstall the second stream was
1087 // posted. Don't run it yet.
1088 stream1->Cancel();
1090 EXPECT_EQ(0u, session_->num_created_streams());
1091 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(MEDIUM));
1093 // Create a third stream prior to the second stream's callback.
1094 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1095 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
1097 EXPECT_EQ(1u, session_->num_created_streams());
1098 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(MEDIUM));
1100 // Now run the message loop. The unstalled stream will re-stall itself.
1101 base::RunLoop().RunUntilIdle();
1102 EXPECT_EQ(1u, session_->num_created_streams());
1103 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(MEDIUM));
1105 // Cancel the third stream and run the message loop. Verify that the second
1106 // stream creation now completes.
1107 stream3->Cancel();
1108 base::RunLoop().RunUntilIdle();
1110 EXPECT_EQ(1u, session_->num_created_streams());
1111 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(MEDIUM));
1112 EXPECT_EQ(OK, callback2.WaitForResult());
1115 TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
1116 session_deps_.host_resolver->set_synchronous_mode(true);
1117 session_deps_.time_func = TheNearFuture;
1119 scoped_ptr<SpdyFrame> req(
1120 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
1121 scoped_ptr<SpdyFrame> rst(
1122 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
1123 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5)};
1125 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
1126 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
1127 scoped_ptr<SpdyFrame> push_a_body(
1128 spdy_util_.ConstructSpdyBodyFrame(2, false));
1129 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1130 // iterators inside. See http://crbug.com/443490
1131 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
1132 nullptr, 0, 4, 1, "http://www.example.org/0.dat"));
1133 MockRead reads[] = {
1134 CreateMockRead(*push_a, 1),
1135 CreateMockRead(*push_a_body, 2),
1136 MockRead(ASYNC, ERR_IO_PENDING, 3),
1137 CreateMockRead(*push_b, 4),
1138 MockRead(ASYNC, ERR_IO_PENDING, 6),
1139 MockRead(ASYNC, 0, 7) // EOF
1142 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1143 session_deps_.socket_factory->AddSocketDataProvider(&data);
1145 CreateNetworkSession();
1146 CreateInsecureSpdySession();
1148 // Process the principal request, and the first push stream request & body.
1149 GURL url(kDefaultURL);
1150 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1151 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
1152 test::StreamDelegateDoNothing delegate(spdy_stream);
1153 spdy_stream->SetDelegate(&delegate);
1155 scoped_ptr<SpdyHeaderBlock> headers(
1156 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1157 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1159 base::RunLoop().RunUntilIdle();
1161 // Verify that there is one unclaimed push stream.
1162 EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
1163 SpdySession::PushedStreamMap::iterator iter =
1164 session_->unclaimed_pushed_streams_.find(
1165 GURL("http://www.example.org/a.dat"));
1166 EXPECT_TRUE(session_->unclaimed_pushed_streams_.end() != iter);
1168 if (session_->flow_control_state_ ==
1169 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1170 // Unclaimed push body consumed bytes from the session window.
1171 EXPECT_EQ(
1172 SpdySession::GetDefaultInitialWindowSize(GetParam()) - kUploadDataSize,
1173 session_->session_recv_window_size_);
1174 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
1177 // Shift time to expire the push stream. Read the second SYN_STREAM,
1178 // and verify a RST_STREAM was written.
1179 g_time_delta = base::TimeDelta::FromSeconds(301);
1180 data.CompleteRead();
1181 base::RunLoop().RunUntilIdle();
1183 // Verify that the second pushed stream evicted the first pushed stream.
1184 EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
1185 iter = session_->unclaimed_pushed_streams_.find(
1186 GURL("http://www.example.org/0.dat"));
1187 EXPECT_TRUE(session_->unclaimed_pushed_streams_.end() != iter);
1189 if (session_->flow_control_state_ ==
1190 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1191 // Verify that the session window reclaimed the evicted stream body.
1192 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
1193 session_->session_recv_window_size_);
1194 EXPECT_EQ(kUploadDataSize, session_->session_unacked_recv_window_bytes_);
1197 // Read and process EOF.
1198 EXPECT_TRUE(session_);
1199 data.CompleteRead();
1200 base::RunLoop().RunUntilIdle();
1201 EXPECT_FALSE(session_);
1204 TEST_P(SpdySessionTest, FailedPing) {
1205 session_deps_.host_resolver->set_synchronous_mode(true);
1207 MockRead reads[] = {
1208 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1210 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
1211 scoped_ptr<SpdyFrame> goaway(
1212 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping."));
1213 MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)};
1215 StaticSocketDataProvider data(
1216 reads, arraysize(reads), writes, arraysize(writes));
1217 session_deps_.socket_factory->AddSocketDataProvider(&data);
1219 CreateNetworkSession();
1220 CreateInsecureSpdySession();
1222 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1223 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1224 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1225 test::StreamDelegateSendImmediate delegate(spdy_stream1, nullptr);
1226 spdy_stream1->SetDelegate(&delegate);
1228 session_->set_connection_at_risk_of_loss_time(
1229 base::TimeDelta::FromSeconds(0));
1230 session_->set_hung_interval(base::TimeDelta::FromSeconds(0));
1232 // Send a PING frame.
1233 session_->WritePingFrame(1, false);
1234 EXPECT_LT(0, session_->pings_in_flight());
1235 EXPECT_GE(session_->next_ping_id(), 1U);
1236 EXPECT_TRUE(session_->check_ping_status_pending());
1238 // Assert session is not closed.
1239 EXPECT_TRUE(session_->IsAvailable());
1240 EXPECT_LT(0u,
1241 session_->num_active_streams() + session_->num_created_streams());
1242 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1244 // We set last time we have received any data in 1 sec less than now.
1245 // CheckPingStatus will trigger timeout because hung interval is zero.
1246 base::TimeTicks now = base::TimeTicks::Now();
1247 session_->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
1248 session_->CheckPingStatus(now);
1249 base::RunLoop().RunUntilIdle();
1251 EXPECT_FALSE(session_);
1252 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1253 EXPECT_FALSE(spdy_stream1);
1256 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1257 // settings frame increasing the max concurrent streams by 1. Make
1258 // sure nothing blows up. This is a regression test for
1259 // http://crbug.com/57331 .
1260 TEST_P(SpdySessionTest, OnSettings) {
1261 session_deps_.host_resolver->set_synchronous_mode(true);
1263 const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1265 int seq = 0;
1266 std::vector<MockWrite> writes;
1267 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1268 if (GetParam() >= kProtoHTTP2MinimumVersion) {
1269 writes.push_back(CreateMockWrite(*settings_ack, ++seq));
1272 SettingsMap new_settings;
1273 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1274 new_settings[kSpdySettingsIds] =
1275 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1276 scoped_ptr<SpdyFrame> settings_frame(
1277 spdy_util_.ConstructSpdySettings(new_settings));
1278 MockRead reads[] = {
1279 CreateMockRead(*settings_frame, 0),
1280 MockRead(ASYNC, ERR_IO_PENDING, ++seq),
1281 MockRead(ASYNC, 0, ++seq),
1284 SequencedSocketData data(reads, arraysize(reads), vector_as_array(&writes),
1285 writes.size());
1286 session_deps_.socket_factory->AddSocketDataProvider(&data);
1288 CreateNetworkSession();
1289 CreateInsecureSpdySession();
1291 // Create the maximum number of concurrent streams.
1292 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1293 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1294 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1295 ASSERT_TRUE(spdy_stream != nullptr);
1298 StreamReleaserCallback stream_releaser;
1299 SpdyStreamRequest request;
1300 ASSERT_EQ(ERR_IO_PENDING,
1301 request.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1302 MEDIUM, BoundNetLog(),
1303 stream_releaser.MakeCallback(&request)));
1305 base::RunLoop().RunUntilIdle();
1307 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1309 data.CompleteRead();
1310 base::RunLoop().RunUntilIdle();
1311 EXPECT_FALSE(session_);
1313 EXPECT_TRUE(data.AllWriteDataConsumed());
1314 EXPECT_TRUE(data.AllReadDataConsumed());
1317 // Start with a persisted value for max concurrent streams. Receive a
1318 // settings frame increasing the max concurrent streams by 1 and which
1319 // also clears the persisted data. Verify that persisted data is
1320 // correct.
1321 TEST_P(SpdySessionTest, ClearSettings) {
1322 if (spdy_util_.spdy_version() >= HTTP2) {
1323 // HTTP/2 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1324 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in HTTP/2.
1325 return;
1327 session_deps_.host_resolver->set_synchronous_mode(true);
1329 SettingsMap new_settings;
1330 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1331 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1332 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1333 scoped_ptr<SpdyFrame> settings_frame(
1334 spdy_util_.ConstructSpdySettings(new_settings));
1335 uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1336 test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1337 MockRead reads[] = {
1338 CreateMockRead(*settings_frame, 0),
1339 MockRead(ASYNC, ERR_IO_PENDING, 1),
1340 MockRead(ASYNC, 0, 2),
1343 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
1344 session_deps_.socket_factory->AddSocketDataProvider(&data);
1346 CreateNetworkSession();
1348 // Initialize the SpdySetting with the default.
1349 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1350 test_host_port_pair_,
1351 SETTINGS_MAX_CONCURRENT_STREAMS,
1352 SETTINGS_FLAG_PLEASE_PERSIST,
1353 kInitialMaxConcurrentStreams);
1355 EXPECT_FALSE(
1356 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1357 test_host_port_pair_).empty());
1359 CreateInsecureSpdySession();
1361 // Create the maximum number of concurrent streams.
1362 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1363 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1364 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1365 ASSERT_TRUE(spdy_stream != nullptr);
1368 StreamReleaserCallback stream_releaser;
1370 SpdyStreamRequest request;
1371 ASSERT_EQ(ERR_IO_PENDING,
1372 request.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1373 MEDIUM, BoundNetLog(),
1374 stream_releaser.MakeCallback(&request)));
1376 base::RunLoop().RunUntilIdle();
1378 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1380 // Make sure that persisted data is cleared.
1381 EXPECT_TRUE(
1382 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1383 test_host_port_pair_).empty());
1385 // Make sure session's max_concurrent_streams is correct.
1386 EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1387 session_->max_concurrent_streams());
1389 data.CompleteRead();
1390 base::RunLoop().RunUntilIdle();
1391 EXPECT_FALSE(session_);
1394 // Start with max concurrent streams set to 1. Request two streams.
1395 // When the first completes, have the callback close its stream, which
1396 // should trigger the second stream creation. Then cancel that one
1397 // immediately. Don't crash. This is a regression test for
1398 // http://crbug.com/63532 .
1399 TEST_P(SpdySessionTest, CancelPendingCreateStream) {
1400 session_deps_.host_resolver->set_synchronous_mode(true);
1402 MockRead reads[] = {
1403 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1406 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1407 session_deps_.socket_factory->AddSocketDataProvider(&data);
1409 CreateNetworkSession();
1411 // Initialize the SpdySetting with 1 max concurrent streams.
1412 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1413 test_host_port_pair_,
1414 SETTINGS_MAX_CONCURRENT_STREAMS,
1415 SETTINGS_FLAG_PLEASE_PERSIST,
1418 CreateInsecureSpdySession();
1420 // Leave room for only one more stream to be created.
1421 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1422 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1423 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1424 ASSERT_TRUE(spdy_stream != nullptr);
1427 // Create 2 more streams. First will succeed. Second will be pending.
1428 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1429 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1430 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1432 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1433 // a valgrind error if the callback is invoked when it's not supposed to be.
1434 scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
1436 SpdyStreamRequest request;
1437 ASSERT_EQ(ERR_IO_PENDING,
1438 request.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1439 MEDIUM, BoundNetLog(), callback->callback()));
1441 // Release the first one, this will allow the second to be created.
1442 spdy_stream1->Cancel();
1443 EXPECT_FALSE(spdy_stream1);
1445 request.CancelRequest();
1446 callback.reset();
1448 // Should not crash when running the pending callback.
1449 base::RunLoop().RunUntilIdle();
1452 TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
1453 session_deps_.host_resolver->set_synchronous_mode(true);
1455 MockRead reads[] = {
1456 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1459 SettingsMap settings;
1460 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1461 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
1462 scoped_ptr<SpdyFrame> settings_frame(
1463 spdy_util_.ConstructSpdySettings(settings));
1464 std::vector<MockWrite> writes;
1465 if ((GetParam() >= kProtoHTTP2MinimumVersion) &&
1466 (GetParam() <= kProtoHTTP2MaximumVersion)) {
1467 writes.push_back(
1468 MockWrite(ASYNC,
1469 kHttp2ConnectionHeaderPrefix,
1470 kHttp2ConnectionHeaderPrefixSize));
1472 writes.push_back(CreateMockWrite(*settings_frame));
1474 SettingsMap server_settings;
1475 const uint32 initial_max_concurrent_streams = 1;
1476 server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1477 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1478 initial_max_concurrent_streams);
1479 scoped_ptr<SpdyFrame> server_settings_frame(
1480 spdy_util_.ConstructSpdySettings(server_settings));
1481 if (GetParam() <= kProtoSPDY31) {
1482 writes.push_back(CreateMockWrite(*server_settings_frame));
1485 StaticSocketDataProvider data(reads, arraysize(reads),
1486 vector_as_array(&writes), writes.size());
1487 session_deps_.socket_factory->AddSocketDataProvider(&data);
1489 CreateNetworkSession();
1491 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1492 test_host_port_pair_,
1493 SETTINGS_MAX_CONCURRENT_STREAMS,
1494 SETTINGS_FLAG_PLEASE_PERSIST,
1495 initial_max_concurrent_streams);
1497 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1498 pool_peer.SetEnableSendingInitialData(true);
1500 CreateInsecureSpdySession();
1502 base::RunLoop().RunUntilIdle();
1503 EXPECT_TRUE(data.AllWriteDataConsumed());
1506 TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
1507 CreateNetworkSession();
1509 base::WeakPtr<HttpServerProperties> test_http_server_properties =
1510 spdy_session_pool_->http_server_properties();
1511 SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
1512 test_http_server_properties->SetSpdySetting(
1513 test_host_port_pair_,
1514 SETTINGS_MAX_CONCURRENT_STREAMS,
1515 SETTINGS_FLAG_PLEASE_PERSIST,
1517 EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
1518 test_host_port_pair_).size());
1519 spdy_session_pool_->OnIPAddressChanged();
1520 EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
1521 test_host_port_pair_).size());
1524 TEST_P(SpdySessionTest, Initialize) {
1525 session_deps_.host_resolver->set_synchronous_mode(true);
1527 MockRead reads[] = {
1528 MockRead(ASYNC, 0, 0) // EOF
1531 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1532 session_deps_.socket_factory->AddSocketDataProvider(&data);
1534 CreateNetworkSession();
1535 CreateInsecureSpdySession();
1536 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1538 // Flush the read completion task.
1539 base::RunLoop().RunUntilIdle();
1541 TestNetLogEntry::List entries;
1542 log_.GetEntries(&entries);
1543 EXPECT_LT(0u, entries.size());
1545 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1546 int pos = ExpectLogContainsSomewhere(
1547 entries, 0, NetLog::TYPE_HTTP2_SESSION_INITIALIZED, NetLog::PHASE_NONE);
1548 EXPECT_LT(0, pos);
1550 TestNetLogEntry entry = entries[pos];
1551 NetLog::Source socket_source;
1552 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1553 &socket_source));
1554 EXPECT_TRUE(socket_source.IsValid());
1555 EXPECT_NE(log_.bound().source().id, socket_source.id);
1558 TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
1559 session_deps_.host_resolver->set_synchronous_mode(true);
1561 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
1562 MockRead reads[] = {
1563 CreateMockRead(*goaway),
1564 MockRead(SYNCHRONOUS, 0, 0) // EOF
1567 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1568 session_deps_.socket_factory->AddSocketDataProvider(&data);
1570 CreateNetworkSession();
1571 CreateInsecureSpdySession();
1572 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1574 // Flush the read completion task.
1575 base::RunLoop().RunUntilIdle();
1577 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1578 EXPECT_FALSE(session_);
1580 // Check that the NetLog was filled reasonably.
1581 TestNetLogEntry::List entries;
1582 log_.GetEntries(&entries);
1583 EXPECT_LT(0u, entries.size());
1585 // Check that we logged SPDY_SESSION_CLOSE correctly.
1586 int pos = ExpectLogContainsSomewhere(
1587 entries, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE, NetLog::PHASE_NONE);
1589 if (pos < static_cast<int>(entries.size())) {
1590 TestNetLogEntry entry = entries[pos];
1591 int error_code = 0;
1592 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1593 EXPECT_EQ(OK, error_code);
1594 } else {
1595 ADD_FAILURE();
1599 TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1600 session_deps_.host_resolver->set_synchronous_mode(true);
1602 MockRead reads[] = {
1603 MockRead(SYNCHRONOUS, 0, 0) // EOF
1606 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1607 session_deps_.socket_factory->AddSocketDataProvider(&data);
1609 CreateNetworkSession();
1610 CreateInsecureSpdySession();
1611 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1613 // Flush the read completion task.
1614 base::RunLoop().RunUntilIdle();
1616 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1617 EXPECT_FALSE(session_);
1619 // Check that the NetLog was filled reasonably.
1620 TestNetLogEntry::List entries;
1621 log_.GetEntries(&entries);
1622 EXPECT_LT(0u, entries.size());
1624 // Check that we logged SPDY_SESSION_CLOSE correctly.
1625 int pos = ExpectLogContainsSomewhere(
1626 entries, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE, NetLog::PHASE_NONE);
1628 if (pos < static_cast<int>(entries.size())) {
1629 TestNetLogEntry entry = entries[pos];
1630 int error_code = 0;
1631 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1632 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1633 } else {
1634 ADD_FAILURE();
1638 TEST_P(SpdySessionTest, SynCompressionHistograms) {
1639 session_deps_.enable_compression = true;
1641 scoped_ptr<SpdyFrame> req(
1642 spdy_util_.ConstructSpdyGet(nullptr, 0, true, 1, MEDIUM, true));
1643 MockWrite writes[] = {
1644 CreateMockWrite(*req, 0),
1646 MockRead reads[] = {
1647 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
1649 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1650 session_deps_.socket_factory->AddSocketDataProvider(&data);
1652 CreateNetworkSession();
1653 CreateInsecureSpdySession();
1655 GURL url(kDefaultURL);
1656 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1657 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
1658 test::StreamDelegateDoNothing delegate(spdy_stream);
1659 spdy_stream->SetDelegate(&delegate);
1661 scoped_ptr<SpdyHeaderBlock> headers(
1662 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1663 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1664 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1666 // Write request headers & capture resulting histogram update.
1667 base::HistogramTester histogram_tester;
1669 base::RunLoop().RunUntilIdle();
1670 // Regression test of compression performance under the request fixture.
1671 switch (spdy_util_.spdy_version()) {
1672 case SPDY3:
1673 histogram_tester.ExpectBucketCount(
1674 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1675 break;
1676 case HTTP2:
1677 histogram_tester.ExpectBucketCount(
1678 "Net.SpdySynStreamCompressionPercentage", 81, 1);
1679 break;
1680 default:
1681 NOTREACHED();
1684 // Read and process EOF.
1685 EXPECT_TRUE(session_);
1686 data.CompleteRead();
1687 base::RunLoop().RunUntilIdle();
1688 EXPECT_FALSE(session_);
1691 // Queue up a low-priority SYN_STREAM followed by a high-priority
1692 // one. The high priority one should still send first and receive
1693 // first.
1694 TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1695 // Construct the request.
1696 scoped_ptr<SpdyFrame> req_highest(
1697 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, HIGHEST, true));
1698 scoped_ptr<SpdyFrame> req_lowest(
1699 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST, true));
1700 MockWrite writes[] = {
1701 CreateMockWrite(*req_highest, 0),
1702 CreateMockWrite(*req_lowest, 1),
1705 scoped_ptr<SpdyFrame> resp_highest(
1706 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
1707 scoped_ptr<SpdyFrame> body_highest(
1708 spdy_util_.ConstructSpdyBodyFrame(1, true));
1709 scoped_ptr<SpdyFrame> resp_lowest(
1710 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
1711 scoped_ptr<SpdyFrame> body_lowest(
1712 spdy_util_.ConstructSpdyBodyFrame(3, true));
1713 MockRead reads[] = {
1714 CreateMockRead(*resp_highest, 2),
1715 CreateMockRead(*body_highest, 3),
1716 CreateMockRead(*resp_lowest, 4),
1717 CreateMockRead(*body_lowest, 5),
1718 MockRead(ASYNC, 0, 6) // EOF
1721 session_deps_.host_resolver->set_synchronous_mode(true);
1723 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1724 session_deps_.socket_factory->AddSocketDataProvider(&data);
1726 CreateNetworkSession();
1727 CreateInsecureSpdySession();
1729 GURL url(kDefaultURL);
1731 base::WeakPtr<SpdyStream> spdy_stream_lowest = CreateStreamSynchronously(
1732 SPDY_REQUEST_RESPONSE_STREAM, session_, url, LOWEST, BoundNetLog());
1733 ASSERT_TRUE(spdy_stream_lowest);
1734 EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1735 test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1736 spdy_stream_lowest->SetDelegate(&delegate_lowest);
1738 base::WeakPtr<SpdyStream> spdy_stream_highest = CreateStreamSynchronously(
1739 SPDY_REQUEST_RESPONSE_STREAM, session_, url, HIGHEST, BoundNetLog());
1740 ASSERT_TRUE(spdy_stream_highest);
1741 EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1742 test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1743 spdy_stream_highest->SetDelegate(&delegate_highest);
1745 // Queue the lower priority one first.
1747 scoped_ptr<SpdyHeaderBlock> headers_lowest(
1748 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1749 spdy_stream_lowest->SendRequestHeaders(
1750 headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1751 EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1753 scoped_ptr<SpdyHeaderBlock> headers_highest(
1754 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1755 spdy_stream_highest->SendRequestHeaders(
1756 headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1757 EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1759 base::RunLoop().RunUntilIdle();
1761 EXPECT_FALSE(spdy_stream_lowest);
1762 EXPECT_FALSE(spdy_stream_highest);
1763 EXPECT_EQ(3u, delegate_lowest.stream_id());
1764 EXPECT_EQ(1u, delegate_highest.stream_id());
1767 TEST_P(SpdySessionTest, CancelStream) {
1768 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1769 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1770 scoped_ptr<SpdyFrame> req2(
1771 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
1772 MockWrite writes[] = {
1773 CreateMockWrite(*req2, 0),
1776 scoped_ptr<SpdyFrame> resp2(
1777 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
1778 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1779 MockRead reads[] = {
1780 CreateMockRead(*resp2, 1),
1781 MockRead(ASYNC, ERR_IO_PENDING, 2),
1782 CreateMockRead(*body2, 3),
1783 MockRead(ASYNC, 0, 4) // EOF
1786 session_deps_.host_resolver->set_synchronous_mode(true);
1788 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1789 session_deps_.socket_factory->AddSocketDataProvider(&data);
1791 CreateNetworkSession();
1792 CreateInsecureSpdySession();
1794 GURL url1(kDefaultURL);
1795 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1796 SPDY_REQUEST_RESPONSE_STREAM, session_, url1, HIGHEST, BoundNetLog());
1797 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1798 EXPECT_EQ(0u, spdy_stream1->stream_id());
1799 test::StreamDelegateDoNothing delegate1(spdy_stream1);
1800 spdy_stream1->SetDelegate(&delegate1);
1802 GURL url2(kDefaultURL);
1803 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
1804 SPDY_REQUEST_RESPONSE_STREAM, session_, url2, LOWEST, BoundNetLog());
1805 ASSERT_TRUE(spdy_stream2.get() != nullptr);
1806 EXPECT_EQ(0u, spdy_stream2->stream_id());
1807 test::StreamDelegateDoNothing delegate2(spdy_stream2);
1808 spdy_stream2->SetDelegate(&delegate2);
1810 scoped_ptr<SpdyHeaderBlock> headers(
1811 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1812 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1813 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1815 scoped_ptr<SpdyHeaderBlock> headers2(
1816 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1817 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1818 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1820 EXPECT_EQ(0u, spdy_stream1->stream_id());
1822 spdy_stream1->Cancel();
1823 EXPECT_FALSE(spdy_stream1);
1825 EXPECT_EQ(0u, delegate1.stream_id());
1827 base::RunLoop().RunUntilIdle();
1829 EXPECT_EQ(0u, delegate1.stream_id());
1830 EXPECT_EQ(1u, delegate2.stream_id());
1832 spdy_stream2->Cancel();
1833 EXPECT_FALSE(spdy_stream2);
1836 // Create two streams that are set to re-close themselves on close,
1837 // and then close the session. Nothing should blow up. Also a
1838 // regression test for http://crbug.com/139518 .
1839 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1840 session_deps_.host_resolver->set_synchronous_mode(true);
1843 // No actual data will be sent.
1844 MockWrite writes[] = {
1845 MockWrite(ASYNC, 0, 1) // EOF
1848 MockRead reads[] = {
1849 MockRead(ASYNC, 0, 0) // EOF
1851 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1852 session_deps_.socket_factory->AddSocketDataProvider(&data);
1854 CreateNetworkSession();
1855 CreateInsecureSpdySession();
1857 GURL url1(kDefaultURL);
1858 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1859 SPDY_BIDIRECTIONAL_STREAM, session_, url1, HIGHEST, BoundNetLog());
1860 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1861 EXPECT_EQ(0u, spdy_stream1->stream_id());
1863 GURL url2(kDefaultURL);
1864 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
1865 SPDY_BIDIRECTIONAL_STREAM, session_, url2, LOWEST, BoundNetLog());
1866 ASSERT_TRUE(spdy_stream2.get() != nullptr);
1867 EXPECT_EQ(0u, spdy_stream2->stream_id());
1869 test::ClosingDelegate delegate1(spdy_stream1);
1870 spdy_stream1->SetDelegate(&delegate1);
1872 test::ClosingDelegate delegate2(spdy_stream2);
1873 spdy_stream2->SetDelegate(&delegate2);
1875 scoped_ptr<SpdyHeaderBlock> headers(
1876 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1877 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1878 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1880 scoped_ptr<SpdyHeaderBlock> headers2(
1881 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1882 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1883 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1885 // Ensure that the streams have not yet been activated and assigned an id.
1886 EXPECT_EQ(0u, spdy_stream1->stream_id());
1887 EXPECT_EQ(0u, spdy_stream2->stream_id());
1889 // Ensure we don't crash while closing the session.
1890 session_->CloseSessionOnError(ERR_ABORTED, std::string());
1892 EXPECT_FALSE(spdy_stream1);
1893 EXPECT_FALSE(spdy_stream2);
1895 EXPECT_TRUE(delegate1.StreamIsClosed());
1896 EXPECT_TRUE(delegate2.StreamIsClosed());
1898 base::RunLoop().RunUntilIdle();
1899 EXPECT_FALSE(session_);
1902 // Create two streams that are set to close each other on close, and
1903 // then close the session. Nothing should blow up.
1904 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
1905 session_deps_.host_resolver->set_synchronous_mode(true);
1907 SequencedSocketData data(nullptr, 0, nullptr, 0);
1908 session_deps_.socket_factory->AddSocketDataProvider(&data);
1910 CreateNetworkSession();
1911 CreateInsecureSpdySession();
1913 GURL url1(kDefaultURL);
1914 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1915 SPDY_BIDIRECTIONAL_STREAM, session_, url1, HIGHEST, BoundNetLog());
1916 ASSERT_TRUE(spdy_stream1);
1917 EXPECT_EQ(0u, spdy_stream1->stream_id());
1919 GURL url2(kDefaultURL);
1920 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
1921 SPDY_BIDIRECTIONAL_STREAM, session_, url2, LOWEST, BoundNetLog());
1922 ASSERT_TRUE(spdy_stream2);
1923 EXPECT_EQ(0u, spdy_stream2->stream_id());
1925 // Make |spdy_stream1| close |spdy_stream2|.
1926 test::ClosingDelegate delegate1(spdy_stream2);
1927 spdy_stream1->SetDelegate(&delegate1);
1929 // Make |spdy_stream2| close |spdy_stream1|.
1930 test::ClosingDelegate delegate2(spdy_stream1);
1931 spdy_stream2->SetDelegate(&delegate2);
1933 scoped_ptr<SpdyHeaderBlock> headers(
1934 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1935 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1936 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1938 scoped_ptr<SpdyHeaderBlock> headers2(
1939 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1940 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1941 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1943 // Ensure that the streams have not yet been activated and assigned an id.
1944 EXPECT_EQ(0u, spdy_stream1->stream_id());
1945 EXPECT_EQ(0u, spdy_stream2->stream_id());
1947 // Ensure we don't crash while closing the session.
1948 session_->CloseSessionOnError(ERR_ABORTED, std::string());
1950 EXPECT_FALSE(spdy_stream1);
1951 EXPECT_FALSE(spdy_stream2);
1953 EXPECT_TRUE(delegate1.StreamIsClosed());
1954 EXPECT_TRUE(delegate2.StreamIsClosed());
1956 base::RunLoop().RunUntilIdle();
1957 EXPECT_FALSE(session_);
1960 // Create two streams that are set to re-close themselves on close,
1961 // activate them, and then close the session. Nothing should blow up.
1962 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
1963 session_deps_.host_resolver->set_synchronous_mode(true);
1965 scoped_ptr<SpdyFrame> req1(
1966 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
1967 scoped_ptr<SpdyFrame> req2(
1968 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
1969 MockWrite writes[] = {
1970 CreateMockWrite(*req1, 0),
1971 CreateMockWrite(*req2, 1),
1974 MockRead reads[] = {
1975 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
1978 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1979 session_deps_.socket_factory->AddSocketDataProvider(&data);
1981 CreateNetworkSession();
1982 CreateInsecureSpdySession();
1984 GURL url1(kDefaultURL);
1985 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1986 SPDY_REQUEST_RESPONSE_STREAM, session_, url1, MEDIUM, BoundNetLog());
1987 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1988 EXPECT_EQ(0u, spdy_stream1->stream_id());
1990 GURL url2(kDefaultURL);
1991 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
1992 SPDY_REQUEST_RESPONSE_STREAM, session_, url2, MEDIUM, BoundNetLog());
1993 ASSERT_TRUE(spdy_stream2.get() != nullptr);
1994 EXPECT_EQ(0u, spdy_stream2->stream_id());
1996 test::ClosingDelegate delegate1(spdy_stream1);
1997 spdy_stream1->SetDelegate(&delegate1);
1999 test::ClosingDelegate delegate2(spdy_stream2);
2000 spdy_stream2->SetDelegate(&delegate2);
2002 scoped_ptr<SpdyHeaderBlock> headers(
2003 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2004 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2005 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2007 scoped_ptr<SpdyHeaderBlock> headers2(
2008 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2009 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2010 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2012 // Ensure that the streams have not yet been activated and assigned an id.
2013 EXPECT_EQ(0u, spdy_stream1->stream_id());
2014 EXPECT_EQ(0u, spdy_stream2->stream_id());
2016 base::RunLoop().RunUntilIdle();
2018 EXPECT_EQ(1u, spdy_stream1->stream_id());
2019 EXPECT_EQ(3u, spdy_stream2->stream_id());
2021 // Ensure we don't crash while closing the session.
2022 session_->CloseSessionOnError(ERR_ABORTED, std::string());
2024 EXPECT_FALSE(spdy_stream1);
2025 EXPECT_FALSE(spdy_stream2);
2027 EXPECT_TRUE(delegate1.StreamIsClosed());
2028 EXPECT_TRUE(delegate2.StreamIsClosed());
2030 EXPECT_TRUE(session_);
2031 data.CompleteRead();
2032 base::RunLoop().RunUntilIdle();
2033 EXPECT_FALSE(session_);
2036 // Create two streams that are set to close each other on close,
2037 // activate them, and then close the session. Nothing should blow up.
2038 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2039 session_deps_.host_resolver->set_synchronous_mode(true);
2041 scoped_ptr<SpdyFrame> req1(
2042 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2043 scoped_ptr<SpdyFrame> req2(
2044 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
2045 MockWrite writes[] = {
2046 CreateMockWrite(*req1, 0),
2047 CreateMockWrite(*req2, 1),
2050 MockRead reads[] = {
2051 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
2054 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2055 session_deps_.socket_factory->AddSocketDataProvider(&data);
2057 CreateNetworkSession();
2058 CreateInsecureSpdySession();
2060 GURL url1(kDefaultURL);
2061 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2062 SPDY_REQUEST_RESPONSE_STREAM, session_, url1, MEDIUM, BoundNetLog());
2063 ASSERT_TRUE(spdy_stream1);
2064 EXPECT_EQ(0u, spdy_stream1->stream_id());
2066 GURL url2(kDefaultURL);
2067 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
2068 SPDY_REQUEST_RESPONSE_STREAM, session_, url2, MEDIUM, BoundNetLog());
2069 ASSERT_TRUE(spdy_stream2);
2070 EXPECT_EQ(0u, spdy_stream2->stream_id());
2072 // Make |spdy_stream1| close |spdy_stream2|.
2073 test::ClosingDelegate delegate1(spdy_stream2);
2074 spdy_stream1->SetDelegate(&delegate1);
2076 // Make |spdy_stream2| close |spdy_stream1|.
2077 test::ClosingDelegate delegate2(spdy_stream1);
2078 spdy_stream2->SetDelegate(&delegate2);
2080 scoped_ptr<SpdyHeaderBlock> headers(
2081 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2082 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2083 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2085 scoped_ptr<SpdyHeaderBlock> headers2(
2086 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2087 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2088 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2090 // Ensure that the streams have not yet been activated and assigned an id.
2091 EXPECT_EQ(0u, spdy_stream1->stream_id());
2092 EXPECT_EQ(0u, spdy_stream2->stream_id());
2094 base::RunLoop().RunUntilIdle();
2096 EXPECT_EQ(1u, spdy_stream1->stream_id());
2097 EXPECT_EQ(3u, spdy_stream2->stream_id());
2099 // Ensure we don't crash while closing the session.
2100 session_->CloseSessionOnError(ERR_ABORTED, std::string());
2102 EXPECT_FALSE(spdy_stream1);
2103 EXPECT_FALSE(spdy_stream2);
2105 EXPECT_TRUE(delegate1.StreamIsClosed());
2106 EXPECT_TRUE(delegate2.StreamIsClosed());
2108 EXPECT_TRUE(session_);
2109 data.CompleteRead();
2110 base::RunLoop().RunUntilIdle();
2111 EXPECT_FALSE(session_);
2114 // Delegate that closes a given session when the stream is closed.
2115 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2116 public:
2117 SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2118 const base::WeakPtr<SpdySession>& session_to_close)
2119 : StreamDelegateDoNothing(stream),
2120 session_to_close_(session_to_close) {}
2122 ~SessionClosingDelegate() override {}
2124 void OnClose(int status) override {
2125 session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2128 private:
2129 base::WeakPtr<SpdySession> session_to_close_;
2132 // Close an activated stream that closes its session. Nothing should
2133 // blow up. This is a regression test for https://crbug.com/263691.
2134 TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2135 session_deps_.host_resolver->set_synchronous_mode(true);
2137 scoped_ptr<SpdyFrame> req(
2138 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2139 scoped_ptr<SpdyFrame> rst(
2140 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2141 scoped_ptr<SpdyFrame> goaway(
2142 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2143 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2144 // despite being queued second.
2145 MockWrite writes[] = {
2146 CreateMockWrite(*req, 0),
2147 CreateMockWrite(*goaway, 1),
2148 CreateMockWrite(*rst, 3),
2151 MockRead reads[] = {
2152 MockRead(ASYNC, 0, 2) // EOF
2154 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2155 session_deps_.socket_factory->AddSocketDataProvider(&data);
2157 CreateNetworkSession();
2158 CreateInsecureSpdySession();
2160 GURL url(kDefaultURL);
2161 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
2162 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
2163 ASSERT_TRUE(spdy_stream.get() != nullptr);
2164 EXPECT_EQ(0u, spdy_stream->stream_id());
2166 SessionClosingDelegate delegate(spdy_stream, session_);
2167 spdy_stream->SetDelegate(&delegate);
2169 scoped_ptr<SpdyHeaderBlock> headers(
2170 spdy_util_.ConstructGetHeaderBlock(url.spec()));
2171 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2172 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2174 EXPECT_EQ(0u, spdy_stream->stream_id());
2176 base::RunLoop().RunUntilIdle();
2178 EXPECT_EQ(1u, spdy_stream->stream_id());
2180 // Ensure we don't crash while closing the stream (which closes the
2181 // session).
2182 spdy_stream->Cancel();
2184 EXPECT_FALSE(spdy_stream);
2185 EXPECT_TRUE(delegate.StreamIsClosed());
2187 // Write the RST_STREAM & GOAWAY.
2188 base::RunLoop().RunUntilIdle();
2189 EXPECT_TRUE(data.AllWriteDataConsumed());
2190 EXPECT_TRUE(data.AllReadDataConsumed());
2193 TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2194 session_deps_.host_resolver->set_synchronous_mode(true);
2196 SequencedSocketData data(nullptr, 0, nullptr, 0);
2197 session_deps_.socket_factory->AddSocketDataProvider(&data);
2199 // Load a cert that is valid for:
2200 // www.example.org
2201 // mail.example.org
2202 // www.example.com
2203 base::FilePath certs_dir = GetTestCertsDirectory();
2204 scoped_refptr<X509Certificate> test_cert(
2205 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2206 ASSERT_NE(static_cast<X509Certificate*>(nullptr), test_cert.get());
2208 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2209 ssl.cert = test_cert;
2210 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2212 CreateNetworkSession();
2214 session_ = CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2216 EXPECT_TRUE(session_->VerifyDomainAuthentication("www.example.org"));
2217 EXPECT_TRUE(session_->VerifyDomainAuthentication("mail.example.org"));
2218 EXPECT_TRUE(session_->VerifyDomainAuthentication("mail.example.com"));
2219 EXPECT_FALSE(session_->VerifyDomainAuthentication("mail.google.com"));
2222 TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2223 session_deps_.host_resolver->set_synchronous_mode(true);
2225 SequencedSocketData data(nullptr, 0, nullptr, 0);
2226 session_deps_.socket_factory->AddSocketDataProvider(&data);
2228 // Load a cert that is valid for:
2229 // www.example.org
2230 // mail.example.org
2231 // www.example.com
2232 base::FilePath certs_dir = GetTestCertsDirectory();
2233 scoped_refptr<X509Certificate> test_cert(
2234 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2235 ASSERT_NE(static_cast<X509Certificate*>(nullptr), test_cert.get());
2237 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2238 ssl.channel_id_sent = true;
2239 ssl.cert = test_cert;
2240 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2242 CreateNetworkSession();
2244 session_ = CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2246 EXPECT_TRUE(session_->VerifyDomainAuthentication("www.example.org"));
2247 EXPECT_TRUE(session_->VerifyDomainAuthentication("mail.example.org"));
2248 EXPECT_FALSE(session_->VerifyDomainAuthentication("mail.example.com"));
2249 EXPECT_FALSE(session_->VerifyDomainAuthentication("mail.google.com"));
2252 TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2253 // TODO(rtenneti): Define a helper class/methods and move the common code in
2254 // this file.
2255 SettingsMap new_settings;
2256 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2257 const uint32 max_concurrent_streams = 1;
2258 new_settings[kSpdySettingsIds1] =
2259 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2261 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
2262 scoped_ptr<SpdyFrame> req1(
2263 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
2264 scoped_ptr<SpdyFrame> req2(
2265 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST, true));
2266 scoped_ptr<SpdyFrame> req3(
2267 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 5, LOWEST, true));
2268 MockWrite writes[] = {
2269 CreateMockWrite(*settings_ack, 1),
2270 CreateMockWrite(*req1, 2),
2271 CreateMockWrite(*req2, 5),
2272 CreateMockWrite(*req3, 8),
2275 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2276 // streams to 1.
2277 scoped_ptr<SpdyFrame> settings_frame(
2278 spdy_util_.ConstructSpdySettings(new_settings));
2280 scoped_ptr<SpdyFrame> resp1(
2281 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2282 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2284 scoped_ptr<SpdyFrame> resp2(
2285 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
2286 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2288 scoped_ptr<SpdyFrame> resp3(
2289 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 5));
2290 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2292 MockRead reads[] = {
2293 CreateMockRead(*settings_frame, 0),
2294 CreateMockRead(*resp1, 3),
2295 CreateMockRead(*body1, 4),
2296 CreateMockRead(*resp2, 6),
2297 CreateMockRead(*body2, 7),
2298 CreateMockRead(*resp3, 9),
2299 CreateMockRead(*body3, 10),
2300 MockRead(ASYNC, ERR_IO_PENDING, 11),
2301 MockRead(ASYNC, 0, 12) // EOF
2304 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2305 session_deps_.socket_factory->AddSocketDataProvider(&data);
2307 CreateNetworkSession();
2308 CreateInsecureSpdySession();
2310 // Read the settings frame.
2311 base::RunLoop().RunUntilIdle();
2313 GURL url1(kDefaultURL);
2314 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2315 SPDY_REQUEST_RESPONSE_STREAM, session_, url1, LOWEST, BoundNetLog());
2316 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2317 EXPECT_EQ(0u, spdy_stream1->stream_id());
2318 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2319 spdy_stream1->SetDelegate(&delegate1);
2321 TestCompletionCallback callback2;
2322 GURL url2(kDefaultURL);
2323 SpdyStreamRequest request2;
2324 ASSERT_EQ(ERR_IO_PENDING,
2325 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, url2,
2326 LOWEST, BoundNetLog(), callback2.callback()));
2328 TestCompletionCallback callback3;
2329 GURL url3(kDefaultURL);
2330 SpdyStreamRequest request3;
2331 ASSERT_EQ(ERR_IO_PENDING,
2332 request3.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, url3,
2333 LOWEST, BoundNetLog(), callback3.callback()));
2335 EXPECT_EQ(0u, session_->num_active_streams());
2336 EXPECT_EQ(1u, session_->num_created_streams());
2337 EXPECT_EQ(2u, session_->pending_create_stream_queue_size(LOWEST));
2339 scoped_ptr<SpdyHeaderBlock> headers(
2340 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2341 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2342 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2344 // Run until 1st stream is activated and then closed.
2345 EXPECT_EQ(0u, delegate1.stream_id());
2346 base::RunLoop().RunUntilIdle();
2347 EXPECT_FALSE(spdy_stream1);
2348 EXPECT_EQ(1u, delegate1.stream_id());
2350 EXPECT_EQ(0u, session_->num_active_streams());
2351 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(LOWEST));
2353 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2354 // create the 2nd stream.
2355 base::RunLoop().RunUntilIdle();
2357 EXPECT_EQ(0u, session_->num_active_streams());
2358 EXPECT_EQ(1u, session_->num_created_streams());
2359 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(LOWEST));
2361 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2362 test::StreamDelegateDoNothing delegate2(stream2);
2363 stream2->SetDelegate(&delegate2);
2364 scoped_ptr<SpdyHeaderBlock> headers2(
2365 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2366 stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2367 EXPECT_TRUE(stream2->HasUrlFromHeaders());
2369 // Run until 2nd stream is activated and then closed.
2370 EXPECT_EQ(0u, delegate2.stream_id());
2371 base::RunLoop().RunUntilIdle();
2372 EXPECT_FALSE(stream2);
2373 EXPECT_EQ(3u, delegate2.stream_id());
2375 EXPECT_EQ(0u, session_->num_active_streams());
2376 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2378 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2379 // create the 3rd stream.
2380 base::RunLoop().RunUntilIdle();
2382 EXPECT_EQ(0u, session_->num_active_streams());
2383 EXPECT_EQ(1u, session_->num_created_streams());
2384 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2386 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2387 test::StreamDelegateDoNothing delegate3(stream3);
2388 stream3->SetDelegate(&delegate3);
2389 scoped_ptr<SpdyHeaderBlock> headers3(
2390 spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2391 stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2392 EXPECT_TRUE(stream3->HasUrlFromHeaders());
2394 // Run until 2nd stream is activated and then closed.
2395 EXPECT_EQ(0u, delegate3.stream_id());
2396 base::RunLoop().RunUntilIdle();
2397 EXPECT_FALSE(stream3);
2398 EXPECT_EQ(5u, delegate3.stream_id());
2400 EXPECT_EQ(0u, session_->num_active_streams());
2401 EXPECT_EQ(0u, session_->num_created_streams());
2402 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2404 data.CompleteRead();
2405 base::RunLoop().RunUntilIdle();
2408 TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2409 session_deps_.host_resolver->set_synchronous_mode(true);
2411 MockRead reads[] = {
2412 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2415 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
2416 session_deps_.socket_factory->AddSocketDataProvider(&data);
2418 CreateNetworkSession();
2419 CreateInsecureSpdySession();
2421 // Leave room for only one more stream to be created.
2422 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2423 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
2424 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2425 ASSERT_TRUE(spdy_stream != nullptr);
2428 GURL url1(kDefaultURL);
2429 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2430 SPDY_BIDIRECTIONAL_STREAM, session_, url1, LOWEST, BoundNetLog());
2431 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2432 EXPECT_EQ(0u, spdy_stream1->stream_id());
2434 TestCompletionCallback callback2;
2435 GURL url2(kDefaultURL);
2436 SpdyStreamRequest request2;
2437 ASSERT_EQ(ERR_IO_PENDING,
2438 request2.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, url2,
2439 LOWEST, BoundNetLog(), callback2.callback()));
2441 TestCompletionCallback callback3;
2442 GURL url3(kDefaultURL);
2443 SpdyStreamRequest request3;
2444 ASSERT_EQ(ERR_IO_PENDING,
2445 request3.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, url3,
2446 LOWEST, BoundNetLog(), callback3.callback()));
2448 EXPECT_EQ(0u, session_->num_active_streams());
2449 EXPECT_EQ(kInitialMaxConcurrentStreams, session_->num_created_streams());
2450 EXPECT_EQ(2u, session_->pending_create_stream_queue_size(LOWEST));
2452 // Cancel the first stream; this will allow the second stream to be created.
2453 EXPECT_TRUE(spdy_stream1);
2454 spdy_stream1->Cancel();
2455 EXPECT_FALSE(spdy_stream1);
2457 EXPECT_EQ(OK, callback2.WaitForResult());
2458 EXPECT_EQ(0u, session_->num_active_streams());
2459 EXPECT_EQ(kInitialMaxConcurrentStreams, session_->num_created_streams());
2460 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(LOWEST));
2462 // Cancel the second stream; this will allow the third stream to be created.
2463 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2464 spdy_stream2->Cancel();
2465 EXPECT_FALSE(spdy_stream2);
2467 EXPECT_EQ(OK, callback3.WaitForResult());
2468 EXPECT_EQ(0u, session_->num_active_streams());
2469 EXPECT_EQ(kInitialMaxConcurrentStreams, session_->num_created_streams());
2470 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2472 // Cancel the third stream.
2473 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2474 spdy_stream3->Cancel();
2475 EXPECT_FALSE(spdy_stream3);
2476 EXPECT_EQ(0u, session_->num_active_streams());
2477 EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session_->num_created_streams());
2478 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2481 // Test that SpdySession::DoReadLoop reads data from the socket
2482 // without yielding. This test makes 32k - 1 bytes of data available
2483 // on the socket for reading. It then verifies that it has read all
2484 // the available data without yielding.
2485 TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2486 session_deps_.host_resolver->set_synchronous_mode(true);
2488 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2490 scoped_ptr<SpdyFrame> req1(
2491 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2492 MockWrite writes[] = {
2493 CreateMockWrite(*req1, 0),
2496 // Build buffer of size kYieldAfterBytesRead / 4
2497 // (-spdy_data_frame_size).
2498 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
2499 const int kPayloadSize =
2500 kYieldAfterBytesRead / 4 - framer.GetControlFrameHeaderSize();
2501 TestDataStream test_stream;
2502 scoped_refptr<IOBuffer> payload(new IOBuffer(kPayloadSize));
2503 char* payload_data = payload->data();
2504 test_stream.GetBytes(payload_data, kPayloadSize);
2506 scoped_ptr<SpdyFrame> partial_data_frame(
2507 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2508 scoped_ptr<SpdyFrame> finish_data_frame(
2509 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2511 scoped_ptr<SpdyFrame> resp1(
2512 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2514 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2515 // bytes.
2516 MockRead reads[] = {
2517 CreateMockRead(*resp1, 1),
2518 MockRead(ASYNC, ERR_IO_PENDING, 2),
2519 CreateMockRead(*partial_data_frame, 3),
2520 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2521 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2522 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2523 MockRead(ASYNC, 0, 7) // EOF
2526 // Create SpdySession and SpdyStream and send the request.
2527 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2528 session_deps_.socket_factory->AddSocketDataProvider(&data);
2530 CreateNetworkSession();
2531 CreateInsecureSpdySession();
2533 GURL url1(kDefaultURL);
2534 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2535 SPDY_REQUEST_RESPONSE_STREAM, session_, url1, MEDIUM, BoundNetLog());
2536 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2537 EXPECT_EQ(0u, spdy_stream1->stream_id());
2538 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2539 spdy_stream1->SetDelegate(&delegate1);
2541 scoped_ptr<SpdyHeaderBlock> headers1(
2542 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2543 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2544 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2546 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2547 // post a task.
2548 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2550 // Run until 1st read.
2551 EXPECT_EQ(0u, delegate1.stream_id());
2552 base::RunLoop().RunUntilIdle();
2553 EXPECT_EQ(1u, delegate1.stream_id());
2554 EXPECT_EQ(0u, observer.executed_count());
2556 // Read all the data and verify SpdySession::DoReadLoop has not
2557 // posted a task.
2558 data.CompleteRead();
2559 base::RunLoop().RunUntilIdle();
2560 EXPECT_FALSE(spdy_stream1);
2562 // Verify task observer's executed_count is zero, which indicates DoRead read
2563 // all the available data.
2564 EXPECT_EQ(0u, observer.executed_count());
2565 EXPECT_TRUE(data.AllWriteDataConsumed());
2566 EXPECT_TRUE(data.AllReadDataConsumed());
2569 // Test that SpdySession::DoReadLoop yields if more than
2570 // |kYieldAfterDurationMilliseconds| has passed. This test uses a mock time
2571 // function that makes the response frame look very slow to read.
2572 TEST_P(SpdySessionTest, TestYieldingSlowReads) {
2573 session_deps_.host_resolver->set_synchronous_mode(true);
2574 session_deps_.time_func = SlowReads;
2576 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2578 scoped_ptr<SpdyFrame> req1(
2579 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2580 MockWrite writes[] = {
2581 CreateMockWrite(*req1, 0),
2584 scoped_ptr<SpdyFrame> resp1(
2585 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2587 MockRead reads[] = {
2588 CreateMockRead(*resp1, 1), MockRead(ASYNC, 0, 2) // EOF
2591 // Create SpdySession and SpdyStream and send the request.
2592 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2593 session_deps_.socket_factory->AddSocketDataProvider(&data);
2595 CreateNetworkSession();
2596 CreateInsecureSpdySession();
2598 GURL url1(kDefaultURL);
2599 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2600 SPDY_REQUEST_RESPONSE_STREAM, session_, url1, MEDIUM, BoundNetLog());
2601 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2602 EXPECT_EQ(0u, spdy_stream1->stream_id());
2603 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2604 spdy_stream1->SetDelegate(&delegate1);
2606 scoped_ptr<SpdyHeaderBlock> headers1(
2607 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2608 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2609 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2611 // Set up the TaskObserver to verify that SpdySession::DoReadLoop posts a
2612 // task.
2613 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2615 EXPECT_EQ(0u, delegate1.stream_id());
2616 EXPECT_EQ(0u, observer.executed_count());
2618 // Read all the data and verify that SpdySession::DoReadLoop has posted a
2619 // task.
2620 base::RunLoop().RunUntilIdle();
2621 EXPECT_EQ(1u, delegate1.stream_id());
2622 EXPECT_FALSE(spdy_stream1);
2624 // Verify task that the observer's executed_count is 1, which indicates DoRead
2625 // has posted only one task and thus yielded though there is data available
2626 // for it to read.
2627 EXPECT_EQ(1u, observer.executed_count());
2628 EXPECT_TRUE(data.AllWriteDataConsumed());
2629 EXPECT_TRUE(data.AllReadDataConsumed());
2632 // Test that SpdySession::DoReadLoop yields while reading the
2633 // data. This test makes 32k + 1 bytes of data available on the socket
2634 // for reading. It then verifies that DoRead has yielded even though
2635 // there is data available for it to read (i.e, socket()->Read didn't
2636 // return ERR_IO_PENDING during socket reads).
2637 TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2638 session_deps_.host_resolver->set_synchronous_mode(true);
2640 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2642 scoped_ptr<SpdyFrame> req1(
2643 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2644 MockWrite writes[] = {
2645 CreateMockWrite(*req1, 0),
2648 // Build buffer of size kYieldAfterBytesRead / 4
2649 // (-spdy_data_frame_size).
2650 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
2651 const int kPayloadSize =
2652 kYieldAfterBytesRead / 4 - framer.GetControlFrameHeaderSize();
2653 TestDataStream test_stream;
2654 scoped_refptr<IOBuffer> payload(new IOBuffer(kPayloadSize));
2655 char* payload_data = payload->data();
2656 test_stream.GetBytes(payload_data, kPayloadSize);
2658 scoped_ptr<SpdyFrame> partial_data_frame(
2659 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2660 scoped_ptr<SpdyFrame> finish_data_frame(
2661 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2663 scoped_ptr<SpdyFrame> resp1(
2664 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2666 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2667 MockRead reads[] = {
2668 CreateMockRead(*resp1, 1),
2669 MockRead(ASYNC, ERR_IO_PENDING, 2),
2670 CreateMockRead(*partial_data_frame, 3),
2671 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2672 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2673 CreateMockRead(*partial_data_frame, 6, SYNCHRONOUS),
2674 CreateMockRead(*finish_data_frame, 7, SYNCHRONOUS),
2675 MockRead(ASYNC, 0, 8) // EOF
2678 // Create SpdySession and SpdyStream and send the request.
2679 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2680 session_deps_.socket_factory->AddSocketDataProvider(&data);
2682 CreateNetworkSession();
2683 CreateInsecureSpdySession();
2685 GURL url1(kDefaultURL);
2686 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2687 SPDY_REQUEST_RESPONSE_STREAM, session_, url1, MEDIUM, BoundNetLog());
2688 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2689 EXPECT_EQ(0u, spdy_stream1->stream_id());
2690 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2691 spdy_stream1->SetDelegate(&delegate1);
2693 scoped_ptr<SpdyHeaderBlock> headers1(
2694 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2695 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2696 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2698 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a task.
2699 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2701 // Run until 1st read.
2702 EXPECT_EQ(0u, delegate1.stream_id());
2703 base::RunLoop().RunUntilIdle();
2704 EXPECT_EQ(1u, delegate1.stream_id());
2705 EXPECT_EQ(0u, observer.executed_count());
2707 // Read all the data and verify SpdySession::DoReadLoop has posted a task.
2708 data.CompleteRead();
2709 base::RunLoop().RunUntilIdle();
2710 EXPECT_FALSE(spdy_stream1);
2712 // Verify task observer's executed_count is 1, which indicates DoRead has
2713 // posted only one task and thus yielded though there is data available for it
2714 // to read.
2715 EXPECT_EQ(1u, observer.executed_count());
2716 EXPECT_TRUE(data.AllWriteDataConsumed());
2717 EXPECT_TRUE(data.AllReadDataConsumed());
2720 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2721 // + async, by doing the following MockReads.
2723 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2724 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2726 // The above reads 26K synchronously. Since that is less that 32K, we
2727 // will attempt to read again. However, that DoRead() will return
2728 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2729 // yield. When we come back, DoRead() will read the results from the
2730 // async read, and rest of the data synchronously.
2731 TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2732 session_deps_.host_resolver->set_synchronous_mode(true);
2734 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2736 scoped_ptr<SpdyFrame> req1(
2737 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2738 MockWrite writes[] = {
2739 CreateMockWrite(*req1, 0),
2742 // Build buffer of size kYieldAfterBytesRead / 4
2743 // (-spdy_data_frame_size).
2744 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
2745 TestDataStream test_stream;
2746 const int kEightKPayloadSize =
2747 kYieldAfterBytesRead / 4 - framer.GetControlFrameHeaderSize();
2748 scoped_refptr<IOBuffer> eightk_payload(new IOBuffer(kEightKPayloadSize));
2749 char* eightk_payload_data = eightk_payload->data();
2750 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2752 // Build buffer of 2k size.
2753 TestDataStream test_stream2;
2754 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2755 scoped_refptr<IOBuffer> twok_payload(new IOBuffer(kTwoKPayloadSize));
2756 char* twok_payload_data = twok_payload->data();
2757 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2759 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2760 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2761 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2762 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2763 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2764 1, "h", 1, DATA_FLAG_FIN));
2766 scoped_ptr<SpdyFrame> resp1(
2767 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2769 MockRead reads[] = {
2770 CreateMockRead(*resp1, 1),
2771 MockRead(ASYNC, ERR_IO_PENDING, 2),
2772 CreateMockRead(*eightk_data_frame, 3),
2773 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2774 CreateMockRead(*eightk_data_frame, 5, SYNCHRONOUS),
2775 CreateMockRead(*twok_data_frame, 6, SYNCHRONOUS),
2776 CreateMockRead(*eightk_data_frame, 7, ASYNC),
2777 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2778 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2779 CreateMockRead(*eightk_data_frame, 10, SYNCHRONOUS),
2780 CreateMockRead(*twok_data_frame, 11, SYNCHRONOUS),
2781 CreateMockRead(*finish_data_frame, 12, SYNCHRONOUS),
2782 MockRead(ASYNC, 0, 13) // EOF
2785 // Create SpdySession and SpdyStream and send the request.
2786 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2787 session_deps_.socket_factory->AddSocketDataProvider(&data);
2789 CreateNetworkSession();
2790 CreateInsecureSpdySession();
2792 GURL url1(kDefaultURL);
2793 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2794 SPDY_REQUEST_RESPONSE_STREAM, session_, url1, MEDIUM, BoundNetLog());
2795 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2796 EXPECT_EQ(0u, spdy_stream1->stream_id());
2797 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2798 spdy_stream1->SetDelegate(&delegate1);
2800 scoped_ptr<SpdyHeaderBlock> headers1(
2801 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2802 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2803 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2805 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2806 // posting of tasks.
2807 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2809 // Run until 1st read.
2810 EXPECT_EQ(0u, delegate1.stream_id());
2811 base::RunLoop().RunUntilIdle();
2812 EXPECT_EQ(1u, delegate1.stream_id());
2813 EXPECT_EQ(0u, observer.executed_count());
2815 // Read all the data and verify SpdySession::DoReadLoop has posted a
2816 // task.
2817 data.CompleteRead();
2818 base::RunLoop().RunUntilIdle();
2819 EXPECT_FALSE(spdy_stream1);
2821 // Verify task observer's executed_count is 1, which indicates DoRead has
2822 // posted only one task and thus yielded though there is data available for
2823 // it to read.
2824 EXPECT_EQ(1u, observer.executed_count());
2825 EXPECT_TRUE(data.AllWriteDataConsumed());
2826 EXPECT_TRUE(data.AllReadDataConsumed());
2829 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2830 // nothing blows up.
2831 TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
2832 session_deps_.host_resolver->set_synchronous_mode(true);
2834 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2836 scoped_ptr<SpdyFrame> req1(
2837 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2838 MockWrite writes[] = {
2839 CreateMockWrite(*req1, 0),
2842 scoped_ptr<SpdyFrame> resp1(
2843 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2844 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2845 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
2847 MockRead reads[] = {
2848 CreateMockRead(*resp1, 1),
2849 MockRead(ASYNC, ERR_IO_PENDING, 2),
2850 CreateMockRead(*body1, 3),
2851 CreateMockRead(*goaway, 4),
2854 // Create SpdySession and SpdyStream and send the request.
2855 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2856 session_deps_.socket_factory->AddSocketDataProvider(&data);
2858 CreateNetworkSession();
2859 CreateInsecureSpdySession();
2861 GURL url1(kDefaultURL);
2862 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2863 SPDY_REQUEST_RESPONSE_STREAM, session_, url1, MEDIUM, BoundNetLog());
2864 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2865 spdy_stream1->SetDelegate(&delegate1);
2866 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2867 EXPECT_EQ(0u, spdy_stream1->stream_id());
2869 scoped_ptr<SpdyHeaderBlock> headers1(
2870 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2871 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2872 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2874 // Run until 1st read.
2875 EXPECT_EQ(0u, spdy_stream1->stream_id());
2876 base::RunLoop().RunUntilIdle();
2877 EXPECT_EQ(1u, spdy_stream1->stream_id());
2879 // Run until GoAway.
2880 data.CompleteRead();
2881 base::RunLoop().RunUntilIdle();
2882 EXPECT_FALSE(spdy_stream1);
2883 EXPECT_TRUE(data.AllWriteDataConsumed());
2884 EXPECT_TRUE(data.AllReadDataConsumed());
2885 EXPECT_FALSE(session_);
2888 // Within this framework, a SpdySession should be initialized with
2889 // flow control disabled for protocol version 2, with flow control
2890 // enabled only for streams for protocol version 3, and with flow
2891 // control enabled for streams and sessions for higher versions.
2892 TEST_P(SpdySessionTest, ProtocolNegotiation) {
2893 session_deps_.host_resolver->set_synchronous_mode(true);
2895 MockRead reads[] = {
2896 MockRead(SYNCHRONOUS, 0, 0) // EOF
2898 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
2899 session_deps_.socket_factory->AddSocketDataProvider(&data);
2901 CreateNetworkSession();
2902 session_ = CreateFakeSpdySession(spdy_session_pool_, key_);
2904 EXPECT_EQ(spdy_util_.spdy_version(),
2905 session_->buffered_spdy_framer_->protocol_version());
2906 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
2907 session_->flow_control_state());
2908 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
2909 session_->session_send_window_size_);
2910 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
2911 session_->session_recv_window_size_);
2912 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
2915 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2916 // pointers to the idle session are currently held.
2917 TEST_P(SpdySessionTest, CloseOneIdleConnection) {
2918 ClientSocketPoolManager::set_max_sockets_per_group(
2919 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2920 ClientSocketPoolManager::set_max_sockets_per_pool(
2921 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2923 MockRead reads[] = {
2924 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2926 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
2927 session_deps_.socket_factory->AddSocketDataProvider(&data);
2928 session_deps_.socket_factory->AddSocketDataProvider(&data);
2930 CreateNetworkSession();
2932 TransportClientSocketPool* pool =
2933 http_session_->GetTransportSocketPool(
2934 HttpNetworkSession::NORMAL_SOCKET_POOL);
2936 // Create an idle SPDY session.
2937 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2938 PRIVACY_MODE_DISABLED);
2939 base::WeakPtr<SpdySession> session1 =
2940 ::net::CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2941 EXPECT_FALSE(pool->IsStalled());
2943 // Trying to create a new connection should cause the pool to be stalled, and
2944 // post a task asynchronously to try and close the session.
2945 TestCompletionCallback callback2;
2946 HostPortPair host_port2("2.com", 80);
2947 scoped_refptr<TransportSocketParams> params2(
2948 new TransportSocketParams(
2949 host_port2, false, false, OnHostResolutionCallback(),
2950 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
2951 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
2952 EXPECT_EQ(ERR_IO_PENDING,
2953 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
2954 callback2.callback(), pool, BoundNetLog()));
2955 EXPECT_TRUE(pool->IsStalled());
2957 // The socket pool should close the connection asynchronously and establish a
2958 // new connection.
2959 EXPECT_EQ(OK, callback2.WaitForResult());
2960 EXPECT_FALSE(pool->IsStalled());
2961 EXPECT_FALSE(session1);
2964 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2965 // pointers to the idle session are currently held, in the case the SPDY session
2966 // has an alias.
2967 TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
2968 ClientSocketPoolManager::set_max_sockets_per_group(
2969 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2970 ClientSocketPoolManager::set_max_sockets_per_pool(
2971 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2973 MockRead reads[] = {
2974 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2976 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
2977 session_deps_.socket_factory->AddSocketDataProvider(&data);
2978 session_deps_.socket_factory->AddSocketDataProvider(&data);
2980 session_deps_.host_resolver->set_synchronous_mode(true);
2981 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2982 "1.com", "192.168.0.2", std::string());
2983 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2984 "2.com", "192.168.0.2", std::string());
2985 // Not strictly needed.
2986 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2987 "3.com", "192.168.0.3", std::string());
2989 CreateNetworkSession();
2991 TransportClientSocketPool* pool =
2992 http_session_->GetTransportSocketPool(
2993 HttpNetworkSession::NORMAL_SOCKET_POOL);
2995 // Create an idle SPDY session.
2996 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2997 PRIVACY_MODE_DISABLED);
2998 base::WeakPtr<SpdySession> session1 =
2999 ::net::CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3000 EXPECT_FALSE(pool->IsStalled());
3002 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3003 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3004 PRIVACY_MODE_DISABLED);
3005 HostResolver::RequestInfo info(key2.host_port_pair());
3006 AddressList addresses;
3007 // Pre-populate the DNS cache, since a synchronous resolution is required in
3008 // order to create the alias.
3009 session_deps_.host_resolver->Resolve(info, DEFAULT_PRIORITY, &addresses,
3010 CompletionCallback(), nullptr,
3011 BoundNetLog());
3012 // Get a session for |key2|, which should return the session created earlier.
3013 base::WeakPtr<SpdySession> session2 =
3014 spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3015 ASSERT_EQ(session1.get(), session2.get());
3016 EXPECT_FALSE(pool->IsStalled());
3018 // Trying to create a new connection should cause the pool to be stalled, and
3019 // post a task asynchronously to try and close the session.
3020 TestCompletionCallback callback3;
3021 HostPortPair host_port3("3.com", 80);
3022 scoped_refptr<TransportSocketParams> params3(
3023 new TransportSocketParams(
3024 host_port3, false, false, OnHostResolutionCallback(),
3025 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3026 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3027 EXPECT_EQ(ERR_IO_PENDING,
3028 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3029 callback3.callback(), pool, BoundNetLog()));
3030 EXPECT_TRUE(pool->IsStalled());
3032 // The socket pool should close the connection asynchronously and establish a
3033 // new connection.
3034 EXPECT_EQ(OK, callback3.WaitForResult());
3035 EXPECT_FALSE(pool->IsStalled());
3036 EXPECT_FALSE(session1);
3037 EXPECT_FALSE(session2);
3040 // Tests that when a SPDY session becomes idle, it closes itself if there is
3041 // a lower layer pool stalled on the per-pool socket limit.
3042 TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3043 ClientSocketPoolManager::set_max_sockets_per_group(
3044 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3045 ClientSocketPoolManager::set_max_sockets_per_pool(
3046 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3048 MockRead reads[] = {
3049 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3051 scoped_ptr<SpdyFrame> req1(
3052 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
3053 scoped_ptr<SpdyFrame> cancel1(
3054 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3055 MockWrite writes[] = {
3056 CreateMockWrite(*req1, 1),
3057 CreateMockWrite(*cancel1, 1),
3059 StaticSocketDataProvider data(reads, arraysize(reads),
3060 writes, arraysize(writes));
3061 session_deps_.socket_factory->AddSocketDataProvider(&data);
3063 MockRead http_reads[] = {
3064 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3066 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
3068 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3071 CreateNetworkSession();
3073 TransportClientSocketPool* pool =
3074 http_session_->GetTransportSocketPool(
3075 HttpNetworkSession::NORMAL_SOCKET_POOL);
3077 // Create a SPDY session.
3078 GURL url1(kDefaultURL);
3079 SpdySessionKey key1(HostPortPair(url1.host(), 80),
3080 ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3081 base::WeakPtr<SpdySession> session1 =
3082 ::net::CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3083 EXPECT_FALSE(pool->IsStalled());
3085 // Create a stream using the session, and send a request.
3087 TestCompletionCallback callback1;
3088 base::WeakPtr<SpdyStream> spdy_stream1 =
3089 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3090 session1, url1, DEFAULT_PRIORITY,
3091 BoundNetLog());
3092 ASSERT_TRUE(spdy_stream1.get());
3093 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3094 spdy_stream1->SetDelegate(&delegate1);
3096 scoped_ptr<SpdyHeaderBlock> headers1(
3097 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3098 EXPECT_EQ(ERR_IO_PENDING,
3099 spdy_stream1->SendRequestHeaders(
3100 headers1.Pass(), NO_MORE_DATA_TO_SEND));
3101 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3103 base::RunLoop().RunUntilIdle();
3105 // Trying to create a new connection should cause the pool to be stalled, and
3106 // post a task asynchronously to try and close the session.
3107 TestCompletionCallback callback2;
3108 HostPortPair host_port2("2.com", 80);
3109 scoped_refptr<TransportSocketParams> params2(
3110 new TransportSocketParams(
3111 host_port2, false, false, OnHostResolutionCallback(),
3112 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3113 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3114 EXPECT_EQ(ERR_IO_PENDING,
3115 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3116 callback2.callback(), pool, BoundNetLog()));
3117 EXPECT_TRUE(pool->IsStalled());
3119 // Running the message loop should cause the socket pool to ask the SPDY
3120 // session to close an idle socket, but since the socket is in use, nothing
3121 // happens.
3122 base::RunLoop().RunUntilIdle();
3123 EXPECT_TRUE(pool->IsStalled());
3124 EXPECT_FALSE(callback2.have_result());
3126 // Cancelling the request should result in the session's socket being
3127 // closed, since the pool is stalled.
3128 ASSERT_TRUE(spdy_stream1.get());
3129 spdy_stream1->Cancel();
3130 base::RunLoop().RunUntilIdle();
3131 ASSERT_FALSE(pool->IsStalled());
3132 EXPECT_EQ(OK, callback2.WaitForResult());
3135 // Verify that SpdySessionKey and therefore SpdySession is different when
3136 // privacy mode is enabled or disabled.
3137 TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3138 CreateNetworkSession();
3140 HostPortPair host_port_pair("www.example.org", 443);
3141 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3142 PRIVACY_MODE_ENABLED);
3143 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3144 PRIVACY_MODE_DISABLED);
3146 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3147 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3149 // Add SpdySession with PrivacyMode Enabled to the pool.
3150 base::WeakPtr<SpdySession> session_privacy_enabled =
3151 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3153 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3154 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3156 // Add SpdySession with PrivacyMode Disabled to the pool.
3157 base::WeakPtr<SpdySession> session_privacy_disabled =
3158 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3160 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3161 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3163 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3164 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3165 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3167 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3168 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3169 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3172 // Delegate that creates another stream when its stream is closed.
3173 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3174 public:
3175 StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3176 const base::WeakPtr<SpdySession>& session)
3177 : StreamDelegateDoNothing(stream),
3178 session_(session) {}
3180 ~StreamCreatingDelegate() override {}
3182 void OnClose(int status) override {
3183 GURL url(kDefaultURL);
3184 ignore_result(
3185 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3186 session_, url, MEDIUM, BoundNetLog()));
3189 private:
3190 const base::WeakPtr<SpdySession> session_;
3193 // Create another stream in response to a stream being reset. Nothing
3194 // should blow up. This is a regression test for
3195 // http://crbug.com/263690 .
3196 TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3197 session_deps_.host_resolver->set_synchronous_mode(true);
3199 scoped_ptr<SpdyFrame> req(
3200 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
3201 MockWrite writes[] = {
3202 CreateMockWrite(*req, 0),
3205 scoped_ptr<SpdyFrame> rst(
3206 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3207 MockRead reads[] = {
3208 MockRead(ASYNC, ERR_IO_PENDING, 1),
3209 CreateMockRead(*rst, 2),
3210 MockRead(ASYNC, ERR_IO_PENDING, 3),
3211 MockRead(ASYNC, 0, 4) // EOF
3213 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3214 session_deps_.socket_factory->AddSocketDataProvider(&data);
3216 CreateNetworkSession();
3217 CreateInsecureSpdySession();
3219 GURL url(kDefaultURL);
3220 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
3221 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
3222 ASSERT_TRUE(spdy_stream.get() != nullptr);
3223 EXPECT_EQ(0u, spdy_stream->stream_id());
3225 StreamCreatingDelegate delegate(spdy_stream, session_);
3226 spdy_stream->SetDelegate(&delegate);
3228 scoped_ptr<SpdyHeaderBlock> headers(
3229 spdy_util_.ConstructGetHeaderBlock(url.spec()));
3230 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3231 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3233 EXPECT_EQ(0u, spdy_stream->stream_id());
3235 base::RunLoop().RunUntilIdle();
3237 EXPECT_EQ(1u, spdy_stream->stream_id());
3239 // Cause the stream to be reset, which should cause another stream
3240 // to be created.
3241 data.CompleteRead();
3242 base::RunLoop().RunUntilIdle();
3244 EXPECT_FALSE(spdy_stream);
3245 EXPECT_TRUE(delegate.StreamIsClosed());
3246 EXPECT_EQ(0u, session_->num_active_streams());
3247 EXPECT_EQ(1u, session_->num_created_streams());
3249 data.CompleteRead();
3250 base::RunLoop().RunUntilIdle();
3251 EXPECT_FALSE(session_);
3254 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3255 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3256 // gets sent.
3257 SettingsMap new_settings;
3258 int32 window_size = 1;
3259 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3260 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3262 // Set up the socket so we read a SETTINGS frame that sets
3263 // INITIAL_WINDOW_SIZE.
3264 scoped_ptr<SpdyFrame> settings_frame(
3265 spdy_util_.ConstructSpdySettings(new_settings));
3266 MockRead reads[] = {
3267 CreateMockRead(*settings_frame, 0),
3268 MockRead(ASYNC, ERR_IO_PENDING, 1),
3269 MockRead(ASYNC, 0, 2) // EOF
3272 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3273 MockWrite writes[] = {
3274 CreateMockWrite(*settings_ack, 3),
3277 session_deps_.host_resolver->set_synchronous_mode(true);
3279 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3280 session_deps_.socket_factory->AddSocketDataProvider(&data);
3282 CreateNetworkSession();
3283 CreateInsecureSpdySession();
3284 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
3285 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
3286 ASSERT_TRUE(spdy_stream1.get() != nullptr);
3287 TestCompletionCallback callback1;
3288 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3290 // Process the SETTINGS frame.
3291 base::RunLoop().RunUntilIdle();
3292 EXPECT_EQ(session_->stream_initial_send_window_size(), window_size);
3293 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3295 // Release the first one, this will allow the second to be created.
3296 spdy_stream1->Cancel();
3297 EXPECT_FALSE(spdy_stream1);
3299 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
3300 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
3301 ASSERT_TRUE(spdy_stream2.get() != nullptr);
3302 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3303 spdy_stream2->Cancel();
3304 EXPECT_FALSE(spdy_stream2);
3306 EXPECT_TRUE(session_);
3307 data.CompleteRead();
3308 base::RunLoop().RunUntilIdle();
3309 EXPECT_FALSE(session_);
3312 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3313 // adjust the session receive window size. In addition,
3314 // SpdySession::IncreaseRecvWindowSize should trigger
3315 // sending a WINDOW_UPDATE frame for a large enough delta.
3316 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3317 session_deps_.host_resolver->set_synchronous_mode(true);
3319 const int32 initial_window_size =
3320 SpdySession::GetDefaultInitialWindowSize(GetParam());
3321 const int32 delta_window_size = 100;
3323 MockRead reads[] = {
3324 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
3326 scoped_ptr<SpdyFrame> window_update(spdy_util_.ConstructSpdyWindowUpdate(
3327 kSessionFlowControlStreamId, initial_window_size + delta_window_size));
3328 MockWrite writes[] = {
3329 CreateMockWrite(*window_update, 0),
3331 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3332 session_deps_.socket_factory->AddSocketDataProvider(&data);
3334 CreateNetworkSession();
3335 CreateInsecureSpdySession();
3336 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3337 session_->flow_control_state());
3339 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3340 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3342 session_->IncreaseRecvWindowSize(delta_window_size);
3343 EXPECT_EQ(initial_window_size + delta_window_size,
3344 session_->session_recv_window_size_);
3345 EXPECT_EQ(delta_window_size, session_->session_unacked_recv_window_bytes_);
3347 // Should trigger sending a WINDOW_UPDATE frame.
3348 session_->IncreaseRecvWindowSize(initial_window_size);
3349 EXPECT_EQ(initial_window_size + delta_window_size + initial_window_size,
3350 session_->session_recv_window_size_);
3351 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3353 base::RunLoop().RunUntilIdle();
3355 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3356 session_->in_io_loop_ = true;
3357 session_->DecreaseRecvWindowSize(initial_window_size + delta_window_size +
3358 initial_window_size);
3359 session_->in_io_loop_ = false;
3360 EXPECT_EQ(0, session_->session_recv_window_size_);
3361 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3363 EXPECT_TRUE(session_);
3364 data.CompleteRead();
3365 base::RunLoop().RunUntilIdle();
3366 EXPECT_FALSE(session_);
3369 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3370 // adjust the session send window size when the "enable_spdy_31" flag
3371 // is set.
3372 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3373 session_deps_.host_resolver->set_synchronous_mode(true);
3375 MockRead reads[] = {
3376 MockRead(SYNCHRONOUS, 0, 0) // EOF
3378 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
3379 session_deps_.socket_factory->AddSocketDataProvider(&data);
3381 CreateNetworkSession();
3382 session_ = CreateFakeSpdySession(spdy_session_pool_, key_);
3383 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3384 session_->flow_control_state());
3386 const int32 initial_window_size =
3387 SpdySession::GetDefaultInitialWindowSize(GetParam());
3388 const int32 delta_window_size = 100;
3390 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3392 session_->IncreaseSendWindowSize(delta_window_size);
3393 EXPECT_EQ(initial_window_size + delta_window_size,
3394 session_->session_send_window_size_);
3396 session_->DecreaseSendWindowSize(delta_window_size);
3397 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3400 // Incoming data for an inactive stream should not cause the session
3401 // receive window size to decrease, but it should cause the unacked
3402 // bytes to increase.
3403 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3404 session_deps_.host_resolver->set_synchronous_mode(true);
3406 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3407 MockRead reads[] = {
3408 CreateMockRead(*resp, 0),
3409 MockRead(ASYNC, ERR_IO_PENDING, 1),
3410 MockRead(ASYNC, 0, 2) // EOF
3412 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
3413 session_deps_.socket_factory->AddSocketDataProvider(&data);
3415 CreateNetworkSession();
3416 CreateInsecureSpdySession();
3417 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3418 session_->flow_control_state());
3420 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3421 session_->session_recv_window_size_);
3422 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3424 base::RunLoop().RunUntilIdle();
3426 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3427 session_->session_recv_window_size_);
3428 EXPECT_EQ(kUploadDataSize, session_->session_unacked_recv_window_bytes_);
3430 EXPECT_TRUE(session_);
3431 data.CompleteRead();
3432 base::RunLoop().RunUntilIdle();
3433 EXPECT_FALSE(session_);
3436 // The frame header is not included in flow control, but frame payload
3437 // (including optional pad length and padding) is.
3438 TEST_P(SpdySessionTest, SessionFlowControlPadding) {
3439 // Padding only exists in HTTP/2.
3440 if (GetParam() < kProtoHTTP2MinimumVersion)
3441 return;
3443 session_deps_.host_resolver->set_synchronous_mode(true);
3445 const int padding_length = 42;
3446 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(
3447 1, kUploadData, kUploadDataSize, false, padding_length));
3448 MockRead reads[] = {
3449 CreateMockRead(*resp, 0),
3450 MockRead(ASYNC, ERR_IO_PENDING, 1),
3451 MockRead(ASYNC, 0, 2) // EOF
3453 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
3454 session_deps_.socket_factory->AddSocketDataProvider(&data);
3456 CreateNetworkSession();
3457 CreateInsecureSpdySession();
3458 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3459 session_->flow_control_state());
3461 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3462 session_->session_recv_window_size_);
3463 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3465 base::RunLoop().RunUntilIdle();
3467 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3468 session_->session_recv_window_size_);
3469 EXPECT_EQ(kUploadDataSize + padding_length,
3470 session_->session_unacked_recv_window_bytes_);
3472 data.CompleteRead();
3473 base::RunLoop().RunUntilIdle();
3474 EXPECT_FALSE(session_);
3477 // Peer sends more data than stream level receiving flow control window.
3478 TEST_P(SpdySessionTest, StreamFlowControlTooMuchData) {
3479 const int32 stream_max_recv_window_size = 1024;
3480 const int32 data_frame_size = 2 * stream_max_recv_window_size;
3482 scoped_ptr<SpdyFrame> req(
3483 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
3484 scoped_ptr<SpdyFrame> rst(
3485 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
3486 MockWrite writes[] = {
3487 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
3490 scoped_ptr<SpdyFrame> resp(
3491 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3492 const std::string payload(data_frame_size, 'a');
3493 scoped_ptr<SpdyFrame> data_frame(spdy_util_.ConstructSpdyBodyFrame(
3494 1, payload.data(), data_frame_size, false));
3495 MockRead reads[] = {
3496 CreateMockRead(*resp, 1),
3497 MockRead(ASYNC, ERR_IO_PENDING, 2),
3498 CreateMockRead(*data_frame, 3),
3499 MockRead(ASYNC, ERR_IO_PENDING, 5),
3500 MockRead(ASYNC, 0, 6),
3503 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3504 session_deps_.socket_factory->AddSocketDataProvider(&data);
3505 CreateNetworkSession();
3507 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
3508 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
3509 CreateInsecureSpdySession();
3510 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM, session_->flow_control_state());
3512 GURL url(kDefaultURL);
3513 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
3514 SPDY_REQUEST_RESPONSE_STREAM, session_, url, LOWEST, BoundNetLog());
3515 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3517 test::StreamDelegateDoNothing delegate(spdy_stream);
3518 spdy_stream->SetDelegate(&delegate);
3520 scoped_ptr<SpdyHeaderBlock> headers(
3521 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3522 EXPECT_EQ(ERR_IO_PENDING, spdy_stream->SendRequestHeaders(
3523 headers.Pass(), NO_MORE_DATA_TO_SEND));
3525 // Request and response.
3526 base::RunLoop().RunUntilIdle();
3527 EXPECT_EQ(1u, spdy_stream->stream_id());
3529 // Too large data frame causes flow control error, should close stream.
3530 data.CompleteRead();
3531 base::RunLoop().RunUntilIdle();
3532 EXPECT_FALSE(spdy_stream);
3534 EXPECT_TRUE(session_);
3535 data.CompleteRead();
3536 base::RunLoop().RunUntilIdle();
3537 EXPECT_FALSE(session_);
3540 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3541 // deltas in the receiving window size when checking incoming frames for flow
3542 // control errors at session level.
3543 TEST_P(SpdySessionTest, SessionFlowControlTooMuchDataTwoDataFrames) {
3544 const int32 session_max_recv_window_size = 500;
3545 const int32 first_data_frame_size = 200;
3546 const int32 second_data_frame_size = 400;
3548 // First data frame should not trigger a WINDOW_UPDATE.
3549 ASSERT_GT(session_max_recv_window_size / 2, first_data_frame_size);
3550 // Second data frame would be fine had there been a WINDOW_UPDATE.
3551 ASSERT_GT(session_max_recv_window_size, second_data_frame_size);
3552 // But in fact, the two data frames together overflow the receiving window at
3553 // session level.
3554 ASSERT_LT(session_max_recv_window_size,
3555 first_data_frame_size + second_data_frame_size);
3557 session_deps_.host_resolver->set_synchronous_mode(true);
3559 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3560 0, GOAWAY_FLOW_CONTROL_ERROR,
3561 "delta_window_size is 400 in DecreaseRecvWindowSize, which is larger "
3562 "than the receive window size of 500"));
3563 MockWrite writes[] = {
3564 CreateMockWrite(*goaway, 4),
3567 const std::string first_data_frame(first_data_frame_size, 'a');
3568 scoped_ptr<SpdyFrame> first(spdy_util_.ConstructSpdyBodyFrame(
3569 1, first_data_frame.data(), first_data_frame_size, false));
3570 const std::string second_data_frame(second_data_frame_size, 'b');
3571 scoped_ptr<SpdyFrame> second(spdy_util_.ConstructSpdyBodyFrame(
3572 1, second_data_frame.data(), second_data_frame_size, false));
3573 MockRead reads[] = {
3574 CreateMockRead(*first, 0),
3575 MockRead(ASYNC, ERR_IO_PENDING, 1),
3576 CreateMockRead(*second, 2),
3577 MockRead(ASYNC, 0, 3),
3579 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3580 session_deps_.socket_factory->AddSocketDataProvider(&data);
3582 CreateNetworkSession();
3583 CreateInsecureSpdySession();
3584 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3585 session_->flow_control_state());
3586 // Setting session level receiving window size to smaller than initial is not
3587 // possible via SpdySessionPoolPeer.
3588 session_->session_recv_window_size_ = session_max_recv_window_size;
3590 // First data frame is immediately consumed and does not trigger
3591 // WINDOW_UPDATE.
3592 base::RunLoop().RunUntilIdle();
3593 EXPECT_EQ(first_data_frame_size,
3594 session_->session_unacked_recv_window_bytes_);
3595 EXPECT_EQ(session_max_recv_window_size, session_->session_recv_window_size_);
3596 EXPECT_EQ(SpdySession::STATE_AVAILABLE, session_->availability_state_);
3598 // Second data frame overflows receiving window, causes session to close.
3599 data.CompleteRead();
3600 base::RunLoop().RunUntilIdle();
3601 EXPECT_EQ(SpdySession::STATE_DRAINING, session_->availability_state_);
3604 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3605 // deltas in the receiving window size when checking incoming data frames for
3606 // flow control errors at stream level.
3607 TEST_P(SpdySessionTest, StreamFlowControlTooMuchDataTwoDataFrames) {
3608 const int32 stream_max_recv_window_size = 500;
3609 const int32 first_data_frame_size = 200;
3610 const int32 second_data_frame_size = 400;
3612 // First data frame should not trigger a WINDOW_UPDATE.
3613 ASSERT_GT(stream_max_recv_window_size / 2, first_data_frame_size);
3614 // Second data frame would be fine had there been a WINDOW_UPDATE.
3615 ASSERT_GT(stream_max_recv_window_size, second_data_frame_size);
3616 // But in fact, they should overflow the receiving window at stream level.
3617 ASSERT_LT(stream_max_recv_window_size,
3618 first_data_frame_size + second_data_frame_size);
3620 scoped_ptr<SpdyFrame> req(
3621 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
3622 scoped_ptr<SpdyFrame> rst(
3623 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
3624 MockWrite writes[] = {
3625 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 6),
3628 scoped_ptr<SpdyFrame> resp(
3629 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3630 const std::string first_data_frame(first_data_frame_size, 'a');
3631 scoped_ptr<SpdyFrame> first(spdy_util_.ConstructSpdyBodyFrame(
3632 1, first_data_frame.data(), first_data_frame_size, false));
3633 const std::string second_data_frame(second_data_frame_size, 'b');
3634 scoped_ptr<SpdyFrame> second(spdy_util_.ConstructSpdyBodyFrame(
3635 1, second_data_frame.data(), second_data_frame_size, false));
3636 MockRead reads[] = {
3637 CreateMockRead(*resp, 1),
3638 MockRead(ASYNC, ERR_IO_PENDING, 2),
3639 CreateMockRead(*first, 3),
3640 MockRead(ASYNC, ERR_IO_PENDING, 4),
3641 CreateMockRead(*second, 5),
3642 MockRead(ASYNC, ERR_IO_PENDING, 7),
3643 MockRead(ASYNC, 0, 8),
3646 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3647 session_deps_.socket_factory->AddSocketDataProvider(&data);
3649 CreateNetworkSession();
3650 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
3651 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
3653 CreateInsecureSpdySession();
3654 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM, session_->flow_control_state());
3656 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
3657 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
3658 test::StreamDelegateDoNothing delegate(spdy_stream);
3659 spdy_stream->SetDelegate(&delegate);
3661 scoped_ptr<SpdyHeaderBlock> headers(
3662 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3663 EXPECT_EQ(ERR_IO_PENDING, spdy_stream->SendRequestHeaders(
3664 headers.Pass(), NO_MORE_DATA_TO_SEND));
3666 // Request and response.
3667 base::RunLoop().RunUntilIdle();
3668 EXPECT_TRUE(spdy_stream->IsLocallyClosed());
3669 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3671 // First data frame.
3672 data.CompleteRead();
3673 base::RunLoop().RunUntilIdle();
3674 EXPECT_TRUE(spdy_stream->IsLocallyClosed());
3675 EXPECT_EQ(stream_max_recv_window_size - first_data_frame_size,
3676 spdy_stream->recv_window_size());
3678 // Consume first data frame. This does not trigger a WINDOW_UPDATE.
3679 std::string received_data = delegate.TakeReceivedData();
3680 EXPECT_EQ(static_cast<size_t>(first_data_frame_size), received_data.size());
3681 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3683 // Second data frame overflows receiving window, causes the stream to close.
3684 data.CompleteRead();
3685 base::RunLoop().RunUntilIdle();
3686 EXPECT_FALSE(spdy_stream.get());
3688 // RST_STREAM
3689 EXPECT_TRUE(session_);
3690 data.CompleteRead();
3691 base::RunLoop().RunUntilIdle();
3692 EXPECT_FALSE(session_);
3695 // A delegate that drops any received data.
3696 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3697 public:
3698 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3699 base::StringPiece data)
3700 : StreamDelegateSendImmediate(stream, data) {}
3702 ~DropReceivedDataDelegate() override {}
3704 // Drop any received data.
3705 void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override {}
3708 // Send data back and forth but use a delegate that drops its received
3709 // data. The receive window should still increase to its original
3710 // value, i.e. we shouldn't "leak" receive window bytes.
3711 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3712 const char kStreamUrl[] = "http://www.example.org/";
3714 const int32 msg_data_size = 100;
3715 const std::string msg_data(msg_data_size, 'a');
3717 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3718 kStreamUrl, 1, msg_data_size, MEDIUM, nullptr, 0));
3719 scoped_ptr<SpdyFrame> msg(
3720 spdy_util_.ConstructSpdyBodyFrame(
3721 1, msg_data.data(), msg_data_size, false));
3722 MockWrite writes[] = {
3723 CreateMockWrite(*req, 0),
3724 CreateMockWrite(*msg, 2),
3727 scoped_ptr<SpdyFrame> resp(
3728 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3729 scoped_ptr<SpdyFrame> echo(
3730 spdy_util_.ConstructSpdyBodyFrame(
3731 1, msg_data.data(), msg_data_size, false));
3732 scoped_ptr<SpdyFrame> window_update(
3733 spdy_util_.ConstructSpdyWindowUpdate(
3734 kSessionFlowControlStreamId, msg_data_size));
3735 MockRead reads[] = {
3736 CreateMockRead(*resp, 1),
3737 CreateMockRead(*echo, 3),
3738 MockRead(ASYNC, ERR_IO_PENDING, 4),
3739 MockRead(ASYNC, 0, 5) // EOF
3742 // Create SpdySession and SpdyStream and send the request.
3743 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3744 session_deps_.host_resolver->set_synchronous_mode(true);
3745 session_deps_.socket_factory->AddSocketDataProvider(&data);
3747 CreateNetworkSession();
3748 CreateInsecureSpdySession();
3750 GURL url(kStreamUrl);
3751 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
3752 SPDY_BIDIRECTIONAL_STREAM, session_, url, MEDIUM, BoundNetLog());
3753 ASSERT_TRUE(stream.get() != nullptr);
3754 EXPECT_EQ(0u, stream->stream_id());
3756 DropReceivedDataDelegate delegate(stream, msg_data);
3757 stream->SetDelegate(&delegate);
3759 scoped_ptr<SpdyHeaderBlock> headers(
3760 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3761 EXPECT_EQ(ERR_IO_PENDING,
3762 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3763 EXPECT_TRUE(stream->HasUrlFromHeaders());
3765 const int32 initial_window_size =
3766 SpdySession::GetDefaultInitialWindowSize(GetParam());
3767 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3768 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3770 base::RunLoop().RunUntilIdle();
3772 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3773 EXPECT_EQ(msg_data_size, session_->session_unacked_recv_window_bytes_);
3775 stream->Close();
3776 EXPECT_FALSE(stream);
3778 EXPECT_EQ(OK, delegate.WaitForClose());
3780 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3781 EXPECT_EQ(msg_data_size, session_->session_unacked_recv_window_bytes_);
3783 data.CompleteRead();
3784 base::RunLoop().RunUntilIdle();
3785 EXPECT_FALSE(session_);
3788 // Send data back and forth but close the stream before its data frame
3789 // can be written to the socket. The send window should then increase
3790 // to its original value, i.e. we shouldn't "leak" send window bytes.
3791 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3792 const char kStreamUrl[] = "http://www.example.org/";
3794 const int32 msg_data_size = 100;
3795 const std::string msg_data(msg_data_size, 'a');
3797 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3798 kStreamUrl, 1, msg_data_size, MEDIUM, nullptr, 0));
3799 MockWrite writes[] = {
3800 CreateMockWrite(*req, 0),
3803 scoped_ptr<SpdyFrame> resp(
3804 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3805 MockRead reads[] = {
3806 MockRead(ASYNC, ERR_IO_PENDING, 1),
3807 CreateMockRead(*resp, 2),
3808 MockRead(ASYNC, 0, 3) // EOF
3811 // Create SpdySession and SpdyStream and send the request.
3812 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3813 session_deps_.host_resolver->set_synchronous_mode(true);
3814 session_deps_.socket_factory->AddSocketDataProvider(&data);
3816 CreateNetworkSession();
3817 CreateInsecureSpdySession();
3819 GURL url(kStreamUrl);
3820 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
3821 SPDY_BIDIRECTIONAL_STREAM, session_, url, MEDIUM, BoundNetLog());
3822 ASSERT_TRUE(stream.get() != nullptr);
3823 EXPECT_EQ(0u, stream->stream_id());
3825 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3826 stream->SetDelegate(&delegate);
3828 scoped_ptr<SpdyHeaderBlock> headers(
3829 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3830 EXPECT_EQ(ERR_IO_PENDING,
3831 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3832 EXPECT_TRUE(stream->HasUrlFromHeaders());
3834 const int32 initial_window_size =
3835 SpdySession::GetDefaultInitialWindowSize(GetParam());
3836 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3838 // Write request.
3839 base::RunLoop().RunUntilIdle();
3841 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3843 // Read response, but do not run the message loop, so that the body is not
3844 // written to the socket.
3845 data.CompleteRead();
3847 EXPECT_EQ(initial_window_size - msg_data_size,
3848 session_->session_send_window_size_);
3850 // Closing the stream should increase the session's send window.
3851 stream->Close();
3852 EXPECT_FALSE(stream);
3854 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3856 EXPECT_EQ(OK, delegate.WaitForClose());
3858 base::RunLoop().RunUntilIdle();
3859 EXPECT_FALSE(session_);
3861 EXPECT_TRUE(data.AllWriteDataConsumed());
3862 EXPECT_TRUE(data.AllReadDataConsumed());
3865 // Send data back and forth; the send and receive windows should
3866 // change appropriately.
3867 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
3868 const char kStreamUrl[] = "http://www.example.org/";
3870 const int32 msg_data_size = 100;
3871 const std::string msg_data(msg_data_size, 'a');
3873 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3874 kStreamUrl, 1, msg_data_size, MEDIUM, nullptr, 0));
3875 scoped_ptr<SpdyFrame> msg(
3876 spdy_util_.ConstructSpdyBodyFrame(
3877 1, msg_data.data(), msg_data_size, false));
3878 MockWrite writes[] = {
3879 CreateMockWrite(*req, 0),
3880 CreateMockWrite(*msg, 2),
3883 scoped_ptr<SpdyFrame> resp(
3884 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3885 scoped_ptr<SpdyFrame> echo(
3886 spdy_util_.ConstructSpdyBodyFrame(
3887 1, msg_data.data(), msg_data_size, false));
3888 scoped_ptr<SpdyFrame> window_update(
3889 spdy_util_.ConstructSpdyWindowUpdate(
3890 kSessionFlowControlStreamId, msg_data_size));
3891 MockRead reads[] = {
3892 CreateMockRead(*resp, 1),
3893 MockRead(ASYNC, ERR_IO_PENDING, 3),
3894 CreateMockRead(*echo, 4),
3895 MockRead(ASYNC, ERR_IO_PENDING, 5),
3896 CreateMockRead(*window_update, 6),
3897 MockRead(ASYNC, ERR_IO_PENDING, 7),
3898 MockRead(ASYNC, 0, 8) // EOF
3901 // Create SpdySession and SpdyStream and send the request.
3902 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3903 session_deps_.host_resolver->set_synchronous_mode(true);
3904 session_deps_.socket_factory->AddSocketDataProvider(&data);
3906 CreateNetworkSession();
3907 CreateInsecureSpdySession();
3909 GURL url(kStreamUrl);
3910 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
3911 SPDY_BIDIRECTIONAL_STREAM, session_, url, MEDIUM, BoundNetLog());
3912 ASSERT_TRUE(stream.get() != nullptr);
3913 EXPECT_EQ(0u, stream->stream_id());
3915 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3916 stream->SetDelegate(&delegate);
3918 scoped_ptr<SpdyHeaderBlock> headers(
3919 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3920 EXPECT_EQ(ERR_IO_PENDING,
3921 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3922 EXPECT_TRUE(stream->HasUrlFromHeaders());
3924 const int32 initial_window_size =
3925 SpdySession::GetDefaultInitialWindowSize(GetParam());
3926 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3927 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3928 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3930 // Send request and message.
3931 base::RunLoop().RunUntilIdle();
3933 EXPECT_EQ(initial_window_size - msg_data_size,
3934 session_->session_send_window_size_);
3935 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3936 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3938 // Read echo.
3939 data.CompleteRead();
3940 base::RunLoop().RunUntilIdle();
3942 EXPECT_EQ(initial_window_size - msg_data_size,
3943 session_->session_send_window_size_);
3944 EXPECT_EQ(initial_window_size - msg_data_size,
3945 session_->session_recv_window_size_);
3946 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3948 // Read window update.
3949 data.CompleteRead();
3950 base::RunLoop().RunUntilIdle();
3952 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3953 EXPECT_EQ(initial_window_size - msg_data_size,
3954 session_->session_recv_window_size_);
3955 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3957 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
3959 // Draining the delegate's read queue should increase the session's
3960 // receive window.
3961 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3962 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3963 EXPECT_EQ(msg_data_size, session_->session_unacked_recv_window_bytes_);
3965 stream->Close();
3966 EXPECT_FALSE(stream);
3968 EXPECT_EQ(OK, delegate.WaitForClose());
3970 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3971 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3972 EXPECT_EQ(msg_data_size, session_->session_unacked_recv_window_bytes_);
3974 data.CompleteRead();
3975 base::RunLoop().RunUntilIdle();
3976 EXPECT_FALSE(session_);
3979 // Given a stall function and an unstall function, runs a test to make
3980 // sure that a stream resumes after unstall.
3981 void SpdySessionTest::RunResumeAfterUnstallTest(
3982 const base::Callback<void(SpdyStream*)>& stall_function,
3983 const base::Callback<void(SpdyStream*, int32)>& unstall_function) {
3984 const char kStreamUrl[] = "http://www.example.org/";
3985 GURL url(kStreamUrl);
3987 session_deps_.host_resolver->set_synchronous_mode(true);
3989 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3990 kStreamUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
3991 scoped_ptr<SpdyFrame> body(
3992 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3993 MockWrite writes[] = {
3994 CreateMockWrite(*req, 0),
3995 CreateMockWrite(*body, 1),
3998 scoped_ptr<SpdyFrame> resp(
3999 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4000 scoped_ptr<SpdyFrame> echo(
4001 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4002 MockRead reads[] = {
4003 CreateMockRead(*resp, 2), MockRead(ASYNC, 0, 3) // EOF
4006 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4007 session_deps_.socket_factory->AddSocketDataProvider(&data);
4009 CreateNetworkSession();
4010 CreateInsecureSpdySession();
4011 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4012 session_->flow_control_state());
4014 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
4015 SPDY_REQUEST_RESPONSE_STREAM, session_, url, LOWEST, BoundNetLog());
4016 ASSERT_TRUE(stream.get() != nullptr);
4018 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
4019 stream->SetDelegate(&delegate);
4021 EXPECT_FALSE(stream->HasUrlFromHeaders());
4022 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4024 scoped_ptr<SpdyHeaderBlock> headers(
4025 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4026 EXPECT_EQ(ERR_IO_PENDING,
4027 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4028 EXPECT_TRUE(stream->HasUrlFromHeaders());
4029 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
4031 stall_function.Run(stream.get());
4033 base::RunLoop().RunUntilIdle();
4035 EXPECT_TRUE(stream->send_stalled_by_flow_control());
4037 unstall_function.Run(stream.get(), kBodyDataSize);
4039 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4041 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
4043 EXPECT_TRUE(delegate.send_headers_completed());
4044 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
4045 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
4046 EXPECT_FALSE(session_);
4047 EXPECT_TRUE(data.AllWriteDataConsumed());
4050 // Run the resume-after-unstall test with all possible stall and
4051 // unstall sequences.
4053 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
4054 RunResumeAfterUnstallTest(
4055 base::Bind(&SpdySessionTest::StallSessionOnly,
4056 base::Unretained(this)),
4057 base::Bind(&SpdySessionTest::UnstallSessionOnly,
4058 base::Unretained(this)));
4061 // Equivalent to
4062 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4063 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
4064 RunResumeAfterUnstallTest(
4065 base::Bind(&SpdySessionTest::StallStreamOnly,
4066 base::Unretained(this)),
4067 base::Bind(&SpdySessionTest::UnstallStreamOnly,
4068 base::Unretained(this)));
4071 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4072 RunResumeAfterUnstallTest(
4073 base::Bind(&SpdySessionTest::StallSessionStream,
4074 base::Unretained(this)),
4075 base::Bind(&SpdySessionTest::UnstallSessionStream,
4076 base::Unretained(this)));
4079 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4080 RunResumeAfterUnstallTest(
4081 base::Bind(&SpdySessionTest::StallStreamSession,
4082 base::Unretained(this)),
4083 base::Bind(&SpdySessionTest::UnstallSessionStream,
4084 base::Unretained(this)));
4087 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4088 RunResumeAfterUnstallTest(
4089 base::Bind(&SpdySessionTest::StallStreamSession,
4090 base::Unretained(this)),
4091 base::Bind(&SpdySessionTest::UnstallStreamSession,
4092 base::Unretained(this)));
4095 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4096 RunResumeAfterUnstallTest(
4097 base::Bind(&SpdySessionTest::StallSessionStream,
4098 base::Unretained(this)),
4099 base::Bind(&SpdySessionTest::UnstallStreamSession,
4100 base::Unretained(this)));
4103 // Cause a stall by reducing the flow control send window to 0. The
4104 // streams should resume in priority order when that window is then
4105 // increased.
4106 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4107 const char kStreamUrl[] = "http://www.example.org/";
4108 GURL url(kStreamUrl);
4110 session_deps_.host_resolver->set_synchronous_mode(true);
4112 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4113 kStreamUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4114 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4115 kStreamUrl, 3, kBodyDataSize, MEDIUM, nullptr, 0));
4116 scoped_ptr<SpdyFrame> body1(
4117 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4118 scoped_ptr<SpdyFrame> body2(
4119 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4120 MockWrite writes[] = {
4121 CreateMockWrite(*req1, 0),
4122 CreateMockWrite(*req2, 1),
4123 CreateMockWrite(*body2, 2),
4124 CreateMockWrite(*body1, 3),
4127 scoped_ptr<SpdyFrame> resp1(
4128 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4129 scoped_ptr<SpdyFrame> resp2(
4130 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
4131 MockRead reads[] = {
4132 CreateMockRead(*resp1, 4),
4133 CreateMockRead(*resp2, 5),
4134 MockRead(ASYNC, 0, 6) // EOF
4137 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4138 session_deps_.socket_factory->AddSocketDataProvider(&data);
4140 CreateNetworkSession();
4141 CreateInsecureSpdySession();
4142 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4143 session_->flow_control_state());
4145 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
4146 SPDY_REQUEST_RESPONSE_STREAM, session_, url, LOWEST, BoundNetLog());
4147 ASSERT_TRUE(stream1.get() != nullptr);
4149 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4150 stream1->SetDelegate(&delegate1);
4152 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4154 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
4155 SPDY_REQUEST_RESPONSE_STREAM, session_, url, MEDIUM, BoundNetLog());
4156 ASSERT_TRUE(stream2.get() != nullptr);
4158 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4159 stream2->SetDelegate(&delegate2);
4161 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4163 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4164 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4166 StallSessionSend();
4168 scoped_ptr<SpdyHeaderBlock> headers1(
4169 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4170 EXPECT_EQ(ERR_IO_PENDING,
4171 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4172 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4173 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4175 base::RunLoop().RunUntilIdle();
4176 EXPECT_EQ(1u, stream1->stream_id());
4177 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4179 scoped_ptr<SpdyHeaderBlock> headers2(
4180 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4181 EXPECT_EQ(ERR_IO_PENDING,
4182 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4183 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4184 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4186 base::RunLoop().RunUntilIdle();
4187 EXPECT_EQ(3u, stream2->stream_id());
4188 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4190 // This should unstall only stream2.
4191 UnstallSessionSend(kBodyDataSize);
4193 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4194 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4196 base::RunLoop().RunUntilIdle();
4198 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4199 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4201 // This should then unstall stream1.
4202 UnstallSessionSend(kBodyDataSize);
4204 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4205 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4207 base::RunLoop().RunUntilIdle();
4209 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4210 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4212 EXPECT_TRUE(delegate1.send_headers_completed());
4213 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4214 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4216 EXPECT_TRUE(delegate2.send_headers_completed());
4217 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4218 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4220 EXPECT_FALSE(session_);
4221 EXPECT_TRUE(data.AllWriteDataConsumed());
4222 EXPECT_TRUE(data.AllReadDataConsumed());
4225 // Delegate that closes a given stream after sending its body.
4226 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4227 public:
4228 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4229 base::StringPiece data)
4230 : StreamDelegateWithBody(stream, data) {}
4232 ~StreamClosingDelegate() override {}
4234 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4235 stream_to_close_ = stream_to_close;
4238 void OnDataSent() override {
4239 test::StreamDelegateWithBody::OnDataSent();
4240 if (stream_to_close_.get()) {
4241 stream_to_close_->Close();
4242 EXPECT_FALSE(stream_to_close_);
4246 private:
4247 base::WeakPtr<SpdyStream> stream_to_close_;
4250 // Cause a stall by reducing the flow control send window to
4251 // 0. Unstalling the session should properly handle deleted streams.
4252 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4253 const char kStreamUrl[] = "http://www.example.org/";
4254 GURL url(kStreamUrl);
4256 session_deps_.host_resolver->set_synchronous_mode(true);
4258 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4259 kStreamUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4260 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4261 kStreamUrl, 3, kBodyDataSize, LOWEST, nullptr, 0));
4262 scoped_ptr<SpdyFrame> req3(spdy_util_.ConstructSpdyPost(
4263 kStreamUrl, 5, kBodyDataSize, LOWEST, nullptr, 0));
4264 scoped_ptr<SpdyFrame> body2(
4265 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4266 MockWrite writes[] = {
4267 CreateMockWrite(*req1, 0),
4268 CreateMockWrite(*req2, 1),
4269 CreateMockWrite(*req3, 2),
4270 CreateMockWrite(*body2, 3),
4273 scoped_ptr<SpdyFrame> resp2(
4274 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
4275 MockRead reads[] = {
4276 CreateMockRead(*resp2, 4),
4277 MockRead(ASYNC, ERR_IO_PENDING, 5),
4278 MockRead(ASYNC, 0, 6) // EOF
4281 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4282 session_deps_.socket_factory->AddSocketDataProvider(&data);
4284 CreateNetworkSession();
4285 CreateInsecureSpdySession();
4286 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4287 session_->flow_control_state());
4289 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
4290 SPDY_REQUEST_RESPONSE_STREAM, session_, url, LOWEST, BoundNetLog());
4291 ASSERT_TRUE(stream1.get() != nullptr);
4293 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4294 stream1->SetDelegate(&delegate1);
4296 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4298 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
4299 SPDY_REQUEST_RESPONSE_STREAM, session_, url, LOWEST, BoundNetLog());
4300 ASSERT_TRUE(stream2.get() != nullptr);
4302 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4303 stream2->SetDelegate(&delegate2);
4305 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4307 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
4308 SPDY_REQUEST_RESPONSE_STREAM, session_, url, LOWEST, BoundNetLog());
4309 ASSERT_TRUE(stream3.get() != nullptr);
4311 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4312 stream3->SetDelegate(&delegate3);
4314 EXPECT_FALSE(stream3->HasUrlFromHeaders());
4316 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4317 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4318 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4320 StallSessionSend();
4322 scoped_ptr<SpdyHeaderBlock> headers1(
4323 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4324 EXPECT_EQ(ERR_IO_PENDING,
4325 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4326 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4327 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4329 base::RunLoop().RunUntilIdle();
4330 EXPECT_EQ(1u, stream1->stream_id());
4331 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4333 scoped_ptr<SpdyHeaderBlock> headers2(
4334 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4335 EXPECT_EQ(ERR_IO_PENDING,
4336 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4337 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4338 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4340 base::RunLoop().RunUntilIdle();
4341 EXPECT_EQ(3u, stream2->stream_id());
4342 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4344 scoped_ptr<SpdyHeaderBlock> headers3(
4345 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4346 EXPECT_EQ(ERR_IO_PENDING,
4347 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4348 EXPECT_TRUE(stream3->HasUrlFromHeaders());
4349 EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4351 base::RunLoop().RunUntilIdle();
4352 EXPECT_EQ(5u, stream3->stream_id());
4353 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4355 SpdyStreamId stream_id1 = stream1->stream_id();
4356 SpdyStreamId stream_id2 = stream2->stream_id();
4357 SpdyStreamId stream_id3 = stream3->stream_id();
4359 // Close stream1 preemptively.
4360 session_->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4361 EXPECT_FALSE(stream1);
4363 EXPECT_FALSE(session_->IsStreamActive(stream_id1));
4364 EXPECT_TRUE(session_->IsStreamActive(stream_id2));
4365 EXPECT_TRUE(session_->IsStreamActive(stream_id3));
4367 // Unstall stream2, which should then close stream3.
4368 delegate2.set_stream_to_close(stream3);
4369 UnstallSessionSend(kBodyDataSize);
4371 base::RunLoop().RunUntilIdle();
4372 EXPECT_FALSE(stream3);
4374 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4375 EXPECT_FALSE(session_->IsStreamActive(stream_id1));
4376 EXPECT_TRUE(session_->IsStreamActive(stream_id2));
4377 EXPECT_FALSE(session_->IsStreamActive(stream_id3));
4379 data.CompleteRead();
4380 base::RunLoop().RunUntilIdle();
4381 EXPECT_FALSE(stream2);
4382 EXPECT_FALSE(session_);
4384 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4385 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4386 EXPECT_EQ(OK, delegate3.WaitForClose());
4388 EXPECT_TRUE(delegate1.send_headers_completed());
4389 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4391 EXPECT_TRUE(delegate2.send_headers_completed());
4392 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4393 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4395 EXPECT_TRUE(delegate3.send_headers_completed());
4396 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4398 EXPECT_TRUE(data.AllWriteDataConsumed());
4401 // Cause a stall by reducing the flow control send window to
4402 // 0. Unstalling the session should properly handle the session itself
4403 // being closed.
4404 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4405 const char kStreamUrl[] = "http://www.example.org/";
4406 GURL url(kStreamUrl);
4408 session_deps_.host_resolver->set_synchronous_mode(true);
4410 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4411 kStreamUrl, 1, kBodyDataSize, LOWEST, nullptr, 0));
4412 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4413 kStreamUrl, 3, kBodyDataSize, LOWEST, nullptr, 0));
4414 scoped_ptr<SpdyFrame> body1(
4415 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4416 MockWrite writes[] = {
4417 CreateMockWrite(*req1, 0),
4418 CreateMockWrite(*req2, 1),
4421 MockRead reads[] = {
4422 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
4425 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4426 session_deps_.socket_factory->AddSocketDataProvider(&data);
4428 CreateNetworkSession();
4429 CreateInsecureSpdySession();
4430 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4431 session_->flow_control_state());
4433 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
4434 SPDY_REQUEST_RESPONSE_STREAM, session_, url, LOWEST, BoundNetLog());
4435 ASSERT_TRUE(stream1.get() != nullptr);
4437 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4438 stream1->SetDelegate(&delegate1);
4440 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4442 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
4443 SPDY_REQUEST_RESPONSE_STREAM, session_, url, LOWEST, BoundNetLog());
4444 ASSERT_TRUE(stream2.get() != nullptr);
4446 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4447 stream2->SetDelegate(&delegate2);
4449 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4451 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4452 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4454 StallSessionSend();
4456 scoped_ptr<SpdyHeaderBlock> headers1(
4457 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4458 EXPECT_EQ(ERR_IO_PENDING,
4459 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4460 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4461 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4463 base::RunLoop().RunUntilIdle();
4464 EXPECT_EQ(1u, stream1->stream_id());
4465 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4467 scoped_ptr<SpdyHeaderBlock> headers2(
4468 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4469 EXPECT_EQ(ERR_IO_PENDING,
4470 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4471 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4472 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4474 base::RunLoop().RunUntilIdle();
4475 EXPECT_EQ(3u, stream2->stream_id());
4476 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4478 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4480 // Unstall stream1.
4481 UnstallSessionSend(kBodyDataSize);
4483 // Close the session (since we can't do it from within the delegate
4484 // method, since it's in the stream's loop).
4485 session_->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4486 data.CompleteRead();
4487 base::RunLoop().RunUntilIdle();
4488 EXPECT_FALSE(session_);
4490 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4492 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4493 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4495 EXPECT_TRUE(delegate1.send_headers_completed());
4496 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4498 EXPECT_TRUE(delegate2.send_headers_completed());
4499 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4501 EXPECT_TRUE(data.AllWriteDataConsumed());
4504 TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4505 scoped_ptr<SpdyFrame> req(
4506 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4507 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4508 0, GOAWAY_FLOW_CONTROL_ERROR,
4509 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4510 "the receive window size of 1"));
4511 MockWrite writes[] = {
4512 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 4),
4515 scoped_ptr<SpdyFrame> resp(
4516 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4517 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4518 MockRead reads[] = {
4519 MockRead(ASYNC, ERR_IO_PENDING, 1),
4520 CreateMockRead(*resp, 2),
4521 CreateMockRead(*body, 3),
4524 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4525 session_deps_.socket_factory->AddSocketDataProvider(&data);
4527 CreateNetworkSession();
4528 CreateInsecureSpdySession();
4530 GURL url(kDefaultURL);
4531 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4532 SPDY_REQUEST_RESPONSE_STREAM, session_, url, LOWEST, BoundNetLog());
4533 ASSERT_TRUE(spdy_stream.get() != nullptr);
4534 test::StreamDelegateDoNothing delegate(spdy_stream);
4535 spdy_stream->SetDelegate(&delegate);
4537 scoped_ptr<SpdyHeaderBlock> headers(
4538 spdy_util_.ConstructGetHeaderBlock(url.spec()));
4539 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4541 // Write request.
4542 base::RunLoop().RunUntilIdle();
4544 // Put session on the edge of overflowing it's recv window.
4545 session_->session_recv_window_size_ = 1;
4547 // Read response headers & body. Body overflows the session window, and a
4548 // goaway is written.
4549 data.CompleteRead();
4550 base::RunLoop().RunUntilIdle();
4552 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4553 EXPECT_FALSE(session_);
4556 TEST_P(SpdySessionTest, SplitHeaders) {
4557 GURL kStreamUrl("http://www.example.org/foo.dat");
4558 SpdyHeaderBlock headers;
4559 spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4560 headers["alpha"] = "beta";
4562 SpdyHeaderBlock request_headers;
4563 SpdyHeaderBlock response_headers;
4565 SplitPushedHeadersToRequestAndResponse(
4566 headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4568 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4569 std::string alpha_val =
4570 (it == response_headers.end()) ? std::string() : it->second;
4571 EXPECT_EQ("beta", alpha_val);
4573 GURL request_url =
4574 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4575 EXPECT_EQ(kStreamUrl, request_url);
4578 // Regression. Sorta. Push streams and client streams were sharing a single
4579 // limit for a long time.
4580 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4581 SettingsMap new_settings;
4582 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4583 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4584 scoped_ptr<SpdyFrame> settings_frame(
4585 spdy_util_.ConstructSpdySettings(new_settings));
4586 scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4587 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4588 MockRead reads[] = {
4589 CreateMockRead(*settings_frame, 0),
4590 MockRead(ASYNC, ERR_IO_PENDING, 3),
4591 CreateMockRead(*pushed, 4),
4592 MockRead(ASYNC, ERR_IO_PENDING, 5),
4593 MockRead(ASYNC, 0, 6),
4596 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4597 scoped_ptr<SpdyFrame> req(
4598 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4599 MockWrite writes[] = {
4600 CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4603 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4604 session_deps_.socket_factory->AddSocketDataProvider(&data);
4606 CreateNetworkSession();
4607 CreateInsecureSpdySession();
4609 // Read the settings frame.
4610 base::RunLoop().RunUntilIdle();
4612 GURL url1(kDefaultURL);
4613 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4614 SPDY_REQUEST_RESPONSE_STREAM, session_, url1, LOWEST, BoundNetLog());
4615 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4616 EXPECT_EQ(0u, spdy_stream1->stream_id());
4617 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4618 spdy_stream1->SetDelegate(&delegate1);
4620 EXPECT_EQ(0u, session_->num_active_streams());
4621 EXPECT_EQ(1u, session_->num_created_streams());
4622 EXPECT_EQ(0u, session_->num_pushed_streams());
4623 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4625 scoped_ptr<SpdyHeaderBlock> headers(
4626 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4627 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4628 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4630 // Run until 1st stream is activated.
4631 EXPECT_EQ(0u, delegate1.stream_id());
4632 base::RunLoop().RunUntilIdle();
4633 EXPECT_EQ(1u, delegate1.stream_id());
4634 EXPECT_EQ(1u, session_->num_active_streams());
4635 EXPECT_EQ(0u, session_->num_created_streams());
4636 EXPECT_EQ(0u, session_->num_pushed_streams());
4637 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4639 // Run until pushed stream is created.
4640 data.CompleteRead();
4641 base::RunLoop().RunUntilIdle();
4642 EXPECT_EQ(2u, session_->num_active_streams());
4643 EXPECT_EQ(0u, session_->num_created_streams());
4644 EXPECT_EQ(1u, session_->num_pushed_streams());
4645 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4647 // Second stream should not be stalled, although we have 2 active streams, but
4648 // one of them is push stream and should not be taken into account when we
4649 // create streams on the client.
4650 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4651 SPDY_REQUEST_RESPONSE_STREAM, session_, url1, LOWEST, BoundNetLog());
4652 EXPECT_TRUE(spdy_stream2);
4653 EXPECT_EQ(2u, session_->num_active_streams());
4654 EXPECT_EQ(1u, session_->num_created_streams());
4655 EXPECT_EQ(1u, session_->num_pushed_streams());
4656 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4658 // Read EOF.
4659 data.CompleteRead();
4660 base::RunLoop().RunUntilIdle();
4661 EXPECT_FALSE(session_);
4664 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4665 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4666 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4667 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4668 nullptr, 0, 4, 1, "http://www.example.org/b.dat"));
4669 MockRead reads[] = {
4670 MockRead(ASYNC, ERR_IO_PENDING, 1),
4671 CreateMockRead(*push_a, 2),
4672 MockRead(ASYNC, ERR_IO_PENDING, 3),
4673 CreateMockRead(*push_b, 4),
4674 MockRead(ASYNC, ERR_IO_PENDING, 6),
4675 MockRead(ASYNC, 0, 7),
4678 scoped_ptr<SpdyFrame> req(
4679 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4680 scoped_ptr<SpdyFrame> rst(
4681 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4682 MockWrite writes[] = {
4683 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
4686 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4687 session_deps_.socket_factory->AddSocketDataProvider(&data);
4689 CreateNetworkSession();
4690 CreateInsecureSpdySession();
4691 session_->set_max_concurrent_pushed_streams(1);
4693 GURL url1(kDefaultURL);
4694 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4695 SPDY_REQUEST_RESPONSE_STREAM, session_, url1, LOWEST, BoundNetLog());
4696 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4697 EXPECT_EQ(0u, spdy_stream1->stream_id());
4698 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4699 spdy_stream1->SetDelegate(&delegate1);
4701 EXPECT_EQ(0u, session_->num_active_streams());
4702 EXPECT_EQ(1u, session_->num_created_streams());
4703 EXPECT_EQ(0u, session_->num_pushed_streams());
4704 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4706 scoped_ptr<SpdyHeaderBlock> headers(
4707 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4708 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4709 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4711 // Run until 1st stream is activated.
4712 EXPECT_EQ(0u, delegate1.stream_id());
4713 base::RunLoop().RunUntilIdle();
4714 EXPECT_EQ(1u, delegate1.stream_id());
4715 EXPECT_EQ(1u, session_->num_active_streams());
4716 EXPECT_EQ(0u, session_->num_created_streams());
4717 EXPECT_EQ(0u, session_->num_pushed_streams());
4718 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4720 // Run until pushed stream is created.
4721 data.CompleteRead();
4722 base::RunLoop().RunUntilIdle();
4723 EXPECT_EQ(2u, session_->num_active_streams());
4724 EXPECT_EQ(0u, session_->num_created_streams());
4725 EXPECT_EQ(1u, session_->num_pushed_streams());
4726 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4728 // Reset incoming pushed stream.
4729 data.CompleteRead();
4730 base::RunLoop().RunUntilIdle();
4731 EXPECT_EQ(2u, session_->num_active_streams());
4732 EXPECT_EQ(0u, session_->num_created_streams());
4733 EXPECT_EQ(1u, session_->num_pushed_streams());
4734 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4736 // Read EOF.
4737 data.CompleteRead();
4738 base::RunLoop().RunUntilIdle();
4739 EXPECT_FALSE(session_);
4742 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4743 // Streams in reserved remote state exist only in HTTP/2.
4744 if (spdy_util_.spdy_version() < HTTP2)
4745 return;
4747 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4748 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4749 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4750 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/b.dat",
4751 push_headers.get());
4752 scoped_ptr<SpdyFrame> push_b(
4753 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4754 scoped_ptr<SpdyFrame> headers_b(
4755 spdy_util_.ConstructSpdyPushHeaders(4, nullptr, 0));
4756 MockRead reads[] = {
4757 MockRead(ASYNC, ERR_IO_PENDING, 1),
4758 CreateMockRead(*push_a, 2),
4759 MockRead(ASYNC, ERR_IO_PENDING, 3),
4760 CreateMockRead(*push_b, 4),
4761 MockRead(ASYNC, ERR_IO_PENDING, 5),
4762 CreateMockRead(*headers_b, 6),
4763 MockRead(ASYNC, ERR_IO_PENDING, 8),
4764 MockRead(ASYNC, 0, 9),
4767 scoped_ptr<SpdyFrame> req(
4768 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4769 scoped_ptr<SpdyFrame> rst(
4770 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4771 MockWrite writes[] = {
4772 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 7),
4775 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4776 session_deps_.socket_factory->AddSocketDataProvider(&data);
4778 CreateNetworkSession();
4779 CreateInsecureSpdySession();
4780 session_->set_max_concurrent_pushed_streams(1);
4782 GURL url1(kDefaultURL);
4783 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4784 SPDY_REQUEST_RESPONSE_STREAM, session_, url1, LOWEST, BoundNetLog());
4785 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4786 EXPECT_EQ(0u, spdy_stream1->stream_id());
4787 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4788 spdy_stream1->SetDelegate(&delegate1);
4790 EXPECT_EQ(0u, session_->num_active_streams());
4791 EXPECT_EQ(1u, session_->num_created_streams());
4792 EXPECT_EQ(0u, session_->num_pushed_streams());
4793 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4795 scoped_ptr<SpdyHeaderBlock> headers(
4796 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4797 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4798 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4800 // Run until 1st stream is activated.
4801 EXPECT_EQ(0u, delegate1.stream_id());
4802 base::RunLoop().RunUntilIdle();
4803 EXPECT_EQ(1u, delegate1.stream_id());
4804 EXPECT_EQ(1u, session_->num_active_streams());
4805 EXPECT_EQ(0u, session_->num_created_streams());
4806 EXPECT_EQ(0u, session_->num_pushed_streams());
4807 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4809 // Run until pushed stream is created.
4810 data.CompleteRead();
4811 base::RunLoop().RunUntilIdle();
4812 EXPECT_EQ(2u, session_->num_active_streams());
4813 EXPECT_EQ(0u, session_->num_created_streams());
4814 EXPECT_EQ(1u, session_->num_pushed_streams());
4815 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4817 // Accept promised stream. It should not count towards pushed stream limit.
4818 data.CompleteRead();
4819 base::RunLoop().RunUntilIdle();
4820 EXPECT_EQ(3u, session_->num_active_streams());
4821 EXPECT_EQ(0u, session_->num_created_streams());
4822 EXPECT_EQ(2u, session_->num_pushed_streams());
4823 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4825 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4826 // while we accept only one.
4827 data.CompleteRead();
4828 base::RunLoop().RunUntilIdle();
4829 EXPECT_EQ(2u, session_->num_active_streams());
4830 EXPECT_EQ(0u, session_->num_created_streams());
4831 EXPECT_EQ(1u, session_->num_pushed_streams());
4832 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4834 // Read EOF.
4835 data.CompleteRead();
4836 base::RunLoop().RunUntilIdle();
4837 EXPECT_FALSE(session_);
4840 TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
4841 // Streams in reserved remote state exist only in HTTP/2.
4842 if (spdy_util_.spdy_version() < HTTP2)
4843 return;
4845 const char kPushedUrl[] = "http://www.example.org/a.dat";
4846 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4847 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
4848 scoped_ptr<SpdyFrame> push_promise(
4849 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
4850 scoped_ptr<SpdyFrame> headers_frame(
4851 spdy_util_.ConstructSpdyPushHeaders(2, nullptr, 0));
4852 MockRead reads[] = {
4853 MockRead(ASYNC, ERR_IO_PENDING, 1),
4854 CreateMockRead(*push_promise, 2),
4855 MockRead(ASYNC, ERR_IO_PENDING, 3),
4856 CreateMockRead(*headers_frame, 4),
4857 MockRead(ASYNC, ERR_IO_PENDING, 6),
4858 MockRead(ASYNC, 0, 7),
4861 scoped_ptr<SpdyFrame> req(
4862 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4863 scoped_ptr<SpdyFrame> rst(
4864 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
4865 MockWrite writes[] = {
4866 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
4869 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4870 session_deps_.socket_factory->AddSocketDataProvider(&data);
4872 CreateNetworkSession();
4873 CreateInsecureSpdySession();
4875 GURL url1(kDefaultURL);
4876 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4877 SPDY_REQUEST_RESPONSE_STREAM, session_, url1, LOWEST, BoundNetLog());
4878 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4879 EXPECT_EQ(0u, spdy_stream1->stream_id());
4880 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4881 spdy_stream1->SetDelegate(&delegate1);
4883 EXPECT_EQ(0u, session_->num_active_streams());
4884 EXPECT_EQ(1u, session_->num_created_streams());
4885 EXPECT_EQ(0u, session_->num_pushed_streams());
4886 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4888 scoped_ptr<SpdyHeaderBlock> headers(
4889 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4890 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4891 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4893 // Run until 1st stream is activated.
4894 EXPECT_EQ(0u, delegate1.stream_id());
4895 base::RunLoop().RunUntilIdle();
4896 EXPECT_EQ(1u, delegate1.stream_id());
4897 EXPECT_EQ(1u, session_->num_active_streams());
4898 EXPECT_EQ(0u, session_->num_created_streams());
4899 EXPECT_EQ(0u, session_->num_pushed_streams());
4900 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4902 // Run until pushed stream is created.
4903 data.CompleteRead();
4904 base::RunLoop().RunUntilIdle();
4905 EXPECT_EQ(2u, session_->num_active_streams());
4906 EXPECT_EQ(0u, session_->num_created_streams());
4907 EXPECT_EQ(1u, session_->num_pushed_streams());
4908 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4910 base::WeakPtr<SpdyStream> pushed_stream;
4911 int rv =
4912 session_->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
4913 ASSERT_EQ(OK, rv);
4914 ASSERT_TRUE(pushed_stream.get() != nullptr);
4915 test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
4916 pushed_stream->SetDelegate(&delegate2);
4918 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4919 // that all our counters are in consistent state.
4920 data.CompleteRead();
4921 base::RunLoop().RunUntilIdle();
4922 EXPECT_EQ(1u, session_->num_active_streams());
4923 EXPECT_EQ(0u, session_->num_created_streams());
4924 EXPECT_EQ(0u, session_->num_pushed_streams());
4925 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4927 // Read EOF.
4928 data.CompleteRead();
4929 base::RunLoop().RunUntilIdle();
4930 EXPECT_TRUE(data.AllWriteDataConsumed());
4931 EXPECT_TRUE(data.AllReadDataConsumed());
4934 TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
4935 session_deps_.host_resolver->set_synchronous_mode(true);
4937 MockRead reads[] = {
4938 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
4941 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
4942 session_deps_.socket_factory->AddSocketDataProvider(&data);
4944 CreateNetworkSession();
4945 CreateInsecureSpdySession();
4947 session_->stream_hi_water_mark_ = 5;
4948 // Low client (odd) ids are fine.
4949 EXPECT_TRUE(session_->OnUnknownFrame(3, 0));
4950 // Client id exceeding watermark.
4951 EXPECT_FALSE(session_->OnUnknownFrame(9, 0));
4953 session_->last_accepted_push_stream_id_ = 6;
4954 // Low server (even) ids are fine.
4955 EXPECT_TRUE(session_->OnUnknownFrame(2, 0));
4956 // Server id exceeding last accepted id.
4957 EXPECT_FALSE(session_->OnUnknownFrame(8, 0));
4960 TEST(MapFramerErrorToProtocolError, MapsValues) {
4961 CHECK_EQ(
4962 SPDY_ERROR_INVALID_CONTROL_FRAME,
4963 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4964 CHECK_EQ(
4965 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4966 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4967 CHECK_EQ(
4968 SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
4969 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
4970 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
4971 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
4974 TEST(MapFramerErrorToNetError, MapsValue) {
4975 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
4976 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4977 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4978 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
4979 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4980 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4981 CHECK_EQ(
4982 ERR_SPDY_FRAME_SIZE_ERROR,
4983 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
4986 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
4987 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
4988 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
4989 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
4990 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
4991 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
4992 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
4993 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY,
4994 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY));
4995 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED,
4996 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED));
4999 TEST(MapNetErrorToGoAwayStatus, MapsValue) {
5000 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
5001 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
5002 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
5003 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
5004 CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
5005 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
5006 CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
5007 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
5008 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
5009 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
5010 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
5013 TEST(CanPoolTest, CanPool) {
5014 // Load a cert that is valid for:
5015 // www.example.org
5016 // mail.example.org
5017 // www.example.com
5019 TransportSecurityState tss;
5020 SSLInfo ssl_info;
5021 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5022 "spdy_pooling.pem");
5024 EXPECT_TRUE(SpdySession::CanPool(
5025 &tss, ssl_info, "www.example.org", "www.example.org"));
5026 EXPECT_TRUE(SpdySession::CanPool(
5027 &tss, ssl_info, "www.example.org", "mail.example.org"));
5028 EXPECT_TRUE(SpdySession::CanPool(
5029 &tss, ssl_info, "www.example.org", "mail.example.com"));
5030 EXPECT_FALSE(SpdySession::CanPool(
5031 &tss, ssl_info, "www.example.org", "mail.google.com"));
5034 TEST(CanPoolTest, CanNotPoolWithCertErrors) {
5035 // Load a cert that is valid for:
5036 // www.example.org
5037 // mail.example.org
5038 // www.example.com
5040 TransportSecurityState tss;
5041 SSLInfo ssl_info;
5042 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5043 "spdy_pooling.pem");
5044 ssl_info.cert_status = CERT_STATUS_REVOKED;
5046 EXPECT_FALSE(SpdySession::CanPool(
5047 &tss, ssl_info, "www.example.org", "mail.example.org"));
5050 TEST(CanPoolTest, CanNotPoolWithClientCerts) {
5051 // Load a cert that is valid for:
5052 // www.example.org
5053 // mail.example.org
5054 // www.example.com
5056 TransportSecurityState tss;
5057 SSLInfo ssl_info;
5058 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5059 "spdy_pooling.pem");
5060 ssl_info.client_cert_sent = true;
5062 EXPECT_FALSE(SpdySession::CanPool(
5063 &tss, ssl_info, "www.example.org", "mail.example.org"));
5066 TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
5067 // Load a cert that is valid for:
5068 // www.example.org
5069 // mail.example.org
5070 // www.example.com
5072 TransportSecurityState tss;
5073 SSLInfo ssl_info;
5074 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5075 "spdy_pooling.pem");
5076 ssl_info.channel_id_sent = true;
5078 EXPECT_TRUE(SpdySession::CanPool(
5079 &tss, ssl_info, "www.example.org", "mail.example.org"));
5080 EXPECT_FALSE(SpdySession::CanPool(
5081 &tss, ssl_info, "www.example.org", "www.example.com"));
5084 TEST(CanPoolTest, CanNotPoolWithBadPins) {
5085 uint8 primary_pin = 1;
5086 uint8 backup_pin = 2;
5087 uint8 bad_pin = 3;
5088 TransportSecurityState tss;
5089 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5091 SSLInfo ssl_info;
5092 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5093 "spdy_pooling.pem");
5094 ssl_info.is_issued_by_known_root = true;
5095 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
5097 EXPECT_FALSE(SpdySession::CanPool(
5098 &tss, ssl_info, "www.example.org", "mail.example.org"));
5101 TEST(CanPoolTest, CanPoolWithAcceptablePins) {
5102 uint8 primary_pin = 1;
5103 uint8 backup_pin = 2;
5104 TransportSecurityState tss;
5105 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5107 SSLInfo ssl_info;
5108 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5109 "spdy_pooling.pem");
5110 ssl_info.is_issued_by_known_root = true;
5111 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
5113 EXPECT_TRUE(SpdySession::CanPool(
5114 &tss, ssl_info, "www.example.org", "mail.example.org"));
5117 } // namespace net