ozone: drm: Crash immediately if no usable GPU is found
[chromium-blink-merge.git] / net / spdy / spdy_session_unittest.cc
blobc077195e3f812acd3e69ee3dc596d7cbe87ce22d
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 const char kBodyData[] = "Body data";
39 const size_t kBodyDataSize = arraysize(kBodyData);
40 const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize);
42 static base::TimeDelta g_time_delta;
43 static base::TimeTicks g_time_now;
45 base::TimeTicks TheNearFuture() {
46 return base::TimeTicks::Now() + g_time_delta;
49 base::TimeTicks SlowReads() {
50 g_time_delta +=
51 base::TimeDelta::FromMilliseconds(2 * kYieldAfterDurationMilliseconds);
52 return base::TimeTicks::Now() + g_time_delta;
55 base::TimeTicks InstantaneousReads() {
56 return g_time_now;
59 } // namespace
61 class SpdySessionTest : public PlatformTest,
62 public ::testing::WithParamInterface<NextProto> {
63 public:
64 // Functions used with RunResumeAfterUnstallTest().
66 void StallSessionOnly(SpdyStream* stream) { StallSessionSend(); }
68 void StallStreamOnly(SpdyStream* stream) { StallStreamSend(stream); }
70 void StallSessionStream(SpdyStream* stream) {
71 StallSessionSend();
72 StallStreamSend(stream);
75 void StallStreamSession(SpdyStream* stream) {
76 StallStreamSend(stream);
77 StallSessionSend();
80 void UnstallSessionOnly(SpdyStream* stream, int32 delta_window_size) {
81 UnstallSessionSend(delta_window_size);
84 void UnstallStreamOnly(SpdyStream* stream, int32 delta_window_size) {
85 UnstallStreamSend(stream, delta_window_size);
88 void UnstallSessionStream(SpdyStream* stream, int32 delta_window_size) {
89 UnstallSessionSend(delta_window_size);
90 UnstallStreamSend(stream, delta_window_size);
93 void UnstallStreamSession(SpdyStream* stream, int32 delta_window_size) {
94 UnstallStreamSend(stream, delta_window_size);
95 UnstallSessionSend(delta_window_size);
98 protected:
99 SpdySessionTest()
100 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
101 HttpNetworkSession::NORMAL_SOCKET_POOL)),
102 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
103 HttpNetworkSession::NORMAL_SOCKET_POOL)),
104 spdy_util_(GetParam()),
105 session_deps_(GetParam()),
106 spdy_session_pool_(nullptr),
107 test_url_(kDefaultURL),
108 test_host_port_pair_(HostPortPair::FromURL(test_url_)),
109 key_(test_host_port_pair_,
110 ProxyServer::Direct(),
111 PRIVACY_MODE_DISABLED) {}
113 virtual ~SpdySessionTest() {
114 // Important to restore the per-pool limit first, since the pool limit must
115 // always be greater than group limit, and the tests reduce both limits.
116 ClientSocketPoolManager::set_max_sockets_per_pool(
117 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
118 ClientSocketPoolManager::set_max_sockets_per_group(
119 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
122 void SetUp() override {
123 g_time_delta = base::TimeDelta();
124 g_time_now = base::TimeTicks::Now();
125 session_deps_.net_log = log_.bound().net_log();
128 void CreateNetworkSession() {
129 DCHECK(!http_session_);
130 DCHECK(!spdy_session_pool_);
131 http_session_ =
132 SpdySessionDependencies::SpdyCreateSession(&session_deps_);
133 spdy_session_pool_ = http_session_->spdy_session_pool();
136 void CreateInsecureSpdySession() {
137 DCHECK(!session_);
138 session_ =
139 ::net::CreateInsecureSpdySession(http_session_, key_, log_.bound());
142 void StallSessionSend() {
143 // Reduce the send window size to 0 to stall.
144 while (session_->session_send_window_size_ > 0) {
145 session_->DecreaseSendWindowSize(std::min(
146 kMaxSpdyFrameChunkSize, session_->session_send_window_size_));
150 void UnstallSessionSend(int32 delta_window_size) {
151 session_->IncreaseSendWindowSize(delta_window_size);
154 void StallStreamSend(SpdyStream* stream) {
155 // Reduce the send window size to 0 to stall.
156 while (stream->send_window_size() > 0) {
157 stream->DecreaseSendWindowSize(
158 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
162 void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) {
163 stream->IncreaseSendWindowSize(delta_window_size);
166 void RunResumeAfterUnstallTest(
167 const base::Callback<void(SpdyStream*)>& stall_function,
168 const base::Callback<void(SpdyStream*, int32)>& unstall_function);
170 // Original socket limits. Some tests set these. Safest to always restore
171 // them once each test has been run.
172 int old_max_group_sockets_;
173 int old_max_pool_sockets_;
175 SpdyTestUtil spdy_util_;
176 SpdySessionDependencies session_deps_;
177 scoped_refptr<HttpNetworkSession> http_session_;
178 base::WeakPtr<SpdySession> session_;
179 SpdySessionPool* spdy_session_pool_;
180 GURL test_url_;
181 HostPortPair test_host_port_pair_;
182 SpdySessionKey key_;
183 BoundTestNetLog log_;
186 INSTANTIATE_TEST_CASE_P(NextProto,
187 SpdySessionTest,
188 testing::Values(kProtoSPDY31,
189 kProtoHTTP2));
191 // Try to create a SPDY session that will fail during
192 // initialization. Nothing should blow up.
193 TEST_P(SpdySessionTest, InitialReadError) {
194 CreateNetworkSession();
196 session_ = TryCreateFakeSpdySessionExpectingFailure(spdy_session_pool_, key_,
197 ERR_CONNECTION_CLOSED);
198 EXPECT_TRUE(session_);
199 // Flush the read.
200 base::RunLoop().RunUntilIdle();
201 EXPECT_FALSE(session_);
204 namespace {
206 // A helper class that vends a callback that, when fired, destroys a
207 // given SpdyStreamRequest.
208 class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
209 public:
210 StreamRequestDestroyingCallback() {}
212 ~StreamRequestDestroyingCallback() override {}
214 void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) {
215 request_ = request.Pass();
218 CompletionCallback MakeCallback() {
219 return base::Bind(&StreamRequestDestroyingCallback::OnComplete,
220 base::Unretained(this));
223 private:
224 void OnComplete(int result) {
225 request_.reset();
226 SetResult(result);
229 scoped_ptr<SpdyStreamRequest> request_;
232 } // namespace
234 // Request kInitialMaxConcurrentStreams streams. Request two more
235 // streams, but have the callback for one destroy the second stream
236 // request. Close the session. Nothing should blow up. This is a
237 // regression test for http://crbug.com/250841 .
238 TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
239 session_deps_.host_resolver->set_synchronous_mode(true);
241 MockRead reads[] = {MockRead(ASYNC, 0, 0), };
243 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
244 session_deps_.socket_factory->AddSocketDataProvider(&data);
246 CreateNetworkSession();
247 CreateInsecureSpdySession();
249 // Create the maximum number of concurrent streams.
250 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
251 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
252 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
253 ASSERT_TRUE(spdy_stream != nullptr);
256 SpdyStreamRequest request1;
257 scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest);
259 StreamRequestDestroyingCallback callback1;
260 ASSERT_EQ(
261 ERR_IO_PENDING,
262 request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
263 MEDIUM, BoundNetLog(), callback1.MakeCallback()));
265 // |callback2| is never called.
266 TestCompletionCallback callback2;
267 ASSERT_EQ(ERR_IO_PENDING, request2->StartRequest(
268 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
269 MEDIUM, BoundNetLog(), callback2.callback()));
271 callback1.SetRequestToDestroy(request2.Pass());
273 session_->CloseSessionOnError(ERR_ABORTED, "Aborting session");
275 EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
278 // A session receiving a GOAWAY frame with no active streams should close.
279 TEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
280 session_deps_.host_resolver->set_synchronous_mode(true);
282 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
283 MockRead reads[] = {
284 CreateMockRead(*goaway, 0),
286 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
287 session_deps_.socket_factory->AddSocketDataProvider(&data);
289 CreateNetworkSession();
290 CreateInsecureSpdySession();
292 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
294 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
296 // Read and process the GOAWAY frame.
297 base::RunLoop().RunUntilIdle();
298 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
299 EXPECT_FALSE(session_);
302 // A session receiving a GOAWAY frame immediately with no active
303 // streams should then close.
304 TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
305 session_deps_.host_resolver->set_synchronous_mode(true);
307 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
308 MockRead reads[] = {
309 CreateMockRead(*goaway, 0, SYNCHRONOUS), MockRead(ASYNC, 0, 1) // EOF
311 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
312 session_deps_.socket_factory->AddSocketDataProvider(&data);
314 CreateNetworkSession();
316 session_ = TryCreateInsecureSpdySessionExpectingFailure(
317 http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
318 base::RunLoop().RunUntilIdle();
320 EXPECT_FALSE(session_);
321 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
322 EXPECT_FALSE(data.AllReadDataConsumed());
325 // A session receiving a GOAWAY frame with active streams should close
326 // when the last active stream is closed.
327 TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
328 session_deps_.host_resolver->set_synchronous_mode(true);
330 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
331 MockRead reads[] = {
332 MockRead(ASYNC, ERR_IO_PENDING, 2),
333 CreateMockRead(*goaway, 3),
334 MockRead(ASYNC, ERR_IO_PENDING, 4),
335 MockRead(ASYNC, 0, 5) // EOF
337 scoped_ptr<SpdyFrame> req1(
338 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
339 scoped_ptr<SpdyFrame> req2(
340 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
341 MockWrite writes[] = {
342 CreateMockWrite(*req1, 0),
343 CreateMockWrite(*req2, 1),
345 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
346 session_deps_.socket_factory->AddSocketDataProvider(&data);
348 CreateNetworkSession();
349 CreateInsecureSpdySession();
351 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
353 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
354 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
355 test::StreamDelegateDoNothing delegate1(spdy_stream1);
356 spdy_stream1->SetDelegate(&delegate1);
358 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
359 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
360 test::StreamDelegateDoNothing delegate2(spdy_stream2);
361 spdy_stream2->SetDelegate(&delegate2);
363 scoped_ptr<SpdyHeaderBlock> headers(
364 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
365 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
367 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
368 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
369 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
370 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
372 base::RunLoop().RunUntilIdle();
374 EXPECT_EQ(1u, spdy_stream1->stream_id());
375 EXPECT_EQ(3u, spdy_stream2->stream_id());
377 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
379 // Read and process the GOAWAY frame.
380 data.CompleteRead();
381 base::RunLoop().RunUntilIdle();
383 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
385 EXPECT_FALSE(session_->IsStreamActive(3));
386 EXPECT_FALSE(spdy_stream2);
387 EXPECT_TRUE(session_->IsStreamActive(1));
389 EXPECT_TRUE(session_->IsGoingAway());
391 // Should close the session.
392 spdy_stream1->Close();
393 EXPECT_FALSE(spdy_stream1);
395 EXPECT_TRUE(session_);
396 data.CompleteRead();
397 base::RunLoop().RunUntilIdle();
398 EXPECT_FALSE(session_);
401 // Have a session receive two GOAWAY frames, with the last one causing
402 // the last active stream to be closed. The session should then be
403 // closed after the second GOAWAY frame.
404 TEST_P(SpdySessionTest, GoAwayTwice) {
405 session_deps_.host_resolver->set_synchronous_mode(true);
407 scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
408 scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
409 MockRead reads[] = {
410 MockRead(ASYNC, ERR_IO_PENDING, 2),
411 CreateMockRead(*goaway1, 3),
412 MockRead(ASYNC, ERR_IO_PENDING, 4),
413 CreateMockRead(*goaway2, 5),
414 MockRead(ASYNC, ERR_IO_PENDING, 6),
415 MockRead(ASYNC, 0, 7) // EOF
417 scoped_ptr<SpdyFrame> req1(
418 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
419 scoped_ptr<SpdyFrame> req2(
420 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
421 MockWrite writes[] = {
422 CreateMockWrite(*req1, 0),
423 CreateMockWrite(*req2, 1),
425 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
426 session_deps_.socket_factory->AddSocketDataProvider(&data);
428 CreateNetworkSession();
429 CreateInsecureSpdySession();
431 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
433 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
434 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
435 test::StreamDelegateDoNothing delegate1(spdy_stream1);
436 spdy_stream1->SetDelegate(&delegate1);
438 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
439 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
440 test::StreamDelegateDoNothing delegate2(spdy_stream2);
441 spdy_stream2->SetDelegate(&delegate2);
443 scoped_ptr<SpdyHeaderBlock> headers(
444 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
445 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
447 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
448 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
449 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
450 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
452 base::RunLoop().RunUntilIdle();
454 EXPECT_EQ(1u, spdy_stream1->stream_id());
455 EXPECT_EQ(3u, spdy_stream2->stream_id());
457 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
459 // Read and process the first GOAWAY frame.
460 data.CompleteRead();
461 base::RunLoop().RunUntilIdle();
463 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
465 EXPECT_FALSE(session_->IsStreamActive(3));
466 EXPECT_FALSE(spdy_stream2);
467 EXPECT_TRUE(session_->IsStreamActive(1));
468 EXPECT_TRUE(session_->IsGoingAway());
470 // Read and process the second GOAWAY frame, which should close the
471 // session.
472 data.CompleteRead();
473 base::RunLoop().RunUntilIdle();
474 EXPECT_FALSE(session_);
477 // Have a session with active streams receive a GOAWAY frame and then
478 // close it. It should handle the close properly (i.e., not try to
479 // make itself unavailable in its pool twice).
480 TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
481 session_deps_.host_resolver->set_synchronous_mode(true);
483 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
484 MockRead reads[] = {
485 MockRead(ASYNC, ERR_IO_PENDING, 2),
486 CreateMockRead(*goaway, 3),
487 MockRead(ASYNC, ERR_IO_PENDING, 4),
488 MockRead(ASYNC, 0, 5) // EOF
490 scoped_ptr<SpdyFrame> req1(
491 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
492 scoped_ptr<SpdyFrame> req2(
493 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
494 MockWrite writes[] = {
495 CreateMockWrite(*req1, 0),
496 CreateMockWrite(*req2, 1),
498 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
499 session_deps_.socket_factory->AddSocketDataProvider(&data);
501 CreateNetworkSession();
502 CreateInsecureSpdySession();
504 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
506 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
507 SPDY_REQUEST_RESPONSE_STREAM, session_, test_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_, test_url_, MEDIUM, BoundNetLog());
513 test::StreamDelegateDoNothing delegate2(spdy_stream2);
514 spdy_stream2->SetDelegate(&delegate2);
516 scoped_ptr<SpdyHeaderBlock> headers(
517 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
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 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
595 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
596 test::StreamDelegateDoNothing delegate(spdy_stream);
597 spdy_stream->SetDelegate(&delegate);
599 scoped_ptr<SpdyHeaderBlock> headers(
600 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
601 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
602 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
604 base::RunLoop().RunUntilIdle();
606 // Stream and session closed gracefully.
607 EXPECT_TRUE(delegate.StreamIsClosed());
608 EXPECT_EQ(OK, delegate.WaitForClose());
609 EXPECT_EQ(kUploadData, delegate.TakeReceivedData());
610 EXPECT_FALSE(session_);
613 // Try to create a stream after receiving a GOAWAY frame. It should
614 // fail.
615 TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
616 session_deps_.host_resolver->set_synchronous_mode(true);
618 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
619 MockRead reads[] = {
620 MockRead(ASYNC, ERR_IO_PENDING, 1),
621 CreateMockRead(*goaway, 2),
622 MockRead(ASYNC, ERR_IO_PENDING, 3),
623 MockRead(ASYNC, 0, 4) // EOF
625 scoped_ptr<SpdyFrame> req(
626 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
627 MockWrite writes[] = {
628 CreateMockWrite(*req, 0),
630 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
631 session_deps_.socket_factory->AddSocketDataProvider(&data);
633 CreateNetworkSession();
634 CreateInsecureSpdySession();
636 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
638 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
639 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
640 test::StreamDelegateDoNothing delegate(spdy_stream);
641 spdy_stream->SetDelegate(&delegate);
643 scoped_ptr<SpdyHeaderBlock> headers(
644 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
645 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
646 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
648 base::RunLoop().RunUntilIdle();
650 EXPECT_EQ(1u, spdy_stream->stream_id());
652 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
654 // Read and process the GOAWAY frame.
655 data.CompleteRead();
656 base::RunLoop().RunUntilIdle();
658 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
659 EXPECT_TRUE(session_->IsStreamActive(1));
661 SpdyStreamRequest stream_request;
662 int rv = stream_request.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_,
663 test_url_, MEDIUM, BoundNetLog(),
664 CompletionCallback());
665 EXPECT_EQ(ERR_FAILED, rv);
667 EXPECT_TRUE(session_);
668 data.CompleteRead();
669 base::RunLoop().RunUntilIdle();
670 EXPECT_FALSE(session_);
673 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
674 // the stream being refused.
675 TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
676 session_deps_.host_resolver->set_synchronous_mode(true);
678 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
679 scoped_ptr<SpdyFrame> push(
680 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kDefaultURL));
681 MockRead reads[] = {
682 MockRead(ASYNC, ERR_IO_PENDING, 1),
683 CreateMockRead(*goaway, 2),
684 MockRead(ASYNC, ERR_IO_PENDING, 3),
685 CreateMockRead(*push, 4),
686 MockRead(ASYNC, 0, 6) // EOF
688 scoped_ptr<SpdyFrame> req(
689 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
690 scoped_ptr<SpdyFrame> rst(
691 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
692 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5)};
693 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
694 session_deps_.socket_factory->AddSocketDataProvider(&data);
696 CreateNetworkSession();
697 CreateInsecureSpdySession();
699 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
701 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
702 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
703 test::StreamDelegateDoNothing delegate(spdy_stream);
704 spdy_stream->SetDelegate(&delegate);
706 scoped_ptr<SpdyHeaderBlock> headers(
707 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
708 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
709 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
711 base::RunLoop().RunUntilIdle();
713 EXPECT_EQ(1u, spdy_stream->stream_id());
715 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
717 // Read and process the GOAWAY frame.
718 data.CompleteRead();
719 base::RunLoop().RunUntilIdle();
721 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
722 EXPECT_TRUE(session_->IsStreamActive(1));
724 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
725 // and EOF.
726 data.CompleteRead();
727 base::RunLoop().RunUntilIdle();
728 EXPECT_FALSE(session_);
731 // A session observing a network change with active streams should close
732 // when the last active stream is closed.
733 TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
734 session_deps_.host_resolver->set_synchronous_mode(true);
736 MockRead reads[] = {
737 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
739 scoped_ptr<SpdyFrame> req1(
740 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
741 MockWrite writes[] = {
742 CreateMockWrite(*req1, 0),
744 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
745 session_deps_.socket_factory->AddSocketDataProvider(&data);
747 CreateNetworkSession();
748 CreateInsecureSpdySession();
750 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
752 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
753 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
754 test::StreamDelegateDoNothing delegate(spdy_stream);
755 spdy_stream->SetDelegate(&delegate);
757 scoped_ptr<SpdyHeaderBlock> headers(
758 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
760 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
761 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
763 base::RunLoop().RunUntilIdle();
765 EXPECT_EQ(1u, spdy_stream->stream_id());
767 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
769 spdy_session_pool_->OnIPAddressChanged();
771 // The SpdySessionPool behavior differs based on how the OSs reacts to
772 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
773 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
774 // For OSs where the TCP connections will close upon relevant network
775 // changes, SpdySessionPool doesn't need to force them to close, so in these
776 // cases verify the session has become unavailable but remains open and the
777 // pre-existing stream is still active.
778 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
780 EXPECT_TRUE(session_->IsGoingAway());
782 EXPECT_TRUE(session_->IsStreamActive(1));
784 // Should close the session.
785 spdy_stream->Close();
786 #endif
787 EXPECT_FALSE(spdy_stream);
789 data.CompleteRead();
790 base::RunLoop().RunUntilIdle();
791 EXPECT_FALSE(session_);
794 TEST_P(SpdySessionTest, ClientPing) {
795 session_deps_.enable_ping = true;
796 session_deps_.host_resolver->set_synchronous_mode(true);
798 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
799 MockRead reads[] = {
800 CreateMockRead(*read_ping, 1),
801 MockRead(ASYNC, ERR_IO_PENDING, 2),
802 MockRead(ASYNC, 0, 3) // EOF
804 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
805 MockWrite writes[] = {
806 CreateMockWrite(*write_ping, 0),
808 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
809 session_deps_.socket_factory->AddSocketDataProvider(&data);
811 CreateNetworkSession();
812 CreateInsecureSpdySession();
814 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
815 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
816 ASSERT_TRUE(spdy_stream1.get() != nullptr);
817 test::StreamDelegateSendImmediate delegate(spdy_stream1, nullptr);
818 spdy_stream1->SetDelegate(&delegate);
820 base::TimeTicks before_ping_time = base::TimeTicks::Now();
822 session_->set_connection_at_risk_of_loss_time(
823 base::TimeDelta::FromSeconds(-1));
824 session_->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
826 session_->SendPrefacePingIfNoneInFlight();
828 base::RunLoop().RunUntilIdle();
830 session_->CheckPingStatus(before_ping_time);
832 EXPECT_EQ(0, session_->pings_in_flight());
833 EXPECT_GE(session_->next_ping_id(), 1U);
834 EXPECT_FALSE(session_->check_ping_status_pending());
835 EXPECT_GE(session_->last_activity_time(), before_ping_time);
837 data.CompleteRead();
838 base::RunLoop().RunUntilIdle();
840 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
842 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
843 EXPECT_FALSE(session_);
846 TEST_P(SpdySessionTest, ServerPing) {
847 session_deps_.host_resolver->set_synchronous_mode(true);
849 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
850 MockRead reads[] = {
851 CreateMockRead(*read_ping),
852 MockRead(SYNCHRONOUS, 0, 0) // EOF
854 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
855 MockWrite writes[] = {
856 CreateMockWrite(*write_ping),
858 StaticSocketDataProvider data(
859 reads, arraysize(reads), writes, arraysize(writes));
860 session_deps_.socket_factory->AddSocketDataProvider(&data);
862 CreateNetworkSession();
863 CreateInsecureSpdySession();
865 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
866 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
867 ASSERT_TRUE(spdy_stream1.get() != nullptr);
868 test::StreamDelegateSendImmediate delegate(spdy_stream1, nullptr);
869 spdy_stream1->SetDelegate(&delegate);
871 // Flush the read completion task.
872 base::RunLoop().RunUntilIdle();
874 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
876 EXPECT_FALSE(session_);
877 EXPECT_FALSE(spdy_stream1);
880 // Cause a ping to be sent out while producing a write. The write loop
881 // should handle this properly, i.e. another DoWriteLoop task should
882 // not be posted. This is a regression test for
883 // http://crbug.com/261043 .
884 TEST_P(SpdySessionTest, PingAndWriteLoop) {
885 session_deps_.enable_ping = true;
886 session_deps_.time_func = TheNearFuture;
888 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
889 scoped_ptr<SpdyFrame> req(
890 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
891 MockWrite writes[] = {
892 CreateMockWrite(*req, 0),
893 CreateMockWrite(*write_ping, 1),
896 MockRead reads[] = {
897 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
900 session_deps_.host_resolver->set_synchronous_mode(true);
902 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
903 session_deps_.socket_factory->AddSocketDataProvider(&data);
905 CreateNetworkSession();
906 CreateInsecureSpdySession();
908 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
909 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
910 test::StreamDelegateDoNothing delegate(spdy_stream);
911 spdy_stream->SetDelegate(&delegate);
913 scoped_ptr<SpdyHeaderBlock> headers(
914 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
915 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
917 // Shift time so that a ping will be sent out.
918 g_time_delta = base::TimeDelta::FromSeconds(11);
920 base::RunLoop().RunUntilIdle();
921 session_->CloseSessionOnError(ERR_ABORTED, "Aborting");
923 data.CompleteRead();
924 base::RunLoop().RunUntilIdle();
925 EXPECT_FALSE(session_);
928 TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
929 const SpdyStreamId kLastStreamId = 0x7fffffff;
930 session_deps_.host_resolver->set_synchronous_mode(true);
932 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
933 // fixed to allow for two stream ID assignments, and three concurrent
934 // streams. Four streams are started, and two are activated. Verify the
935 // session goes away, and that the created (but not activated) and
936 // stalled streams are aborted. Also verify the activated streams complete,
937 // at which point the session closes.
939 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
940 nullptr, 0, false, kLastStreamId - 2, MEDIUM, true));
941 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
942 nullptr, 0, false, kLastStreamId, MEDIUM, true));
944 MockWrite writes[] = {
945 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
948 scoped_ptr<SpdyFrame> resp1(
949 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId - 2));
950 scoped_ptr<SpdyFrame> resp2(
951 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId));
953 scoped_ptr<SpdyFrame> body1(
954 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
955 scoped_ptr<SpdyFrame> body2(
956 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
958 MockRead reads[] = {
959 CreateMockRead(*resp1, 2),
960 CreateMockRead(*resp2, 3),
961 MockRead(ASYNC, ERR_IO_PENDING, 4),
962 CreateMockRead(*body1, 5),
963 CreateMockRead(*body2, 6),
964 MockRead(ASYNC, 0, 7) // EOF
967 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
968 session_deps_.socket_factory->AddSocketDataProvider(&data);
970 CreateNetworkSession();
971 CreateInsecureSpdySession();
973 // Fix stream_hi_water_mark_ to allow for two stream activations.
974 session_->stream_hi_water_mark_ = kLastStreamId - 2;
975 // Fix max_concurrent_streams to allow for three stream creations.
976 session_->max_concurrent_streams_ = 3;
978 // Create three streams synchronously, and begin a fourth (which is stalled).
979 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
980 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
981 test::StreamDelegateDoNothing delegate1(stream1);
982 stream1->SetDelegate(&delegate1);
984 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
985 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
986 test::StreamDelegateDoNothing delegate2(stream2);
987 stream2->SetDelegate(&delegate2);
989 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
990 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
991 test::StreamDelegateDoNothing delegate3(stream3);
992 stream3->SetDelegate(&delegate3);
994 SpdyStreamRequest request4;
995 TestCompletionCallback callback4;
996 EXPECT_EQ(
997 ERR_IO_PENDING,
998 request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_,
999 MEDIUM, BoundNetLog(), callback4.callback()));
1001 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1002 EXPECT_EQ(0u, session_->num_active_streams());
1003 EXPECT_EQ(3u, session_->num_created_streams());
1004 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(MEDIUM));
1006 // Activate stream 1. One ID remains available.
1007 stream1->SendRequestHeaders(
1008 scoped_ptr<SpdyHeaderBlock>(
1009 spdy_util_.ConstructGetHeaderBlock(kDefaultURL)),
1010 NO_MORE_DATA_TO_SEND);
1011 base::RunLoop().RunUntilIdle();
1013 EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1014 EXPECT_EQ(1u, session_->num_active_streams());
1015 EXPECT_EQ(2u, session_->num_created_streams());
1016 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(MEDIUM));
1018 // Activate stream 2. ID space is exhausted.
1019 stream2->SendRequestHeaders(
1020 scoped_ptr<SpdyHeaderBlock>(
1021 spdy_util_.ConstructGetHeaderBlock(kDefaultURL)),
1022 NO_MORE_DATA_TO_SEND);
1023 base::RunLoop().RunUntilIdle();
1025 // Active streams remain active.
1026 EXPECT_EQ(kLastStreamId, stream2->stream_id());
1027 EXPECT_EQ(2u, session_->num_active_streams());
1029 // Session is going away. Created and stalled streams were aborted.
1030 EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session_->availability_state_);
1031 EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose());
1032 EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult());
1033 EXPECT_EQ(0u, session_->num_created_streams());
1034 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(MEDIUM));
1036 // Read responses on remaining active streams.
1037 data.CompleteRead();
1038 base::RunLoop().RunUntilIdle();
1039 EXPECT_EQ(OK, delegate1.WaitForClose());
1040 EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1041 EXPECT_EQ(OK, delegate2.WaitForClose());
1042 EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1044 // Session was destroyed.
1045 EXPECT_FALSE(session_);
1048 // Verifies that an unstalled pending stream creation racing with a new stream
1049 // creation doesn't violate the maximum stream concurrency. Regression test for
1050 // crbug.com/373858.
1051 TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) {
1052 session_deps_.host_resolver->set_synchronous_mode(true);
1054 MockRead reads[] = {
1055 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1058 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1059 session_deps_.socket_factory->AddSocketDataProvider(&data);
1061 CreateNetworkSession();
1062 CreateInsecureSpdySession();
1064 // Fix max_concurrent_streams to allow for one open stream.
1065 session_->max_concurrent_streams_ = 1;
1067 // Create two streams: one synchronously, and one which stalls.
1068 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1069 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1071 SpdyStreamRequest request2;
1072 TestCompletionCallback callback2;
1073 EXPECT_EQ(
1074 ERR_IO_PENDING,
1075 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_,
1076 MEDIUM, BoundNetLog(), callback2.callback()));
1078 EXPECT_EQ(1u, session_->num_created_streams());
1079 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(MEDIUM));
1081 // Cancel the first stream. A callback to unstall the second stream was
1082 // posted. Don't run it yet.
1083 stream1->Cancel();
1085 EXPECT_EQ(0u, session_->num_created_streams());
1086 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(MEDIUM));
1088 // Create a third stream prior to the second stream's callback.
1089 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1090 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1092 EXPECT_EQ(1u, session_->num_created_streams());
1093 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(MEDIUM));
1095 // Now run the message loop. The unstalled stream will re-stall itself.
1096 base::RunLoop().RunUntilIdle();
1097 EXPECT_EQ(1u, session_->num_created_streams());
1098 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(MEDIUM));
1100 // Cancel the third stream and run the message loop. Verify that the second
1101 // stream creation now completes.
1102 stream3->Cancel();
1103 base::RunLoop().RunUntilIdle();
1105 EXPECT_EQ(1u, session_->num_created_streams());
1106 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(MEDIUM));
1107 EXPECT_EQ(OK, callback2.WaitForResult());
1110 TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
1111 session_deps_.host_resolver->set_synchronous_mode(true);
1112 session_deps_.time_func = TheNearFuture;
1114 scoped_ptr<SpdyFrame> req(
1115 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
1116 scoped_ptr<SpdyFrame> rst(
1117 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
1118 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5)};
1120 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
1121 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
1122 scoped_ptr<SpdyFrame> push_a_body(
1123 spdy_util_.ConstructSpdyBodyFrame(2, false));
1124 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1125 // iterators inside. See http://crbug.com/443490
1126 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
1127 nullptr, 0, 4, 1, "http://www.example.org/0.dat"));
1128 MockRead reads[] = {
1129 CreateMockRead(*push_a, 1),
1130 CreateMockRead(*push_a_body, 2),
1131 MockRead(ASYNC, ERR_IO_PENDING, 3),
1132 CreateMockRead(*push_b, 4),
1133 MockRead(ASYNC, ERR_IO_PENDING, 6),
1134 MockRead(ASYNC, 0, 7) // EOF
1137 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1138 session_deps_.socket_factory->AddSocketDataProvider(&data);
1140 CreateNetworkSession();
1141 CreateInsecureSpdySession();
1143 // Process the principal request, and the first push stream request & body.
1144 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1145 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1146 test::StreamDelegateDoNothing delegate(spdy_stream);
1147 spdy_stream->SetDelegate(&delegate);
1149 scoped_ptr<SpdyHeaderBlock> headers(
1150 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1151 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1153 base::RunLoop().RunUntilIdle();
1155 // Verify that there is one unclaimed push stream.
1156 EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
1157 SpdySession::PushedStreamMap::iterator iter =
1158 session_->unclaimed_pushed_streams_.find(
1159 GURL("http://www.example.org/a.dat"));
1160 EXPECT_TRUE(session_->unclaimed_pushed_streams_.end() != iter);
1162 if (session_->flow_control_state_ ==
1163 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1164 // Unclaimed push body consumed bytes from the session window.
1165 EXPECT_EQ(
1166 SpdySession::GetDefaultInitialWindowSize(GetParam()) - kUploadDataSize,
1167 session_->session_recv_window_size_);
1168 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
1171 // Shift time to expire the push stream. Read the second SYN_STREAM,
1172 // and verify a RST_STREAM was written.
1173 g_time_delta = base::TimeDelta::FromSeconds(301);
1174 data.CompleteRead();
1175 base::RunLoop().RunUntilIdle();
1177 // Verify that the second pushed stream evicted the first pushed stream.
1178 EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
1179 iter = session_->unclaimed_pushed_streams_.find(
1180 GURL("http://www.example.org/0.dat"));
1181 EXPECT_TRUE(session_->unclaimed_pushed_streams_.end() != iter);
1183 if (session_->flow_control_state_ ==
1184 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1185 // Verify that the session window reclaimed the evicted stream body.
1186 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
1187 session_->session_recv_window_size_);
1188 EXPECT_EQ(kUploadDataSize, session_->session_unacked_recv_window_bytes_);
1191 // Read and process EOF.
1192 EXPECT_TRUE(session_);
1193 data.CompleteRead();
1194 base::RunLoop().RunUntilIdle();
1195 EXPECT_FALSE(session_);
1198 TEST_P(SpdySessionTest, FailedPing) {
1199 session_deps_.host_resolver->set_synchronous_mode(true);
1201 MockRead reads[] = {
1202 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1204 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
1205 scoped_ptr<SpdyFrame> goaway(
1206 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping."));
1207 MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)};
1209 StaticSocketDataProvider data(
1210 reads, arraysize(reads), writes, arraysize(writes));
1211 session_deps_.socket_factory->AddSocketDataProvider(&data);
1213 CreateNetworkSession();
1214 CreateInsecureSpdySession();
1216 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1217 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1218 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1219 test::StreamDelegateSendImmediate delegate(spdy_stream1, nullptr);
1220 spdy_stream1->SetDelegate(&delegate);
1222 session_->set_connection_at_risk_of_loss_time(
1223 base::TimeDelta::FromSeconds(0));
1224 session_->set_hung_interval(base::TimeDelta::FromSeconds(0));
1226 // Send a PING frame.
1227 session_->WritePingFrame(1, false);
1228 EXPECT_LT(0, session_->pings_in_flight());
1229 EXPECT_GE(session_->next_ping_id(), 1U);
1230 EXPECT_TRUE(session_->check_ping_status_pending());
1232 // Assert session is not closed.
1233 EXPECT_TRUE(session_->IsAvailable());
1234 EXPECT_LT(0u,
1235 session_->num_active_streams() + session_->num_created_streams());
1236 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1238 // We set last time we have received any data in 1 sec less than now.
1239 // CheckPingStatus will trigger timeout because hung interval is zero.
1240 base::TimeTicks now = base::TimeTicks::Now();
1241 session_->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
1242 session_->CheckPingStatus(now);
1243 base::RunLoop().RunUntilIdle();
1245 EXPECT_FALSE(session_);
1246 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1247 EXPECT_FALSE(spdy_stream1);
1250 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1251 // settings frame increasing the max concurrent streams by 1. Make
1252 // sure nothing blows up. This is a regression test for
1253 // http://crbug.com/57331 .
1254 TEST_P(SpdySessionTest, OnSettings) {
1255 session_deps_.host_resolver->set_synchronous_mode(true);
1257 const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1259 int seq = 0;
1260 std::vector<MockWrite> writes;
1261 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1262 if (GetParam() == kProtoHTTP2) {
1263 writes.push_back(CreateMockWrite(*settings_ack, ++seq));
1266 SettingsMap new_settings;
1267 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1268 new_settings[kSpdySettingsIds] =
1269 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1270 scoped_ptr<SpdyFrame> settings_frame(
1271 spdy_util_.ConstructSpdySettings(new_settings));
1272 MockRead reads[] = {
1273 CreateMockRead(*settings_frame, 0),
1274 MockRead(ASYNC, ERR_IO_PENDING, ++seq),
1275 MockRead(ASYNC, 0, ++seq),
1278 SequencedSocketData data(reads, arraysize(reads), vector_as_array(&writes),
1279 writes.size());
1280 session_deps_.socket_factory->AddSocketDataProvider(&data);
1282 CreateNetworkSession();
1283 CreateInsecureSpdySession();
1285 // Create the maximum number of concurrent streams.
1286 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1287 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1288 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1289 ASSERT_TRUE(spdy_stream != nullptr);
1292 StreamReleaserCallback stream_releaser;
1293 SpdyStreamRequest request;
1294 ASSERT_EQ(ERR_IO_PENDING,
1295 request.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1296 MEDIUM, BoundNetLog(),
1297 stream_releaser.MakeCallback(&request)));
1299 base::RunLoop().RunUntilIdle();
1301 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1303 data.CompleteRead();
1304 base::RunLoop().RunUntilIdle();
1305 EXPECT_FALSE(session_);
1307 EXPECT_TRUE(data.AllWriteDataConsumed());
1308 EXPECT_TRUE(data.AllReadDataConsumed());
1311 // Start with a persisted value for max concurrent streams. Receive a
1312 // settings frame increasing the max concurrent streams by 1 and which
1313 // also clears the persisted data. Verify that persisted data is
1314 // correct.
1315 TEST_P(SpdySessionTest, ClearSettings) {
1316 if (spdy_util_.spdy_version() >= HTTP2) {
1317 // HTTP/2 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1318 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in HTTP/2.
1319 return;
1321 session_deps_.host_resolver->set_synchronous_mode(true);
1323 SettingsMap new_settings;
1324 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1325 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1326 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1327 scoped_ptr<SpdyFrame> settings_frame(
1328 spdy_util_.ConstructSpdySettings(new_settings));
1329 uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1330 test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1331 MockRead reads[] = {
1332 CreateMockRead(*settings_frame, 0),
1333 MockRead(ASYNC, ERR_IO_PENDING, 1),
1334 MockRead(ASYNC, 0, 2),
1337 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
1338 session_deps_.socket_factory->AddSocketDataProvider(&data);
1340 CreateNetworkSession();
1342 // Initialize the SpdySetting with the default.
1343 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1344 test_host_port_pair_,
1345 SETTINGS_MAX_CONCURRENT_STREAMS,
1346 SETTINGS_FLAG_PLEASE_PERSIST,
1347 kInitialMaxConcurrentStreams);
1349 EXPECT_FALSE(
1350 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1351 test_host_port_pair_).empty());
1353 CreateInsecureSpdySession();
1355 // Create the maximum number of concurrent streams.
1356 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1357 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1358 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1359 ASSERT_TRUE(spdy_stream != nullptr);
1362 StreamReleaserCallback stream_releaser;
1364 SpdyStreamRequest request;
1365 ASSERT_EQ(ERR_IO_PENDING,
1366 request.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1367 MEDIUM, BoundNetLog(),
1368 stream_releaser.MakeCallback(&request)));
1370 base::RunLoop().RunUntilIdle();
1372 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1374 // Make sure that persisted data is cleared.
1375 EXPECT_TRUE(
1376 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1377 test_host_port_pair_).empty());
1379 // Make sure session's max_concurrent_streams is correct.
1380 EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1381 session_->max_concurrent_streams());
1383 data.CompleteRead();
1384 base::RunLoop().RunUntilIdle();
1385 EXPECT_FALSE(session_);
1388 // Start with max concurrent streams set to 1. Request two streams.
1389 // When the first completes, have the callback close its stream, which
1390 // should trigger the second stream creation. Then cancel that one
1391 // immediately. Don't crash. This is a regression test for
1392 // http://crbug.com/63532 .
1393 TEST_P(SpdySessionTest, CancelPendingCreateStream) {
1394 session_deps_.host_resolver->set_synchronous_mode(true);
1396 MockRead reads[] = {
1397 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1400 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1401 session_deps_.socket_factory->AddSocketDataProvider(&data);
1403 CreateNetworkSession();
1405 // Initialize the SpdySetting with 1 max concurrent streams.
1406 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1407 test_host_port_pair_,
1408 SETTINGS_MAX_CONCURRENT_STREAMS,
1409 SETTINGS_FLAG_PLEASE_PERSIST,
1412 CreateInsecureSpdySession();
1414 // Leave room for only one more stream to be created.
1415 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1416 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1417 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1418 ASSERT_TRUE(spdy_stream != nullptr);
1421 // Create 2 more streams. First will succeed. Second will be pending.
1422 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1423 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1424 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1426 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1427 // a valgrind error if the callback is invoked when it's not supposed to be.
1428 scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
1430 SpdyStreamRequest request;
1431 ASSERT_EQ(ERR_IO_PENDING,
1432 request.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1433 MEDIUM, BoundNetLog(), callback->callback()));
1435 // Release the first one, this will allow the second to be created.
1436 spdy_stream1->Cancel();
1437 EXPECT_FALSE(spdy_stream1);
1439 request.CancelRequest();
1440 callback.reset();
1442 // Should not crash when running the pending callback.
1443 base::RunLoop().RunUntilIdle();
1446 TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
1447 session_deps_.host_resolver->set_synchronous_mode(true);
1449 MockRead reads[] = {
1450 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1453 SettingsMap settings;
1454 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1455 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
1456 scoped_ptr<SpdyFrame> settings_frame(
1457 spdy_util_.ConstructSpdySettings(settings));
1458 std::vector<MockWrite> writes;
1459 if (GetParam() == kProtoHTTP2) {
1460 writes.push_back(
1461 MockWrite(ASYNC,
1462 kHttp2ConnectionHeaderPrefix,
1463 kHttp2ConnectionHeaderPrefixSize));
1465 writes.push_back(CreateMockWrite(*settings_frame));
1467 SettingsMap server_settings;
1468 const uint32 initial_max_concurrent_streams = 1;
1469 server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1470 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1471 initial_max_concurrent_streams);
1472 scoped_ptr<SpdyFrame> server_settings_frame(
1473 spdy_util_.ConstructSpdySettings(server_settings));
1474 if (GetParam() <= kProtoSPDY31) {
1475 writes.push_back(CreateMockWrite(*server_settings_frame));
1478 StaticSocketDataProvider data(reads, arraysize(reads),
1479 vector_as_array(&writes), writes.size());
1480 session_deps_.socket_factory->AddSocketDataProvider(&data);
1482 CreateNetworkSession();
1484 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1485 test_host_port_pair_,
1486 SETTINGS_MAX_CONCURRENT_STREAMS,
1487 SETTINGS_FLAG_PLEASE_PERSIST,
1488 initial_max_concurrent_streams);
1490 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1491 pool_peer.SetEnableSendingInitialData(true);
1493 CreateInsecureSpdySession();
1495 base::RunLoop().RunUntilIdle();
1496 EXPECT_TRUE(data.AllWriteDataConsumed());
1499 TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
1500 CreateNetworkSession();
1502 base::WeakPtr<HttpServerProperties> test_http_server_properties =
1503 spdy_session_pool_->http_server_properties();
1504 SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
1505 test_http_server_properties->SetSpdySetting(
1506 test_host_port_pair_,
1507 SETTINGS_MAX_CONCURRENT_STREAMS,
1508 SETTINGS_FLAG_PLEASE_PERSIST,
1510 EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
1511 test_host_port_pair_).size());
1512 spdy_session_pool_->OnIPAddressChanged();
1513 EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
1514 test_host_port_pair_).size());
1517 TEST_P(SpdySessionTest, Initialize) {
1518 session_deps_.host_resolver->set_synchronous_mode(true);
1520 MockRead reads[] = {
1521 MockRead(ASYNC, 0, 0) // EOF
1524 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1525 session_deps_.socket_factory->AddSocketDataProvider(&data);
1527 CreateNetworkSession();
1528 CreateInsecureSpdySession();
1529 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1531 // Flush the read completion task.
1532 base::RunLoop().RunUntilIdle();
1534 TestNetLogEntry::List entries;
1535 log_.GetEntries(&entries);
1536 EXPECT_LT(0u, entries.size());
1538 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1539 int pos = ExpectLogContainsSomewhere(
1540 entries, 0, NetLog::TYPE_HTTP2_SESSION_INITIALIZED, NetLog::PHASE_NONE);
1541 EXPECT_LT(0, pos);
1543 TestNetLogEntry entry = entries[pos];
1544 NetLog::Source socket_source;
1545 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1546 &socket_source));
1547 EXPECT_TRUE(socket_source.IsValid());
1548 EXPECT_NE(log_.bound().source().id, socket_source.id);
1551 TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
1552 session_deps_.host_resolver->set_synchronous_mode(true);
1554 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
1555 MockRead reads[] = {
1556 CreateMockRead(*goaway),
1557 MockRead(SYNCHRONOUS, 0, 0) // EOF
1560 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1561 session_deps_.socket_factory->AddSocketDataProvider(&data);
1563 CreateNetworkSession();
1564 CreateInsecureSpdySession();
1565 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1567 // Flush the read completion task.
1568 base::RunLoop().RunUntilIdle();
1570 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1571 EXPECT_FALSE(session_);
1573 // Check that the NetLog was filled reasonably.
1574 TestNetLogEntry::List entries;
1575 log_.GetEntries(&entries);
1576 EXPECT_LT(0u, entries.size());
1578 // Check that we logged SPDY_SESSION_CLOSE correctly.
1579 int pos = ExpectLogContainsSomewhere(
1580 entries, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE, NetLog::PHASE_NONE);
1582 if (pos < static_cast<int>(entries.size())) {
1583 TestNetLogEntry entry = entries[pos];
1584 int error_code = 0;
1585 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1586 EXPECT_EQ(OK, error_code);
1587 } else {
1588 ADD_FAILURE();
1592 TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1593 session_deps_.host_resolver->set_synchronous_mode(true);
1595 MockRead reads[] = {
1596 MockRead(SYNCHRONOUS, 0, 0) // EOF
1599 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1600 session_deps_.socket_factory->AddSocketDataProvider(&data);
1602 CreateNetworkSession();
1603 CreateInsecureSpdySession();
1604 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1606 // Flush the read completion task.
1607 base::RunLoop().RunUntilIdle();
1609 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1610 EXPECT_FALSE(session_);
1612 // Check that the NetLog was filled reasonably.
1613 TestNetLogEntry::List entries;
1614 log_.GetEntries(&entries);
1615 EXPECT_LT(0u, entries.size());
1617 // Check that we logged SPDY_SESSION_CLOSE correctly.
1618 int pos = ExpectLogContainsSomewhere(
1619 entries, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE, NetLog::PHASE_NONE);
1621 if (pos < static_cast<int>(entries.size())) {
1622 TestNetLogEntry entry = entries[pos];
1623 int error_code = 0;
1624 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1625 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1626 } else {
1627 ADD_FAILURE();
1631 TEST_P(SpdySessionTest, SynCompressionHistograms) {
1632 session_deps_.enable_compression = true;
1634 scoped_ptr<SpdyFrame> req(
1635 spdy_util_.ConstructSpdyGet(nullptr, 0, true, 1, MEDIUM, true));
1636 MockWrite writes[] = {
1637 CreateMockWrite(*req, 0),
1639 MockRead reads[] = {
1640 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
1642 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1643 session_deps_.socket_factory->AddSocketDataProvider(&data);
1645 CreateNetworkSession();
1646 CreateInsecureSpdySession();
1648 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1649 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1650 test::StreamDelegateDoNothing delegate(spdy_stream);
1651 spdy_stream->SetDelegate(&delegate);
1653 scoped_ptr<SpdyHeaderBlock> headers(
1654 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1655 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1656 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1658 // Write request headers & capture resulting histogram update.
1659 base::HistogramTester histogram_tester;
1661 base::RunLoop().RunUntilIdle();
1662 // Regression test of compression performance under the request fixture.
1663 switch (spdy_util_.spdy_version()) {
1664 case SPDY3:
1665 histogram_tester.ExpectBucketCount(
1666 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1667 break;
1668 case HTTP2:
1669 histogram_tester.ExpectBucketCount(
1670 "Net.SpdySynStreamCompressionPercentage", 81, 1);
1671 break;
1672 default:
1673 NOTREACHED();
1676 // Read and process EOF.
1677 EXPECT_TRUE(session_);
1678 data.CompleteRead();
1679 base::RunLoop().RunUntilIdle();
1680 EXPECT_FALSE(session_);
1683 // Queue up a low-priority SYN_STREAM followed by a high-priority
1684 // one. The high priority one should still send first and receive
1685 // first.
1686 TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1687 // Construct the request.
1688 scoped_ptr<SpdyFrame> req_highest(
1689 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, HIGHEST, true));
1690 scoped_ptr<SpdyFrame> req_lowest(
1691 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST, true));
1692 MockWrite writes[] = {
1693 CreateMockWrite(*req_highest, 0),
1694 CreateMockWrite(*req_lowest, 1),
1697 scoped_ptr<SpdyFrame> resp_highest(
1698 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
1699 scoped_ptr<SpdyFrame> body_highest(
1700 spdy_util_.ConstructSpdyBodyFrame(1, true));
1701 scoped_ptr<SpdyFrame> resp_lowest(
1702 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
1703 scoped_ptr<SpdyFrame> body_lowest(
1704 spdy_util_.ConstructSpdyBodyFrame(3, true));
1705 MockRead reads[] = {
1706 CreateMockRead(*resp_highest, 2),
1707 CreateMockRead(*body_highest, 3),
1708 CreateMockRead(*resp_lowest, 4),
1709 CreateMockRead(*body_lowest, 5),
1710 MockRead(ASYNC, 0, 6) // EOF
1713 session_deps_.host_resolver->set_synchronous_mode(true);
1715 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1716 session_deps_.socket_factory->AddSocketDataProvider(&data);
1718 CreateNetworkSession();
1719 CreateInsecureSpdySession();
1721 base::WeakPtr<SpdyStream> spdy_stream_lowest = CreateStreamSynchronously(
1722 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
1723 ASSERT_TRUE(spdy_stream_lowest);
1724 EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1725 test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1726 spdy_stream_lowest->SetDelegate(&delegate_lowest);
1728 base::WeakPtr<SpdyStream> spdy_stream_highest =
1729 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
1730 test_url_, HIGHEST, BoundNetLog());
1731 ASSERT_TRUE(spdy_stream_highest);
1732 EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1733 test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1734 spdy_stream_highest->SetDelegate(&delegate_highest);
1736 // Queue the lower priority one first.
1738 scoped_ptr<SpdyHeaderBlock> headers_lowest(
1739 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1740 spdy_stream_lowest->SendRequestHeaders(
1741 headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1742 EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1744 scoped_ptr<SpdyHeaderBlock> headers_highest(
1745 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1746 spdy_stream_highest->SendRequestHeaders(
1747 headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1748 EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1750 base::RunLoop().RunUntilIdle();
1752 EXPECT_FALSE(spdy_stream_lowest);
1753 EXPECT_FALSE(spdy_stream_highest);
1754 EXPECT_EQ(3u, delegate_lowest.stream_id());
1755 EXPECT_EQ(1u, delegate_highest.stream_id());
1758 TEST_P(SpdySessionTest, CancelStream) {
1759 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1760 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1761 scoped_ptr<SpdyFrame> req2(
1762 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
1763 MockWrite writes[] = {
1764 CreateMockWrite(*req2, 0),
1767 scoped_ptr<SpdyFrame> resp2(
1768 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
1769 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1770 MockRead reads[] = {
1771 CreateMockRead(*resp2, 1),
1772 MockRead(ASYNC, ERR_IO_PENDING, 2),
1773 CreateMockRead(*body2, 3),
1774 MockRead(ASYNC, 0, 4) // EOF
1777 session_deps_.host_resolver->set_synchronous_mode(true);
1779 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1780 session_deps_.socket_factory->AddSocketDataProvider(&data);
1782 CreateNetworkSession();
1783 CreateInsecureSpdySession();
1785 base::WeakPtr<SpdyStream> spdy_stream1 =
1786 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
1787 test_url_, HIGHEST, BoundNetLog());
1788 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1789 EXPECT_EQ(0u, spdy_stream1->stream_id());
1790 test::StreamDelegateDoNothing delegate1(spdy_stream1);
1791 spdy_stream1->SetDelegate(&delegate1);
1793 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
1794 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
1795 ASSERT_TRUE(spdy_stream2.get() != nullptr);
1796 EXPECT_EQ(0u, spdy_stream2->stream_id());
1797 test::StreamDelegateDoNothing delegate2(spdy_stream2);
1798 spdy_stream2->SetDelegate(&delegate2);
1800 scoped_ptr<SpdyHeaderBlock> headers(
1801 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1802 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1803 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1805 scoped_ptr<SpdyHeaderBlock> headers2(
1806 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1807 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1808 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1810 EXPECT_EQ(0u, spdy_stream1->stream_id());
1812 spdy_stream1->Cancel();
1813 EXPECT_FALSE(spdy_stream1);
1815 EXPECT_EQ(0u, delegate1.stream_id());
1817 base::RunLoop().RunUntilIdle();
1819 EXPECT_EQ(0u, delegate1.stream_id());
1820 EXPECT_EQ(1u, delegate2.stream_id());
1822 spdy_stream2->Cancel();
1823 EXPECT_FALSE(spdy_stream2);
1826 // Create two streams that are set to re-close themselves on close,
1827 // and then close the session. Nothing should blow up. Also a
1828 // regression test for http://crbug.com/139518 .
1829 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1830 session_deps_.host_resolver->set_synchronous_mode(true);
1833 // No actual data will be sent.
1834 MockWrite writes[] = {
1835 MockWrite(ASYNC, 0, 1) // EOF
1838 MockRead reads[] = {
1839 MockRead(ASYNC, 0, 0) // EOF
1841 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1842 session_deps_.socket_factory->AddSocketDataProvider(&data);
1844 CreateNetworkSession();
1845 CreateInsecureSpdySession();
1847 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1848 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, HIGHEST, BoundNetLog());
1849 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1850 EXPECT_EQ(0u, spdy_stream1->stream_id());
1852 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
1853 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, LOWEST, BoundNetLog());
1854 ASSERT_TRUE(spdy_stream2.get() != nullptr);
1855 EXPECT_EQ(0u, spdy_stream2->stream_id());
1857 test::ClosingDelegate delegate1(spdy_stream1);
1858 spdy_stream1->SetDelegate(&delegate1);
1860 test::ClosingDelegate delegate2(spdy_stream2);
1861 spdy_stream2->SetDelegate(&delegate2);
1863 scoped_ptr<SpdyHeaderBlock> headers(
1864 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1865 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1866 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1868 scoped_ptr<SpdyHeaderBlock> headers2(
1869 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1870 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1871 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1873 // Ensure that the streams have not yet been activated and assigned an id.
1874 EXPECT_EQ(0u, spdy_stream1->stream_id());
1875 EXPECT_EQ(0u, spdy_stream2->stream_id());
1877 // Ensure we don't crash while closing the session.
1878 session_->CloseSessionOnError(ERR_ABORTED, std::string());
1880 EXPECT_FALSE(spdy_stream1);
1881 EXPECT_FALSE(spdy_stream2);
1883 EXPECT_TRUE(delegate1.StreamIsClosed());
1884 EXPECT_TRUE(delegate2.StreamIsClosed());
1886 base::RunLoop().RunUntilIdle();
1887 EXPECT_FALSE(session_);
1890 // Create two streams that are set to close each other on close, and
1891 // then close the session. Nothing should blow up.
1892 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
1893 session_deps_.host_resolver->set_synchronous_mode(true);
1895 SequencedSocketData data(nullptr, 0, nullptr, 0);
1896 session_deps_.socket_factory->AddSocketDataProvider(&data);
1898 CreateNetworkSession();
1899 CreateInsecureSpdySession();
1901 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1902 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, HIGHEST, BoundNetLog());
1903 ASSERT_TRUE(spdy_stream1);
1904 EXPECT_EQ(0u, spdy_stream1->stream_id());
1906 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
1907 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, LOWEST, BoundNetLog());
1908 ASSERT_TRUE(spdy_stream2);
1909 EXPECT_EQ(0u, spdy_stream2->stream_id());
1911 // Make |spdy_stream1| close |spdy_stream2|.
1912 test::ClosingDelegate delegate1(spdy_stream2);
1913 spdy_stream1->SetDelegate(&delegate1);
1915 // Make |spdy_stream2| close |spdy_stream1|.
1916 test::ClosingDelegate delegate2(spdy_stream1);
1917 spdy_stream2->SetDelegate(&delegate2);
1919 scoped_ptr<SpdyHeaderBlock> headers(
1920 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1921 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1922 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1924 scoped_ptr<SpdyHeaderBlock> headers2(
1925 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1926 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1927 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1929 // Ensure that the streams have not yet been activated and assigned an id.
1930 EXPECT_EQ(0u, spdy_stream1->stream_id());
1931 EXPECT_EQ(0u, spdy_stream2->stream_id());
1933 // Ensure we don't crash while closing the session.
1934 session_->CloseSessionOnError(ERR_ABORTED, std::string());
1936 EXPECT_FALSE(spdy_stream1);
1937 EXPECT_FALSE(spdy_stream2);
1939 EXPECT_TRUE(delegate1.StreamIsClosed());
1940 EXPECT_TRUE(delegate2.StreamIsClosed());
1942 base::RunLoop().RunUntilIdle();
1943 EXPECT_FALSE(session_);
1946 // Create two streams that are set to re-close themselves on close,
1947 // activate them, and then close the session. Nothing should blow up.
1948 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
1949 session_deps_.host_resolver->set_synchronous_mode(true);
1951 scoped_ptr<SpdyFrame> req1(
1952 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
1953 scoped_ptr<SpdyFrame> req2(
1954 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
1955 MockWrite writes[] = {
1956 CreateMockWrite(*req1, 0),
1957 CreateMockWrite(*req2, 1),
1960 MockRead reads[] = {
1961 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
1964 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1965 session_deps_.socket_factory->AddSocketDataProvider(&data);
1967 CreateNetworkSession();
1968 CreateInsecureSpdySession();
1970 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1971 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1972 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1973 EXPECT_EQ(0u, spdy_stream1->stream_id());
1975 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
1976 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1977 ASSERT_TRUE(spdy_stream2.get() != nullptr);
1978 EXPECT_EQ(0u, spdy_stream2->stream_id());
1980 test::ClosingDelegate delegate1(spdy_stream1);
1981 spdy_stream1->SetDelegate(&delegate1);
1983 test::ClosingDelegate delegate2(spdy_stream2);
1984 spdy_stream2->SetDelegate(&delegate2);
1986 scoped_ptr<SpdyHeaderBlock> headers(
1987 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1988 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1989 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1991 scoped_ptr<SpdyHeaderBlock> headers2(
1992 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1993 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1994 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1996 // Ensure that the streams have not yet been activated and assigned an id.
1997 EXPECT_EQ(0u, spdy_stream1->stream_id());
1998 EXPECT_EQ(0u, spdy_stream2->stream_id());
2000 base::RunLoop().RunUntilIdle();
2002 EXPECT_EQ(1u, spdy_stream1->stream_id());
2003 EXPECT_EQ(3u, spdy_stream2->stream_id());
2005 // Ensure we don't crash while closing the session.
2006 session_->CloseSessionOnError(ERR_ABORTED, std::string());
2008 EXPECT_FALSE(spdy_stream1);
2009 EXPECT_FALSE(spdy_stream2);
2011 EXPECT_TRUE(delegate1.StreamIsClosed());
2012 EXPECT_TRUE(delegate2.StreamIsClosed());
2014 EXPECT_TRUE(session_);
2015 data.CompleteRead();
2016 base::RunLoop().RunUntilIdle();
2017 EXPECT_FALSE(session_);
2020 // Create two streams that are set to close each other on close,
2021 // activate them, and then close the session. Nothing should blow up.
2022 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2023 session_deps_.host_resolver->set_synchronous_mode(true);
2025 scoped_ptr<SpdyFrame> req1(
2026 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2027 scoped_ptr<SpdyFrame> req2(
2028 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
2029 MockWrite writes[] = {
2030 CreateMockWrite(*req1, 0),
2031 CreateMockWrite(*req2, 1),
2034 MockRead reads[] = {
2035 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
2038 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2039 session_deps_.socket_factory->AddSocketDataProvider(&data);
2041 CreateNetworkSession();
2042 CreateInsecureSpdySession();
2044 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2045 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2046 ASSERT_TRUE(spdy_stream1);
2047 EXPECT_EQ(0u, spdy_stream1->stream_id());
2049 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
2050 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2051 ASSERT_TRUE(spdy_stream2);
2052 EXPECT_EQ(0u, spdy_stream2->stream_id());
2054 // Make |spdy_stream1| close |spdy_stream2|.
2055 test::ClosingDelegate delegate1(spdy_stream2);
2056 spdy_stream1->SetDelegate(&delegate1);
2058 // Make |spdy_stream2| close |spdy_stream1|.
2059 test::ClosingDelegate delegate2(spdy_stream1);
2060 spdy_stream2->SetDelegate(&delegate2);
2062 scoped_ptr<SpdyHeaderBlock> headers(
2063 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2064 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2065 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2067 scoped_ptr<SpdyHeaderBlock> headers2(
2068 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2069 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2070 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2072 // Ensure that the streams have not yet been activated and assigned an id.
2073 EXPECT_EQ(0u, spdy_stream1->stream_id());
2074 EXPECT_EQ(0u, spdy_stream2->stream_id());
2076 base::RunLoop().RunUntilIdle();
2078 EXPECT_EQ(1u, spdy_stream1->stream_id());
2079 EXPECT_EQ(3u, spdy_stream2->stream_id());
2081 // Ensure we don't crash while closing the session.
2082 session_->CloseSessionOnError(ERR_ABORTED, std::string());
2084 EXPECT_FALSE(spdy_stream1);
2085 EXPECT_FALSE(spdy_stream2);
2087 EXPECT_TRUE(delegate1.StreamIsClosed());
2088 EXPECT_TRUE(delegate2.StreamIsClosed());
2090 EXPECT_TRUE(session_);
2091 data.CompleteRead();
2092 base::RunLoop().RunUntilIdle();
2093 EXPECT_FALSE(session_);
2096 // Delegate that closes a given session when the stream is closed.
2097 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2098 public:
2099 SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2100 const base::WeakPtr<SpdySession>& session_to_close)
2101 : StreamDelegateDoNothing(stream),
2102 session_to_close_(session_to_close) {}
2104 ~SessionClosingDelegate() override {}
2106 void OnClose(int status) override {
2107 session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2110 private:
2111 base::WeakPtr<SpdySession> session_to_close_;
2114 // Close an activated stream that closes its session. Nothing should
2115 // blow up. This is a regression test for https://crbug.com/263691.
2116 TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2117 session_deps_.host_resolver->set_synchronous_mode(true);
2119 scoped_ptr<SpdyFrame> req(
2120 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2121 scoped_ptr<SpdyFrame> rst(
2122 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2123 scoped_ptr<SpdyFrame> goaway(
2124 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2125 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2126 // despite being queued second.
2127 MockWrite writes[] = {
2128 CreateMockWrite(*req, 0),
2129 CreateMockWrite(*goaway, 1),
2130 CreateMockWrite(*rst, 3),
2133 MockRead reads[] = {
2134 MockRead(ASYNC, 0, 2) // EOF
2136 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2137 session_deps_.socket_factory->AddSocketDataProvider(&data);
2139 CreateNetworkSession();
2140 CreateInsecureSpdySession();
2142 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
2143 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2144 ASSERT_TRUE(spdy_stream.get() != nullptr);
2145 EXPECT_EQ(0u, spdy_stream->stream_id());
2147 SessionClosingDelegate delegate(spdy_stream, session_);
2148 spdy_stream->SetDelegate(&delegate);
2150 scoped_ptr<SpdyHeaderBlock> headers(
2151 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2152 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2153 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2155 EXPECT_EQ(0u, spdy_stream->stream_id());
2157 base::RunLoop().RunUntilIdle();
2159 EXPECT_EQ(1u, spdy_stream->stream_id());
2161 // Ensure we don't crash while closing the stream (which closes the
2162 // session).
2163 spdy_stream->Cancel();
2165 EXPECT_FALSE(spdy_stream);
2166 EXPECT_TRUE(delegate.StreamIsClosed());
2168 // Write the RST_STREAM & GOAWAY.
2169 base::RunLoop().RunUntilIdle();
2170 EXPECT_TRUE(data.AllWriteDataConsumed());
2171 EXPECT_TRUE(data.AllReadDataConsumed());
2174 TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2175 session_deps_.host_resolver->set_synchronous_mode(true);
2177 SequencedSocketData data(nullptr, 0, nullptr, 0);
2178 session_deps_.socket_factory->AddSocketDataProvider(&data);
2180 // Load a cert that is valid for:
2181 // www.example.org
2182 // mail.example.org
2183 // www.example.com
2184 base::FilePath certs_dir = GetTestCertsDirectory();
2185 scoped_refptr<X509Certificate> test_cert(
2186 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2187 ASSERT_NE(static_cast<X509Certificate*>(nullptr), test_cert.get());
2189 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2190 ssl.cert = test_cert;
2191 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2193 CreateNetworkSession();
2195 session_ = CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2197 EXPECT_TRUE(session_->VerifyDomainAuthentication("www.example.org"));
2198 EXPECT_TRUE(session_->VerifyDomainAuthentication("mail.example.org"));
2199 EXPECT_TRUE(session_->VerifyDomainAuthentication("mail.example.com"));
2200 EXPECT_FALSE(session_->VerifyDomainAuthentication("mail.google.com"));
2203 TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2204 session_deps_.host_resolver->set_synchronous_mode(true);
2206 SequencedSocketData data(nullptr, 0, nullptr, 0);
2207 session_deps_.socket_factory->AddSocketDataProvider(&data);
2209 // Load a cert that is valid for:
2210 // www.example.org
2211 // mail.example.org
2212 // www.example.com
2213 base::FilePath certs_dir = GetTestCertsDirectory();
2214 scoped_refptr<X509Certificate> test_cert(
2215 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2216 ASSERT_NE(static_cast<X509Certificate*>(nullptr), test_cert.get());
2218 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2219 ssl.channel_id_sent = true;
2220 ssl.cert = test_cert;
2221 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2223 CreateNetworkSession();
2225 session_ = CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2227 EXPECT_TRUE(session_->VerifyDomainAuthentication("www.example.org"));
2228 EXPECT_TRUE(session_->VerifyDomainAuthentication("mail.example.org"));
2229 EXPECT_FALSE(session_->VerifyDomainAuthentication("mail.example.com"));
2230 EXPECT_FALSE(session_->VerifyDomainAuthentication("mail.google.com"));
2233 TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2234 // TODO(rtenneti): Define a helper class/methods and move the common code in
2235 // this file.
2236 SettingsMap new_settings;
2237 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2238 const uint32 max_concurrent_streams = 1;
2239 new_settings[kSpdySettingsIds1] =
2240 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2242 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
2243 scoped_ptr<SpdyFrame> req1(
2244 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
2245 scoped_ptr<SpdyFrame> req2(
2246 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST, true));
2247 scoped_ptr<SpdyFrame> req3(
2248 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 5, LOWEST, true));
2249 MockWrite writes[] = {
2250 CreateMockWrite(*settings_ack, 1),
2251 CreateMockWrite(*req1, 2),
2252 CreateMockWrite(*req2, 5),
2253 CreateMockWrite(*req3, 8),
2256 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2257 // streams to 1.
2258 scoped_ptr<SpdyFrame> settings_frame(
2259 spdy_util_.ConstructSpdySettings(new_settings));
2261 scoped_ptr<SpdyFrame> resp1(
2262 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2263 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2265 scoped_ptr<SpdyFrame> resp2(
2266 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
2267 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2269 scoped_ptr<SpdyFrame> resp3(
2270 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 5));
2271 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2273 MockRead reads[] = {
2274 CreateMockRead(*settings_frame, 0),
2275 CreateMockRead(*resp1, 3),
2276 CreateMockRead(*body1, 4),
2277 CreateMockRead(*resp2, 6),
2278 CreateMockRead(*body2, 7),
2279 CreateMockRead(*resp3, 9),
2280 CreateMockRead(*body3, 10),
2281 MockRead(ASYNC, ERR_IO_PENDING, 11),
2282 MockRead(ASYNC, 0, 12) // EOF
2285 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2286 session_deps_.socket_factory->AddSocketDataProvider(&data);
2288 CreateNetworkSession();
2289 CreateInsecureSpdySession();
2291 // Read the settings frame.
2292 base::RunLoop().RunUntilIdle();
2294 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2295 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
2296 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2297 EXPECT_EQ(0u, spdy_stream1->stream_id());
2298 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2299 spdy_stream1->SetDelegate(&delegate1);
2301 TestCompletionCallback callback2;
2302 SpdyStreamRequest request2;
2303 ASSERT_EQ(
2304 ERR_IO_PENDING,
2305 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_,
2306 LOWEST, BoundNetLog(), callback2.callback()));
2308 TestCompletionCallback callback3;
2309 SpdyStreamRequest request3;
2310 ASSERT_EQ(
2311 ERR_IO_PENDING,
2312 request3.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_,
2313 LOWEST, BoundNetLog(), callback3.callback()));
2315 EXPECT_EQ(0u, session_->num_active_streams());
2316 EXPECT_EQ(1u, session_->num_created_streams());
2317 EXPECT_EQ(2u, session_->pending_create_stream_queue_size(LOWEST));
2319 scoped_ptr<SpdyHeaderBlock> headers(
2320 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2321 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2322 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2324 // Run until 1st stream is activated and then closed.
2325 EXPECT_EQ(0u, delegate1.stream_id());
2326 base::RunLoop().RunUntilIdle();
2327 EXPECT_FALSE(spdy_stream1);
2328 EXPECT_EQ(1u, delegate1.stream_id());
2330 EXPECT_EQ(0u, session_->num_active_streams());
2331 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(LOWEST));
2333 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2334 // create the 2nd stream.
2335 base::RunLoop().RunUntilIdle();
2337 EXPECT_EQ(0u, session_->num_active_streams());
2338 EXPECT_EQ(1u, session_->num_created_streams());
2339 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(LOWEST));
2341 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2342 test::StreamDelegateDoNothing delegate2(stream2);
2343 stream2->SetDelegate(&delegate2);
2344 scoped_ptr<SpdyHeaderBlock> headers2(
2345 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2346 stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2347 EXPECT_TRUE(stream2->HasUrlFromHeaders());
2349 // Run until 2nd stream is activated and then closed.
2350 EXPECT_EQ(0u, delegate2.stream_id());
2351 base::RunLoop().RunUntilIdle();
2352 EXPECT_FALSE(stream2);
2353 EXPECT_EQ(3u, delegate2.stream_id());
2355 EXPECT_EQ(0u, session_->num_active_streams());
2356 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2358 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2359 // create the 3rd stream.
2360 base::RunLoop().RunUntilIdle();
2362 EXPECT_EQ(0u, session_->num_active_streams());
2363 EXPECT_EQ(1u, session_->num_created_streams());
2364 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2366 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2367 test::StreamDelegateDoNothing delegate3(stream3);
2368 stream3->SetDelegate(&delegate3);
2369 scoped_ptr<SpdyHeaderBlock> headers3(
2370 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2371 stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2372 EXPECT_TRUE(stream3->HasUrlFromHeaders());
2374 // Run until 2nd stream is activated and then closed.
2375 EXPECT_EQ(0u, delegate3.stream_id());
2376 base::RunLoop().RunUntilIdle();
2377 EXPECT_FALSE(stream3);
2378 EXPECT_EQ(5u, delegate3.stream_id());
2380 EXPECT_EQ(0u, session_->num_active_streams());
2381 EXPECT_EQ(0u, session_->num_created_streams());
2382 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2384 data.CompleteRead();
2385 base::RunLoop().RunUntilIdle();
2388 TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2389 session_deps_.host_resolver->set_synchronous_mode(true);
2391 MockRead reads[] = {
2392 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2395 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
2396 session_deps_.socket_factory->AddSocketDataProvider(&data);
2398 CreateNetworkSession();
2399 CreateInsecureSpdySession();
2401 // Leave room for only one more stream to be created.
2402 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2403 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
2404 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2405 ASSERT_TRUE(spdy_stream != nullptr);
2408 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2409 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, LOWEST, BoundNetLog());
2410 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2411 EXPECT_EQ(0u, spdy_stream1->stream_id());
2413 TestCompletionCallback callback2;
2414 SpdyStreamRequest request2;
2415 ASSERT_EQ(ERR_IO_PENDING, request2.StartRequest(
2416 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
2417 LOWEST, BoundNetLog(), callback2.callback()));
2419 TestCompletionCallback callback3;
2420 SpdyStreamRequest request3;
2421 ASSERT_EQ(ERR_IO_PENDING, request3.StartRequest(
2422 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
2423 LOWEST, BoundNetLog(), callback3.callback()));
2425 EXPECT_EQ(0u, session_->num_active_streams());
2426 EXPECT_EQ(kInitialMaxConcurrentStreams, session_->num_created_streams());
2427 EXPECT_EQ(2u, session_->pending_create_stream_queue_size(LOWEST));
2429 // Cancel the first stream; this will allow the second stream to be created.
2430 EXPECT_TRUE(spdy_stream1);
2431 spdy_stream1->Cancel();
2432 EXPECT_FALSE(spdy_stream1);
2434 EXPECT_EQ(OK, callback2.WaitForResult());
2435 EXPECT_EQ(0u, session_->num_active_streams());
2436 EXPECT_EQ(kInitialMaxConcurrentStreams, session_->num_created_streams());
2437 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(LOWEST));
2439 // Cancel the second stream; this will allow the third stream to be created.
2440 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2441 spdy_stream2->Cancel();
2442 EXPECT_FALSE(spdy_stream2);
2444 EXPECT_EQ(OK, callback3.WaitForResult());
2445 EXPECT_EQ(0u, session_->num_active_streams());
2446 EXPECT_EQ(kInitialMaxConcurrentStreams, session_->num_created_streams());
2447 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2449 // Cancel the third stream.
2450 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2451 spdy_stream3->Cancel();
2452 EXPECT_FALSE(spdy_stream3);
2453 EXPECT_EQ(0u, session_->num_active_streams());
2454 EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session_->num_created_streams());
2455 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2458 // Test that SpdySession::DoReadLoop reads data from the socket
2459 // without yielding. This test makes 32k - 1 bytes of data available
2460 // on the socket for reading. It then verifies that it has read all
2461 // the available data without yielding.
2462 TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2463 session_deps_.host_resolver->set_synchronous_mode(true);
2464 session_deps_.time_func = InstantaneousReads;
2466 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2468 scoped_ptr<SpdyFrame> req1(
2469 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2470 MockWrite writes[] = {
2471 CreateMockWrite(*req1, 0),
2474 // Build buffer of size kYieldAfterBytesRead / 4
2475 // (-spdy_data_frame_size).
2476 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
2477 const int kPayloadSize =
2478 kYieldAfterBytesRead / 4 - framer.GetControlFrameHeaderSize();
2479 TestDataStream test_stream;
2480 scoped_refptr<IOBuffer> payload(new IOBuffer(kPayloadSize));
2481 char* payload_data = payload->data();
2482 test_stream.GetBytes(payload_data, kPayloadSize);
2484 scoped_ptr<SpdyFrame> partial_data_frame(
2485 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2486 scoped_ptr<SpdyFrame> finish_data_frame(
2487 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2489 scoped_ptr<SpdyFrame> resp1(
2490 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2492 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2493 // bytes.
2494 MockRead reads[] = {
2495 CreateMockRead(*resp1, 1),
2496 MockRead(ASYNC, ERR_IO_PENDING, 2),
2497 CreateMockRead(*partial_data_frame, 3),
2498 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2499 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2500 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2501 MockRead(ASYNC, 0, 7) // EOF
2504 // Create SpdySession and SpdyStream and send the request.
2505 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2506 session_deps_.socket_factory->AddSocketDataProvider(&data);
2508 CreateNetworkSession();
2509 CreateInsecureSpdySession();
2511 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2512 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2513 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2514 EXPECT_EQ(0u, spdy_stream1->stream_id());
2515 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2516 spdy_stream1->SetDelegate(&delegate1);
2518 scoped_ptr<SpdyHeaderBlock> headers1(
2519 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2520 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2521 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2523 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2524 // post a task.
2525 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2527 // Run until 1st read.
2528 EXPECT_EQ(0u, delegate1.stream_id());
2529 base::RunLoop().RunUntilIdle();
2530 EXPECT_EQ(1u, delegate1.stream_id());
2531 EXPECT_EQ(0u, observer.executed_count());
2533 // Read all the data and verify SpdySession::DoReadLoop has not
2534 // posted a task.
2535 data.CompleteRead();
2536 base::RunLoop().RunUntilIdle();
2537 EXPECT_FALSE(spdy_stream1);
2539 // Verify task observer's executed_count is zero, which indicates DoRead read
2540 // all the available data.
2541 EXPECT_EQ(0u, observer.executed_count());
2542 EXPECT_TRUE(data.AllWriteDataConsumed());
2543 EXPECT_TRUE(data.AllReadDataConsumed());
2546 // Test that SpdySession::DoReadLoop yields if more than
2547 // |kYieldAfterDurationMilliseconds| has passed. This test uses a mock time
2548 // function that makes the response frame look very slow to read.
2549 TEST_P(SpdySessionTest, TestYieldingSlowReads) {
2550 session_deps_.host_resolver->set_synchronous_mode(true);
2551 session_deps_.time_func = SlowReads;
2553 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2555 scoped_ptr<SpdyFrame> req1(
2556 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2557 MockWrite writes[] = {
2558 CreateMockWrite(*req1, 0),
2561 scoped_ptr<SpdyFrame> resp1(
2562 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2564 MockRead reads[] = {
2565 CreateMockRead(*resp1, 1), MockRead(ASYNC, 0, 2) // EOF
2568 // Create SpdySession and SpdyStream and send the request.
2569 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2570 session_deps_.socket_factory->AddSocketDataProvider(&data);
2572 CreateNetworkSession();
2573 CreateInsecureSpdySession();
2575 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2576 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2577 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2578 EXPECT_EQ(0u, spdy_stream1->stream_id());
2579 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2580 spdy_stream1->SetDelegate(&delegate1);
2582 scoped_ptr<SpdyHeaderBlock> headers1(
2583 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2584 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2585 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2587 // Set up the TaskObserver to verify that SpdySession::DoReadLoop posts a
2588 // task.
2589 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2591 EXPECT_EQ(0u, delegate1.stream_id());
2592 EXPECT_EQ(0u, observer.executed_count());
2594 // Read all the data and verify that SpdySession::DoReadLoop has posted a
2595 // task.
2596 base::RunLoop().RunUntilIdle();
2597 EXPECT_EQ(1u, delegate1.stream_id());
2598 EXPECT_FALSE(spdy_stream1);
2600 // Verify task that the observer's executed_count is 1, which indicates DoRead
2601 // has posted only one task and thus yielded though there is data available
2602 // for it to read.
2603 EXPECT_EQ(1u, observer.executed_count());
2604 EXPECT_TRUE(data.AllWriteDataConsumed());
2605 EXPECT_TRUE(data.AllReadDataConsumed());
2608 // Test that SpdySession::DoReadLoop yields while reading the
2609 // data. This test makes 32k + 1 bytes of data available on the socket
2610 // for reading. It then verifies that DoRead has yielded even though
2611 // there is data available for it to read (i.e, socket()->Read didn't
2612 // return ERR_IO_PENDING during socket reads).
2613 TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2614 session_deps_.host_resolver->set_synchronous_mode(true);
2615 session_deps_.time_func = InstantaneousReads;
2617 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2619 scoped_ptr<SpdyFrame> req1(
2620 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2621 MockWrite writes[] = {
2622 CreateMockWrite(*req1, 0),
2625 // Build buffer of size kYieldAfterBytesRead / 4
2626 // (-spdy_data_frame_size).
2627 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
2628 const int kPayloadSize =
2629 kYieldAfterBytesRead / 4 - framer.GetControlFrameHeaderSize();
2630 TestDataStream test_stream;
2631 scoped_refptr<IOBuffer> payload(new IOBuffer(kPayloadSize));
2632 char* payload_data = payload->data();
2633 test_stream.GetBytes(payload_data, kPayloadSize);
2635 scoped_ptr<SpdyFrame> partial_data_frame(
2636 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2637 scoped_ptr<SpdyFrame> finish_data_frame(
2638 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2640 scoped_ptr<SpdyFrame> resp1(
2641 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2643 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2644 MockRead reads[] = {
2645 CreateMockRead(*resp1, 1),
2646 MockRead(ASYNC, ERR_IO_PENDING, 2),
2647 CreateMockRead(*partial_data_frame, 3),
2648 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2649 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2650 CreateMockRead(*partial_data_frame, 6, SYNCHRONOUS),
2651 CreateMockRead(*finish_data_frame, 7, SYNCHRONOUS),
2652 MockRead(ASYNC, 0, 8) // EOF
2655 // Create SpdySession and SpdyStream and send the request.
2656 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2657 session_deps_.socket_factory->AddSocketDataProvider(&data);
2659 CreateNetworkSession();
2660 CreateInsecureSpdySession();
2662 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2663 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2664 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2665 EXPECT_EQ(0u, spdy_stream1->stream_id());
2666 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2667 spdy_stream1->SetDelegate(&delegate1);
2669 scoped_ptr<SpdyHeaderBlock> headers1(
2670 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2671 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2672 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2674 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a task.
2675 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2677 // Run until 1st read.
2678 EXPECT_EQ(0u, delegate1.stream_id());
2679 base::RunLoop().RunUntilIdle();
2680 EXPECT_EQ(1u, delegate1.stream_id());
2681 EXPECT_EQ(0u, observer.executed_count());
2683 // Read all the data and verify SpdySession::DoReadLoop has posted a task.
2684 data.CompleteRead();
2685 base::RunLoop().RunUntilIdle();
2686 EXPECT_FALSE(spdy_stream1);
2688 // Verify task observer's executed_count is 1, which indicates DoRead has
2689 // posted only one task and thus yielded though there is data available for it
2690 // to read.
2691 EXPECT_EQ(1u, observer.executed_count());
2692 EXPECT_TRUE(data.AllWriteDataConsumed());
2693 EXPECT_TRUE(data.AllReadDataConsumed());
2696 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2697 // + async, by doing the following MockReads.
2699 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2700 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2702 // The above reads 26K synchronously. Since that is less that 32K, we
2703 // will attempt to read again. However, that DoRead() will return
2704 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2705 // yield. When we come back, DoRead() will read the results from the
2706 // async read, and rest of the data synchronously.
2707 TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2708 session_deps_.host_resolver->set_synchronous_mode(true);
2709 session_deps_.time_func = InstantaneousReads;
2711 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2713 scoped_ptr<SpdyFrame> req1(
2714 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2715 MockWrite writes[] = {
2716 CreateMockWrite(*req1, 0),
2719 // Build buffer of size kYieldAfterBytesRead / 4
2720 // (-spdy_data_frame_size).
2721 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
2722 TestDataStream test_stream;
2723 const int kEightKPayloadSize =
2724 kYieldAfterBytesRead / 4 - framer.GetControlFrameHeaderSize();
2725 scoped_refptr<IOBuffer> eightk_payload(new IOBuffer(kEightKPayloadSize));
2726 char* eightk_payload_data = eightk_payload->data();
2727 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2729 // Build buffer of 2k size.
2730 TestDataStream test_stream2;
2731 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2732 scoped_refptr<IOBuffer> twok_payload(new IOBuffer(kTwoKPayloadSize));
2733 char* twok_payload_data = twok_payload->data();
2734 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2736 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2737 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2738 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2739 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2740 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2741 1, "h", 1, DATA_FLAG_FIN));
2743 scoped_ptr<SpdyFrame> resp1(
2744 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2746 MockRead reads[] = {
2747 CreateMockRead(*resp1, 1),
2748 MockRead(ASYNC, ERR_IO_PENDING, 2),
2749 CreateMockRead(*eightk_data_frame, 3),
2750 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2751 CreateMockRead(*eightk_data_frame, 5, SYNCHRONOUS),
2752 CreateMockRead(*twok_data_frame, 6, SYNCHRONOUS),
2753 CreateMockRead(*eightk_data_frame, 7, ASYNC),
2754 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2755 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2756 CreateMockRead(*eightk_data_frame, 10, SYNCHRONOUS),
2757 CreateMockRead(*twok_data_frame, 11, SYNCHRONOUS),
2758 CreateMockRead(*finish_data_frame, 12, SYNCHRONOUS),
2759 MockRead(ASYNC, 0, 13) // EOF
2762 // Create SpdySession and SpdyStream and send the request.
2763 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2764 session_deps_.socket_factory->AddSocketDataProvider(&data);
2766 CreateNetworkSession();
2767 CreateInsecureSpdySession();
2769 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2770 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2771 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2772 EXPECT_EQ(0u, spdy_stream1->stream_id());
2773 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2774 spdy_stream1->SetDelegate(&delegate1);
2776 scoped_ptr<SpdyHeaderBlock> headers1(
2777 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2778 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2779 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2781 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2782 // posting of tasks.
2783 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2785 // Run until 1st read.
2786 EXPECT_EQ(0u, delegate1.stream_id());
2787 base::RunLoop().RunUntilIdle();
2788 EXPECT_EQ(1u, delegate1.stream_id());
2789 EXPECT_EQ(0u, observer.executed_count());
2791 // Read all the data and verify SpdySession::DoReadLoop has posted a
2792 // task.
2793 data.CompleteRead();
2794 base::RunLoop().RunUntilIdle();
2795 EXPECT_FALSE(spdy_stream1);
2797 // Verify task observer's executed_count is 1, which indicates DoRead has
2798 // posted only one task and thus yielded though there is data available for
2799 // it to read.
2800 EXPECT_EQ(1u, observer.executed_count());
2801 EXPECT_TRUE(data.AllWriteDataConsumed());
2802 EXPECT_TRUE(data.AllReadDataConsumed());
2805 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2806 // nothing blows up.
2807 TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
2808 session_deps_.host_resolver->set_synchronous_mode(true);
2810 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2812 scoped_ptr<SpdyFrame> req1(
2813 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2814 MockWrite writes[] = {
2815 CreateMockWrite(*req1, 0),
2818 scoped_ptr<SpdyFrame> resp1(
2819 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2820 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2821 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
2823 MockRead reads[] = {
2824 CreateMockRead(*resp1, 1),
2825 MockRead(ASYNC, ERR_IO_PENDING, 2),
2826 CreateMockRead(*body1, 3),
2827 CreateMockRead(*goaway, 4),
2830 // Create SpdySession and SpdyStream and send the request.
2831 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2832 session_deps_.socket_factory->AddSocketDataProvider(&data);
2834 CreateNetworkSession();
2835 CreateInsecureSpdySession();
2837 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2838 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2839 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2840 spdy_stream1->SetDelegate(&delegate1);
2841 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2842 EXPECT_EQ(0u, spdy_stream1->stream_id());
2844 scoped_ptr<SpdyHeaderBlock> headers1(
2845 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2846 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2847 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2849 // Run until 1st read.
2850 EXPECT_EQ(0u, spdy_stream1->stream_id());
2851 base::RunLoop().RunUntilIdle();
2852 EXPECT_EQ(1u, spdy_stream1->stream_id());
2854 // Run until GoAway.
2855 data.CompleteRead();
2856 base::RunLoop().RunUntilIdle();
2857 EXPECT_FALSE(spdy_stream1);
2858 EXPECT_TRUE(data.AllWriteDataConsumed());
2859 EXPECT_TRUE(data.AllReadDataConsumed());
2860 EXPECT_FALSE(session_);
2863 // Within this framework, a SpdySession should be initialized with
2864 // flow control disabled for protocol version 2, with flow control
2865 // enabled only for streams for protocol version 3, and with flow
2866 // control enabled for streams and sessions for higher versions.
2867 TEST_P(SpdySessionTest, ProtocolNegotiation) {
2868 session_deps_.host_resolver->set_synchronous_mode(true);
2870 MockRead reads[] = {
2871 MockRead(SYNCHRONOUS, 0, 0) // EOF
2873 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
2874 session_deps_.socket_factory->AddSocketDataProvider(&data);
2876 CreateNetworkSession();
2877 session_ = CreateFakeSpdySession(spdy_session_pool_, key_);
2879 EXPECT_EQ(spdy_util_.spdy_version(),
2880 session_->buffered_spdy_framer_->protocol_version());
2881 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
2882 session_->flow_control_state());
2883 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
2884 session_->session_send_window_size_);
2885 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
2886 session_->session_recv_window_size_);
2887 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
2890 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2891 // pointers to the idle session are currently held.
2892 TEST_P(SpdySessionTest, CloseOneIdleConnection) {
2893 ClientSocketPoolManager::set_max_sockets_per_group(
2894 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2895 ClientSocketPoolManager::set_max_sockets_per_pool(
2896 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2898 MockRead reads[] = {
2899 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2901 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
2902 session_deps_.socket_factory->AddSocketDataProvider(&data);
2903 session_deps_.socket_factory->AddSocketDataProvider(&data);
2905 CreateNetworkSession();
2907 TransportClientSocketPool* pool =
2908 http_session_->GetTransportSocketPool(
2909 HttpNetworkSession::NORMAL_SOCKET_POOL);
2911 // Create an idle SPDY session.
2912 CreateInsecureSpdySession();
2913 EXPECT_FALSE(pool->IsStalled());
2915 // Trying to create a new connection should cause the pool to be stalled, and
2916 // post a task asynchronously to try and close the session.
2917 TestCompletionCallback callback2;
2918 HostPortPair host_port2("2.com", 80);
2919 scoped_refptr<TransportSocketParams> params2(
2920 new TransportSocketParams(
2921 host_port2, false, false, OnHostResolutionCallback(),
2922 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
2923 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
2924 EXPECT_EQ(ERR_IO_PENDING,
2925 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
2926 callback2.callback(), pool, BoundNetLog()));
2927 EXPECT_TRUE(pool->IsStalled());
2929 // The socket pool should close the connection asynchronously and establish a
2930 // new connection.
2931 EXPECT_EQ(OK, callback2.WaitForResult());
2932 EXPECT_FALSE(pool->IsStalled());
2933 EXPECT_FALSE(session_);
2936 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2937 // pointers to the idle session are currently held, in the case the SPDY session
2938 // has an alias.
2939 TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
2940 ClientSocketPoolManager::set_max_sockets_per_group(
2941 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2942 ClientSocketPoolManager::set_max_sockets_per_pool(
2943 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2945 MockRead reads[] = {
2946 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2948 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
2949 session_deps_.socket_factory->AddSocketDataProvider(&data);
2950 session_deps_.socket_factory->AddSocketDataProvider(&data);
2952 session_deps_.host_resolver->set_synchronous_mode(true);
2953 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2954 "1.com", "192.168.0.2", std::string());
2955 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2956 "2.com", "192.168.0.2", std::string());
2957 // Not strictly needed.
2958 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2959 "3.com", "192.168.0.3", std::string());
2961 CreateNetworkSession();
2963 TransportClientSocketPool* pool =
2964 http_session_->GetTransportSocketPool(
2965 HttpNetworkSession::NORMAL_SOCKET_POOL);
2967 // Create an idle SPDY session.
2968 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2969 PRIVACY_MODE_DISABLED);
2970 base::WeakPtr<SpdySession> session1 =
2971 ::net::CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2972 EXPECT_FALSE(pool->IsStalled());
2974 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
2975 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
2976 PRIVACY_MODE_DISABLED);
2977 HostResolver::RequestInfo info(key2.host_port_pair());
2978 AddressList addresses;
2979 // Pre-populate the DNS cache, since a synchronous resolution is required in
2980 // order to create the alias.
2981 session_deps_.host_resolver->Resolve(info, DEFAULT_PRIORITY, &addresses,
2982 CompletionCallback(), nullptr,
2983 BoundNetLog());
2984 // Get a session for |key2|, which should return the session created earlier.
2985 base::WeakPtr<SpdySession> session2 =
2986 spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
2987 ASSERT_EQ(session1.get(), session2.get());
2988 EXPECT_FALSE(pool->IsStalled());
2990 // Trying to create a new connection should cause the pool to be stalled, and
2991 // post a task asynchronously to try and close the session.
2992 TestCompletionCallback callback3;
2993 HostPortPair host_port3("3.com", 80);
2994 scoped_refptr<TransportSocketParams> params3(
2995 new TransportSocketParams(
2996 host_port3, false, false, OnHostResolutionCallback(),
2997 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
2998 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
2999 EXPECT_EQ(ERR_IO_PENDING,
3000 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3001 callback3.callback(), pool, BoundNetLog()));
3002 EXPECT_TRUE(pool->IsStalled());
3004 // The socket pool should close the connection asynchronously and establish a
3005 // new connection.
3006 EXPECT_EQ(OK, callback3.WaitForResult());
3007 EXPECT_FALSE(pool->IsStalled());
3008 EXPECT_FALSE(session1);
3009 EXPECT_FALSE(session2);
3012 // Tests that when a SPDY session becomes idle, it closes itself if there is
3013 // a lower layer pool stalled on the per-pool socket limit.
3014 TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3015 ClientSocketPoolManager::set_max_sockets_per_group(
3016 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3017 ClientSocketPoolManager::set_max_sockets_per_pool(
3018 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3020 MockRead reads[] = {
3021 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3023 scoped_ptr<SpdyFrame> req1(
3024 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
3025 scoped_ptr<SpdyFrame> cancel1(
3026 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3027 MockWrite writes[] = {
3028 CreateMockWrite(*req1, 1),
3029 CreateMockWrite(*cancel1, 1),
3031 StaticSocketDataProvider data(reads, arraysize(reads),
3032 writes, arraysize(writes));
3033 session_deps_.socket_factory->AddSocketDataProvider(&data);
3035 MockRead http_reads[] = {
3036 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3038 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
3040 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3043 CreateNetworkSession();
3045 TransportClientSocketPool* pool =
3046 http_session_->GetTransportSocketPool(
3047 HttpNetworkSession::NORMAL_SOCKET_POOL);
3049 // Create a SPDY session.
3050 CreateInsecureSpdySession();
3051 EXPECT_FALSE(pool->IsStalled());
3053 // Create a stream using the session, and send a request.
3055 TestCompletionCallback callback1;
3056 base::WeakPtr<SpdyStream> spdy_stream1 =
3057 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
3058 test_url_, DEFAULT_PRIORITY, BoundNetLog());
3059 ASSERT_TRUE(spdy_stream1.get());
3060 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3061 spdy_stream1->SetDelegate(&delegate1);
3063 scoped_ptr<SpdyHeaderBlock> headers1(
3064 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3065 EXPECT_EQ(ERR_IO_PENDING,
3066 spdy_stream1->SendRequestHeaders(
3067 headers1.Pass(), NO_MORE_DATA_TO_SEND));
3068 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3070 base::RunLoop().RunUntilIdle();
3072 // Trying to create a new connection should cause the pool to be stalled, and
3073 // post a task asynchronously to try and close the session.
3074 TestCompletionCallback callback2;
3075 HostPortPair host_port2("2.com", 80);
3076 scoped_refptr<TransportSocketParams> params2(
3077 new TransportSocketParams(
3078 host_port2, false, false, OnHostResolutionCallback(),
3079 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3080 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3081 EXPECT_EQ(ERR_IO_PENDING,
3082 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3083 callback2.callback(), pool, BoundNetLog()));
3084 EXPECT_TRUE(pool->IsStalled());
3086 // Running the message loop should cause the socket pool to ask the SPDY
3087 // session to close an idle socket, but since the socket is in use, nothing
3088 // happens.
3089 base::RunLoop().RunUntilIdle();
3090 EXPECT_TRUE(pool->IsStalled());
3091 EXPECT_FALSE(callback2.have_result());
3093 // Cancelling the request should result in the session's socket being
3094 // closed, since the pool is stalled.
3095 ASSERT_TRUE(spdy_stream1.get());
3096 spdy_stream1->Cancel();
3097 base::RunLoop().RunUntilIdle();
3098 ASSERT_FALSE(pool->IsStalled());
3099 EXPECT_EQ(OK, callback2.WaitForResult());
3102 // Verify that SpdySessionKey and therefore SpdySession is different when
3103 // privacy mode is enabled or disabled.
3104 TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3105 CreateNetworkSession();
3107 HostPortPair host_port_pair("www.example.org", 443);
3108 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3109 PRIVACY_MODE_ENABLED);
3110 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3111 PRIVACY_MODE_DISABLED);
3113 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3114 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3116 // Add SpdySession with PrivacyMode Enabled to the pool.
3117 base::WeakPtr<SpdySession> session_privacy_enabled =
3118 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3120 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3121 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3123 // Add SpdySession with PrivacyMode Disabled to the pool.
3124 base::WeakPtr<SpdySession> session_privacy_disabled =
3125 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3127 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3128 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3130 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3131 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3132 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3134 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3135 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3136 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3139 // Delegate that creates another stream when its stream is closed.
3140 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3141 public:
3142 StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3143 const base::WeakPtr<SpdySession>& session)
3144 : StreamDelegateDoNothing(stream),
3145 session_(session) {}
3147 ~StreamCreatingDelegate() override {}
3149 void OnClose(int status) override {
3150 GURL url(kDefaultURL);
3151 ignore_result(
3152 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3153 session_, url, MEDIUM, BoundNetLog()));
3156 private:
3157 const base::WeakPtr<SpdySession> session_;
3160 // Create another stream in response to a stream being reset. Nothing
3161 // should blow up. This is a regression test for
3162 // http://crbug.com/263690 .
3163 TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3164 session_deps_.host_resolver->set_synchronous_mode(true);
3166 scoped_ptr<SpdyFrame> req(
3167 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
3168 MockWrite writes[] = {
3169 CreateMockWrite(*req, 0),
3172 scoped_ptr<SpdyFrame> rst(
3173 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3174 MockRead reads[] = {
3175 MockRead(ASYNC, ERR_IO_PENDING, 1),
3176 CreateMockRead(*rst, 2),
3177 MockRead(ASYNC, ERR_IO_PENDING, 3),
3178 MockRead(ASYNC, 0, 4) // EOF
3180 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3181 session_deps_.socket_factory->AddSocketDataProvider(&data);
3183 CreateNetworkSession();
3184 CreateInsecureSpdySession();
3186 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
3187 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
3188 ASSERT_TRUE(spdy_stream.get() != nullptr);
3189 EXPECT_EQ(0u, spdy_stream->stream_id());
3191 StreamCreatingDelegate delegate(spdy_stream, session_);
3192 spdy_stream->SetDelegate(&delegate);
3194 scoped_ptr<SpdyHeaderBlock> headers(
3195 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3196 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3197 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3199 EXPECT_EQ(0u, spdy_stream->stream_id());
3201 base::RunLoop().RunUntilIdle();
3203 EXPECT_EQ(1u, spdy_stream->stream_id());
3205 // Cause the stream to be reset, which should cause another stream
3206 // to be created.
3207 data.CompleteRead();
3208 base::RunLoop().RunUntilIdle();
3210 EXPECT_FALSE(spdy_stream);
3211 EXPECT_TRUE(delegate.StreamIsClosed());
3212 EXPECT_EQ(0u, session_->num_active_streams());
3213 EXPECT_EQ(1u, session_->num_created_streams());
3215 data.CompleteRead();
3216 base::RunLoop().RunUntilIdle();
3217 EXPECT_FALSE(session_);
3220 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3221 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3222 // gets sent.
3223 SettingsMap new_settings;
3224 int32 window_size = 1;
3225 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3226 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3228 // Set up the socket so we read a SETTINGS frame that sets
3229 // INITIAL_WINDOW_SIZE.
3230 scoped_ptr<SpdyFrame> settings_frame(
3231 spdy_util_.ConstructSpdySettings(new_settings));
3232 MockRead reads[] = {
3233 CreateMockRead(*settings_frame, 0),
3234 MockRead(ASYNC, ERR_IO_PENDING, 1),
3235 MockRead(ASYNC, 0, 2) // EOF
3238 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3239 MockWrite writes[] = {
3240 CreateMockWrite(*settings_ack, 3),
3243 session_deps_.host_resolver->set_synchronous_mode(true);
3245 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3246 session_deps_.socket_factory->AddSocketDataProvider(&data);
3248 CreateNetworkSession();
3249 CreateInsecureSpdySession();
3250 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
3251 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
3252 ASSERT_TRUE(spdy_stream1.get() != nullptr);
3253 TestCompletionCallback callback1;
3254 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3256 // Process the SETTINGS frame.
3257 base::RunLoop().RunUntilIdle();
3258 EXPECT_EQ(session_->stream_initial_send_window_size(), window_size);
3259 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3261 // Release the first one, this will allow the second to be created.
3262 spdy_stream1->Cancel();
3263 EXPECT_FALSE(spdy_stream1);
3265 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
3266 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
3267 ASSERT_TRUE(spdy_stream2.get() != nullptr);
3268 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3269 spdy_stream2->Cancel();
3270 EXPECT_FALSE(spdy_stream2);
3272 EXPECT_TRUE(session_);
3273 data.CompleteRead();
3274 base::RunLoop().RunUntilIdle();
3275 EXPECT_FALSE(session_);
3278 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3279 // adjust the session receive window size. In addition,
3280 // SpdySession::IncreaseRecvWindowSize should trigger
3281 // sending a WINDOW_UPDATE frame for a large enough delta.
3282 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3283 session_deps_.host_resolver->set_synchronous_mode(true);
3285 const int32 initial_window_size =
3286 SpdySession::GetDefaultInitialWindowSize(GetParam());
3287 const int32 delta_window_size = 100;
3289 MockRead reads[] = {
3290 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
3292 scoped_ptr<SpdyFrame> window_update(spdy_util_.ConstructSpdyWindowUpdate(
3293 kSessionFlowControlStreamId, initial_window_size + delta_window_size));
3294 MockWrite writes[] = {
3295 CreateMockWrite(*window_update, 0),
3297 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3298 session_deps_.socket_factory->AddSocketDataProvider(&data);
3300 CreateNetworkSession();
3301 CreateInsecureSpdySession();
3302 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3303 session_->flow_control_state());
3305 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3306 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3308 session_->IncreaseRecvWindowSize(delta_window_size);
3309 EXPECT_EQ(initial_window_size + delta_window_size,
3310 session_->session_recv_window_size_);
3311 EXPECT_EQ(delta_window_size, session_->session_unacked_recv_window_bytes_);
3313 // Should trigger sending a WINDOW_UPDATE frame.
3314 session_->IncreaseRecvWindowSize(initial_window_size);
3315 EXPECT_EQ(initial_window_size + delta_window_size + initial_window_size,
3316 session_->session_recv_window_size_);
3317 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3319 base::RunLoop().RunUntilIdle();
3321 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3322 session_->in_io_loop_ = true;
3323 session_->DecreaseRecvWindowSize(initial_window_size + delta_window_size +
3324 initial_window_size);
3325 session_->in_io_loop_ = false;
3326 EXPECT_EQ(0, session_->session_recv_window_size_);
3327 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3329 EXPECT_TRUE(session_);
3330 data.CompleteRead();
3331 base::RunLoop().RunUntilIdle();
3332 EXPECT_FALSE(session_);
3335 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3336 // adjust the session send window size when the "enable_spdy_31" flag
3337 // is set.
3338 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3339 session_deps_.host_resolver->set_synchronous_mode(true);
3341 MockRead reads[] = {
3342 MockRead(SYNCHRONOUS, 0, 0) // EOF
3344 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
3345 session_deps_.socket_factory->AddSocketDataProvider(&data);
3347 CreateNetworkSession();
3348 session_ = CreateFakeSpdySession(spdy_session_pool_, key_);
3349 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3350 session_->flow_control_state());
3352 const int32 initial_window_size =
3353 SpdySession::GetDefaultInitialWindowSize(GetParam());
3354 const int32 delta_window_size = 100;
3356 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3358 session_->IncreaseSendWindowSize(delta_window_size);
3359 EXPECT_EQ(initial_window_size + delta_window_size,
3360 session_->session_send_window_size_);
3362 session_->DecreaseSendWindowSize(delta_window_size);
3363 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3366 // Incoming data for an inactive stream should not cause the session
3367 // receive window size to decrease, but it should cause the unacked
3368 // bytes to increase.
3369 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3370 session_deps_.host_resolver->set_synchronous_mode(true);
3372 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3373 MockRead reads[] = {
3374 CreateMockRead(*resp, 0),
3375 MockRead(ASYNC, ERR_IO_PENDING, 1),
3376 MockRead(ASYNC, 0, 2) // EOF
3378 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
3379 session_deps_.socket_factory->AddSocketDataProvider(&data);
3381 CreateNetworkSession();
3382 CreateInsecureSpdySession();
3383 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3384 session_->flow_control_state());
3386 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3387 session_->session_recv_window_size_);
3388 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3390 base::RunLoop().RunUntilIdle();
3392 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3393 session_->session_recv_window_size_);
3394 EXPECT_EQ(kUploadDataSize, session_->session_unacked_recv_window_bytes_);
3396 EXPECT_TRUE(session_);
3397 data.CompleteRead();
3398 base::RunLoop().RunUntilIdle();
3399 EXPECT_FALSE(session_);
3402 // The frame header is not included in flow control, but frame payload
3403 // (including optional pad length and padding) is.
3404 TEST_P(SpdySessionTest, SessionFlowControlPadding) {
3405 // Padding only exists in HTTP/2.
3406 if (GetParam() < kProtoHTTP2)
3407 return;
3409 session_deps_.host_resolver->set_synchronous_mode(true);
3411 const int padding_length = 42;
3412 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(
3413 1, kUploadData, kUploadDataSize, false, padding_length));
3414 MockRead reads[] = {
3415 CreateMockRead(*resp, 0),
3416 MockRead(ASYNC, ERR_IO_PENDING, 1),
3417 MockRead(ASYNC, 0, 2) // EOF
3419 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
3420 session_deps_.socket_factory->AddSocketDataProvider(&data);
3422 CreateNetworkSession();
3423 CreateInsecureSpdySession();
3424 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3425 session_->flow_control_state());
3427 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3428 session_->session_recv_window_size_);
3429 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3431 base::RunLoop().RunUntilIdle();
3433 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3434 session_->session_recv_window_size_);
3435 EXPECT_EQ(kUploadDataSize + padding_length,
3436 session_->session_unacked_recv_window_bytes_);
3438 data.CompleteRead();
3439 base::RunLoop().RunUntilIdle();
3440 EXPECT_FALSE(session_);
3443 // Peer sends more data than stream level receiving flow control window.
3444 TEST_P(SpdySessionTest, StreamFlowControlTooMuchData) {
3445 const int32 stream_max_recv_window_size = 1024;
3446 const int32 data_frame_size = 2 * stream_max_recv_window_size;
3448 scoped_ptr<SpdyFrame> req(
3449 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
3450 scoped_ptr<SpdyFrame> rst(
3451 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
3452 MockWrite writes[] = {
3453 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
3456 scoped_ptr<SpdyFrame> resp(
3457 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3458 const std::string payload(data_frame_size, 'a');
3459 scoped_ptr<SpdyFrame> data_frame(spdy_util_.ConstructSpdyBodyFrame(
3460 1, payload.data(), data_frame_size, false));
3461 MockRead reads[] = {
3462 CreateMockRead(*resp, 1),
3463 MockRead(ASYNC, ERR_IO_PENDING, 2),
3464 CreateMockRead(*data_frame, 3),
3465 MockRead(ASYNC, ERR_IO_PENDING, 5),
3466 MockRead(ASYNC, 0, 6),
3469 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3470 session_deps_.socket_factory->AddSocketDataProvider(&data);
3471 CreateNetworkSession();
3473 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
3474 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
3475 CreateInsecureSpdySession();
3476 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM, session_->flow_control_state());
3478 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
3479 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
3480 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3482 test::StreamDelegateDoNothing delegate(spdy_stream);
3483 spdy_stream->SetDelegate(&delegate);
3485 scoped_ptr<SpdyHeaderBlock> headers(
3486 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3487 EXPECT_EQ(ERR_IO_PENDING, spdy_stream->SendRequestHeaders(
3488 headers.Pass(), NO_MORE_DATA_TO_SEND));
3490 // Request and response.
3491 base::RunLoop().RunUntilIdle();
3492 EXPECT_EQ(1u, spdy_stream->stream_id());
3494 // Too large data frame causes flow control error, should close stream.
3495 data.CompleteRead();
3496 base::RunLoop().RunUntilIdle();
3497 EXPECT_FALSE(spdy_stream);
3499 EXPECT_TRUE(session_);
3500 data.CompleteRead();
3501 base::RunLoop().RunUntilIdle();
3502 EXPECT_FALSE(session_);
3505 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3506 // deltas in the receiving window size when checking incoming frames for flow
3507 // control errors at session level.
3508 TEST_P(SpdySessionTest, SessionFlowControlTooMuchDataTwoDataFrames) {
3509 const int32 session_max_recv_window_size = 500;
3510 const int32 first_data_frame_size = 200;
3511 const int32 second_data_frame_size = 400;
3513 // First data frame should not trigger a WINDOW_UPDATE.
3514 ASSERT_GT(session_max_recv_window_size / 2, first_data_frame_size);
3515 // Second data frame would be fine had there been a WINDOW_UPDATE.
3516 ASSERT_GT(session_max_recv_window_size, second_data_frame_size);
3517 // But in fact, the two data frames together overflow the receiving window at
3518 // session level.
3519 ASSERT_LT(session_max_recv_window_size,
3520 first_data_frame_size + second_data_frame_size);
3522 session_deps_.host_resolver->set_synchronous_mode(true);
3524 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3525 0, GOAWAY_FLOW_CONTROL_ERROR,
3526 "delta_window_size is 400 in DecreaseRecvWindowSize, which is larger "
3527 "than the receive window size of 500"));
3528 MockWrite writes[] = {
3529 CreateMockWrite(*goaway, 4),
3532 const std::string first_data_frame(first_data_frame_size, 'a');
3533 scoped_ptr<SpdyFrame> first(spdy_util_.ConstructSpdyBodyFrame(
3534 1, first_data_frame.data(), first_data_frame_size, false));
3535 const std::string second_data_frame(second_data_frame_size, 'b');
3536 scoped_ptr<SpdyFrame> second(spdy_util_.ConstructSpdyBodyFrame(
3537 1, second_data_frame.data(), second_data_frame_size, false));
3538 MockRead reads[] = {
3539 CreateMockRead(*first, 0),
3540 MockRead(ASYNC, ERR_IO_PENDING, 1),
3541 CreateMockRead(*second, 2),
3542 MockRead(ASYNC, 0, 3),
3544 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3545 session_deps_.socket_factory->AddSocketDataProvider(&data);
3547 CreateNetworkSession();
3548 CreateInsecureSpdySession();
3549 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3550 session_->flow_control_state());
3551 // Setting session level receiving window size to smaller than initial is not
3552 // possible via SpdySessionPoolPeer.
3553 session_->session_recv_window_size_ = session_max_recv_window_size;
3555 // First data frame is immediately consumed and does not trigger
3556 // WINDOW_UPDATE.
3557 base::RunLoop().RunUntilIdle();
3558 EXPECT_EQ(first_data_frame_size,
3559 session_->session_unacked_recv_window_bytes_);
3560 EXPECT_EQ(session_max_recv_window_size, session_->session_recv_window_size_);
3561 EXPECT_EQ(SpdySession::STATE_AVAILABLE, session_->availability_state_);
3563 // Second data frame overflows receiving window, causes session to close.
3564 data.CompleteRead();
3565 base::RunLoop().RunUntilIdle();
3566 EXPECT_EQ(SpdySession::STATE_DRAINING, session_->availability_state_);
3569 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3570 // deltas in the receiving window size when checking incoming data frames for
3571 // flow control errors at stream level.
3572 TEST_P(SpdySessionTest, StreamFlowControlTooMuchDataTwoDataFrames) {
3573 const int32 stream_max_recv_window_size = 500;
3574 const int32 first_data_frame_size = 200;
3575 const int32 second_data_frame_size = 400;
3577 // First data frame should not trigger a WINDOW_UPDATE.
3578 ASSERT_GT(stream_max_recv_window_size / 2, first_data_frame_size);
3579 // Second data frame would be fine had there been a WINDOW_UPDATE.
3580 ASSERT_GT(stream_max_recv_window_size, second_data_frame_size);
3581 // But in fact, they should overflow the receiving window at stream level.
3582 ASSERT_LT(stream_max_recv_window_size,
3583 first_data_frame_size + second_data_frame_size);
3585 scoped_ptr<SpdyFrame> req(
3586 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
3587 scoped_ptr<SpdyFrame> rst(
3588 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
3589 MockWrite writes[] = {
3590 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 6),
3593 scoped_ptr<SpdyFrame> resp(
3594 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3595 const std::string first_data_frame(first_data_frame_size, 'a');
3596 scoped_ptr<SpdyFrame> first(spdy_util_.ConstructSpdyBodyFrame(
3597 1, first_data_frame.data(), first_data_frame_size, false));
3598 const std::string second_data_frame(second_data_frame_size, 'b');
3599 scoped_ptr<SpdyFrame> second(spdy_util_.ConstructSpdyBodyFrame(
3600 1, second_data_frame.data(), second_data_frame_size, false));
3601 MockRead reads[] = {
3602 CreateMockRead(*resp, 1),
3603 MockRead(ASYNC, ERR_IO_PENDING, 2),
3604 CreateMockRead(*first, 3),
3605 MockRead(ASYNC, ERR_IO_PENDING, 4),
3606 CreateMockRead(*second, 5),
3607 MockRead(ASYNC, ERR_IO_PENDING, 7),
3608 MockRead(ASYNC, 0, 8),
3611 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3612 session_deps_.socket_factory->AddSocketDataProvider(&data);
3614 CreateNetworkSession();
3615 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
3616 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
3618 CreateInsecureSpdySession();
3619 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM, session_->flow_control_state());
3621 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
3622 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
3623 test::StreamDelegateDoNothing delegate(spdy_stream);
3624 spdy_stream->SetDelegate(&delegate);
3626 scoped_ptr<SpdyHeaderBlock> headers(
3627 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3628 EXPECT_EQ(ERR_IO_PENDING, spdy_stream->SendRequestHeaders(
3629 headers.Pass(), NO_MORE_DATA_TO_SEND));
3631 // Request and response.
3632 base::RunLoop().RunUntilIdle();
3633 EXPECT_TRUE(spdy_stream->IsLocallyClosed());
3634 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3636 // First data frame.
3637 data.CompleteRead();
3638 base::RunLoop().RunUntilIdle();
3639 EXPECT_TRUE(spdy_stream->IsLocallyClosed());
3640 EXPECT_EQ(stream_max_recv_window_size - first_data_frame_size,
3641 spdy_stream->recv_window_size());
3643 // Consume first data frame. This does not trigger a WINDOW_UPDATE.
3644 std::string received_data = delegate.TakeReceivedData();
3645 EXPECT_EQ(static_cast<size_t>(first_data_frame_size), received_data.size());
3646 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3648 // Second data frame overflows receiving window, causes the stream to close.
3649 data.CompleteRead();
3650 base::RunLoop().RunUntilIdle();
3651 EXPECT_FALSE(spdy_stream.get());
3653 // RST_STREAM
3654 EXPECT_TRUE(session_);
3655 data.CompleteRead();
3656 base::RunLoop().RunUntilIdle();
3657 EXPECT_FALSE(session_);
3660 // A delegate that drops any received data.
3661 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3662 public:
3663 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3664 base::StringPiece data)
3665 : StreamDelegateSendImmediate(stream, data) {}
3667 ~DropReceivedDataDelegate() override {}
3669 // Drop any received data.
3670 void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override {}
3673 // Send data back and forth but use a delegate that drops its received
3674 // data. The receive window should still increase to its original
3675 // value, i.e. we shouldn't "leak" receive window bytes.
3676 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3677 const int32 msg_data_size = 100;
3678 const std::string msg_data(msg_data_size, 'a');
3680 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3681 kDefaultURL, 1, msg_data_size, MEDIUM, nullptr, 0));
3682 scoped_ptr<SpdyFrame> msg(
3683 spdy_util_.ConstructSpdyBodyFrame(
3684 1, msg_data.data(), msg_data_size, false));
3685 MockWrite writes[] = {
3686 CreateMockWrite(*req, 0),
3687 CreateMockWrite(*msg, 2),
3690 scoped_ptr<SpdyFrame> resp(
3691 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3692 scoped_ptr<SpdyFrame> echo(
3693 spdy_util_.ConstructSpdyBodyFrame(
3694 1, msg_data.data(), msg_data_size, false));
3695 scoped_ptr<SpdyFrame> window_update(
3696 spdy_util_.ConstructSpdyWindowUpdate(
3697 kSessionFlowControlStreamId, msg_data_size));
3698 MockRead reads[] = {
3699 CreateMockRead(*resp, 1),
3700 CreateMockRead(*echo, 3),
3701 MockRead(ASYNC, ERR_IO_PENDING, 4),
3702 MockRead(ASYNC, 0, 5) // EOF
3705 // Create SpdySession and SpdyStream and send the request.
3706 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3707 session_deps_.host_resolver->set_synchronous_mode(true);
3708 session_deps_.socket_factory->AddSocketDataProvider(&data);
3710 CreateNetworkSession();
3711 CreateInsecureSpdySession();
3713 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
3714 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
3715 ASSERT_TRUE(stream.get() != nullptr);
3716 EXPECT_EQ(0u, stream->stream_id());
3718 DropReceivedDataDelegate delegate(stream, msg_data);
3719 stream->SetDelegate(&delegate);
3721 scoped_ptr<SpdyHeaderBlock> headers(
3722 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, msg_data_size));
3723 EXPECT_EQ(ERR_IO_PENDING,
3724 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3725 EXPECT_TRUE(stream->HasUrlFromHeaders());
3727 const int32 initial_window_size =
3728 SpdySession::GetDefaultInitialWindowSize(GetParam());
3729 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3730 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3732 base::RunLoop().RunUntilIdle();
3734 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3735 EXPECT_EQ(msg_data_size, session_->session_unacked_recv_window_bytes_);
3737 stream->Close();
3738 EXPECT_FALSE(stream);
3740 EXPECT_EQ(OK, delegate.WaitForClose());
3742 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3743 EXPECT_EQ(msg_data_size, session_->session_unacked_recv_window_bytes_);
3745 data.CompleteRead();
3746 base::RunLoop().RunUntilIdle();
3747 EXPECT_FALSE(session_);
3750 // Send data back and forth but close the stream before its data frame
3751 // can be written to the socket. The send window should then increase
3752 // to its original value, i.e. we shouldn't "leak" send window bytes.
3753 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3754 const int32 msg_data_size = 100;
3755 const std::string msg_data(msg_data_size, 'a');
3757 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3758 kDefaultURL, 1, msg_data_size, MEDIUM, nullptr, 0));
3759 MockWrite writes[] = {
3760 CreateMockWrite(*req, 0),
3763 scoped_ptr<SpdyFrame> resp(
3764 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3765 MockRead reads[] = {
3766 MockRead(ASYNC, ERR_IO_PENDING, 1),
3767 CreateMockRead(*resp, 2),
3768 MockRead(ASYNC, 0, 3) // EOF
3771 // Create SpdySession and SpdyStream and send the request.
3772 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3773 session_deps_.host_resolver->set_synchronous_mode(true);
3774 session_deps_.socket_factory->AddSocketDataProvider(&data);
3776 CreateNetworkSession();
3777 CreateInsecureSpdySession();
3779 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
3780 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
3781 ASSERT_TRUE(stream.get() != nullptr);
3782 EXPECT_EQ(0u, stream->stream_id());
3784 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3785 stream->SetDelegate(&delegate);
3787 scoped_ptr<SpdyHeaderBlock> headers(
3788 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, msg_data_size));
3789 EXPECT_EQ(ERR_IO_PENDING,
3790 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3791 EXPECT_TRUE(stream->HasUrlFromHeaders());
3793 const int32 initial_window_size =
3794 SpdySession::GetDefaultInitialWindowSize(GetParam());
3795 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3797 // Write request.
3798 base::RunLoop().RunUntilIdle();
3800 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3802 // Read response, but do not run the message loop, so that the body is not
3803 // written to the socket.
3804 data.CompleteRead();
3806 EXPECT_EQ(initial_window_size - msg_data_size,
3807 session_->session_send_window_size_);
3809 // Closing the stream should increase the session's send window.
3810 stream->Close();
3811 EXPECT_FALSE(stream);
3813 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3815 EXPECT_EQ(OK, delegate.WaitForClose());
3817 base::RunLoop().RunUntilIdle();
3818 EXPECT_FALSE(session_);
3820 EXPECT_TRUE(data.AllWriteDataConsumed());
3821 EXPECT_TRUE(data.AllReadDataConsumed());
3824 // Send data back and forth; the send and receive windows should
3825 // change appropriately.
3826 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
3827 const int32 msg_data_size = 100;
3828 const std::string msg_data(msg_data_size, 'a');
3830 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3831 kDefaultURL, 1, msg_data_size, MEDIUM, nullptr, 0));
3832 scoped_ptr<SpdyFrame> msg(
3833 spdy_util_.ConstructSpdyBodyFrame(
3834 1, msg_data.data(), msg_data_size, false));
3835 MockWrite writes[] = {
3836 CreateMockWrite(*req, 0),
3837 CreateMockWrite(*msg, 2),
3840 scoped_ptr<SpdyFrame> resp(
3841 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3842 scoped_ptr<SpdyFrame> echo(
3843 spdy_util_.ConstructSpdyBodyFrame(
3844 1, msg_data.data(), msg_data_size, false));
3845 scoped_ptr<SpdyFrame> window_update(
3846 spdy_util_.ConstructSpdyWindowUpdate(
3847 kSessionFlowControlStreamId, msg_data_size));
3848 MockRead reads[] = {
3849 CreateMockRead(*resp, 1),
3850 MockRead(ASYNC, ERR_IO_PENDING, 3),
3851 CreateMockRead(*echo, 4),
3852 MockRead(ASYNC, ERR_IO_PENDING, 5),
3853 CreateMockRead(*window_update, 6),
3854 MockRead(ASYNC, ERR_IO_PENDING, 7),
3855 MockRead(ASYNC, 0, 8) // EOF
3858 // Create SpdySession and SpdyStream and send the request.
3859 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3860 session_deps_.host_resolver->set_synchronous_mode(true);
3861 session_deps_.socket_factory->AddSocketDataProvider(&data);
3863 CreateNetworkSession();
3864 CreateInsecureSpdySession();
3866 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
3867 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
3868 ASSERT_TRUE(stream.get() != nullptr);
3869 EXPECT_EQ(0u, stream->stream_id());
3871 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3872 stream->SetDelegate(&delegate);
3874 scoped_ptr<SpdyHeaderBlock> headers(
3875 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, msg_data_size));
3876 EXPECT_EQ(ERR_IO_PENDING,
3877 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3878 EXPECT_TRUE(stream->HasUrlFromHeaders());
3880 const int32 initial_window_size =
3881 SpdySession::GetDefaultInitialWindowSize(GetParam());
3882 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3883 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3884 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3886 // Send request and message.
3887 base::RunLoop().RunUntilIdle();
3889 EXPECT_EQ(initial_window_size - msg_data_size,
3890 session_->session_send_window_size_);
3891 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3892 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3894 // Read echo.
3895 data.CompleteRead();
3896 base::RunLoop().RunUntilIdle();
3898 EXPECT_EQ(initial_window_size - msg_data_size,
3899 session_->session_send_window_size_);
3900 EXPECT_EQ(initial_window_size - msg_data_size,
3901 session_->session_recv_window_size_);
3902 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3904 // Read window update.
3905 data.CompleteRead();
3906 base::RunLoop().RunUntilIdle();
3908 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3909 EXPECT_EQ(initial_window_size - msg_data_size,
3910 session_->session_recv_window_size_);
3911 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3913 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
3915 // Draining the delegate's read queue should increase the session's
3916 // receive window.
3917 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3918 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3919 EXPECT_EQ(msg_data_size, session_->session_unacked_recv_window_bytes_);
3921 stream->Close();
3922 EXPECT_FALSE(stream);
3924 EXPECT_EQ(OK, delegate.WaitForClose());
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(msg_data_size, session_->session_unacked_recv_window_bytes_);
3930 data.CompleteRead();
3931 base::RunLoop().RunUntilIdle();
3932 EXPECT_FALSE(session_);
3935 // Given a stall function and an unstall function, runs a test to make
3936 // sure that a stream resumes after unstall.
3937 void SpdySessionTest::RunResumeAfterUnstallTest(
3938 const base::Callback<void(SpdyStream*)>& stall_function,
3939 const base::Callback<void(SpdyStream*, int32)>& unstall_function) {
3941 session_deps_.host_resolver->set_synchronous_mode(true);
3943 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3944 kDefaultURL, 1, kBodyDataSize, LOWEST, nullptr, 0));
3945 scoped_ptr<SpdyFrame> body(
3946 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3947 MockWrite writes[] = {
3948 CreateMockWrite(*req, 0),
3949 CreateMockWrite(*body, 1),
3952 scoped_ptr<SpdyFrame> resp(
3953 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3954 scoped_ptr<SpdyFrame> echo(
3955 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
3956 MockRead reads[] = {
3957 CreateMockRead(*resp, 2), MockRead(ASYNC, 0, 3) // EOF
3960 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3961 session_deps_.socket_factory->AddSocketDataProvider(&data);
3963 CreateNetworkSession();
3964 CreateInsecureSpdySession();
3965 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3966 session_->flow_control_state());
3968 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
3969 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
3970 ASSERT_TRUE(stream.get() != nullptr);
3972 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
3973 stream->SetDelegate(&delegate);
3975 EXPECT_FALSE(stream->HasUrlFromHeaders());
3976 EXPECT_FALSE(stream->send_stalled_by_flow_control());
3978 scoped_ptr<SpdyHeaderBlock> headers(
3979 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
3980 EXPECT_EQ(ERR_IO_PENDING,
3981 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3982 EXPECT_TRUE(stream->HasUrlFromHeaders());
3983 EXPECT_EQ(kDefaultURL, stream->GetUrlFromHeaders().spec());
3985 stall_function.Run(stream.get());
3987 base::RunLoop().RunUntilIdle();
3989 EXPECT_TRUE(stream->send_stalled_by_flow_control());
3991 unstall_function.Run(stream.get(), kBodyDataSize);
3993 EXPECT_FALSE(stream->send_stalled_by_flow_control());
3995 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
3997 EXPECT_TRUE(delegate.send_headers_completed());
3998 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
3999 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
4000 EXPECT_FALSE(session_);
4001 EXPECT_TRUE(data.AllWriteDataConsumed());
4004 // Run the resume-after-unstall test with all possible stall and
4005 // unstall sequences.
4007 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
4008 RunResumeAfterUnstallTest(
4009 base::Bind(&SpdySessionTest::StallSessionOnly,
4010 base::Unretained(this)),
4011 base::Bind(&SpdySessionTest::UnstallSessionOnly,
4012 base::Unretained(this)));
4015 // Equivalent to
4016 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4017 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
4018 RunResumeAfterUnstallTest(
4019 base::Bind(&SpdySessionTest::StallStreamOnly,
4020 base::Unretained(this)),
4021 base::Bind(&SpdySessionTest::UnstallStreamOnly,
4022 base::Unretained(this)));
4025 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4026 RunResumeAfterUnstallTest(
4027 base::Bind(&SpdySessionTest::StallSessionStream,
4028 base::Unretained(this)),
4029 base::Bind(&SpdySessionTest::UnstallSessionStream,
4030 base::Unretained(this)));
4033 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4034 RunResumeAfterUnstallTest(
4035 base::Bind(&SpdySessionTest::StallStreamSession,
4036 base::Unretained(this)),
4037 base::Bind(&SpdySessionTest::UnstallSessionStream,
4038 base::Unretained(this)));
4041 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4042 RunResumeAfterUnstallTest(
4043 base::Bind(&SpdySessionTest::StallStreamSession,
4044 base::Unretained(this)),
4045 base::Bind(&SpdySessionTest::UnstallStreamSession,
4046 base::Unretained(this)));
4049 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4050 RunResumeAfterUnstallTest(
4051 base::Bind(&SpdySessionTest::StallSessionStream,
4052 base::Unretained(this)),
4053 base::Bind(&SpdySessionTest::UnstallStreamSession,
4054 base::Unretained(this)));
4057 // Cause a stall by reducing the flow control send window to 0. The
4058 // streams should resume in priority order when that window is then
4059 // increased.
4060 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4061 session_deps_.host_resolver->set_synchronous_mode(true);
4063 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4064 kDefaultURL, 1, kBodyDataSize, LOWEST, nullptr, 0));
4065 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4066 kDefaultURL, 3, kBodyDataSize, MEDIUM, nullptr, 0));
4067 scoped_ptr<SpdyFrame> body1(
4068 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4069 scoped_ptr<SpdyFrame> body2(
4070 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4071 MockWrite writes[] = {
4072 CreateMockWrite(*req1, 0),
4073 CreateMockWrite(*req2, 1),
4074 CreateMockWrite(*body2, 2),
4075 CreateMockWrite(*body1, 3),
4078 scoped_ptr<SpdyFrame> resp1(
4079 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4080 scoped_ptr<SpdyFrame> resp2(
4081 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
4082 MockRead reads[] = {
4083 CreateMockRead(*resp1, 4),
4084 CreateMockRead(*resp2, 5),
4085 MockRead(ASYNC, 0, 6) // EOF
4088 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4089 session_deps_.socket_factory->AddSocketDataProvider(&data);
4091 CreateNetworkSession();
4092 CreateInsecureSpdySession();
4093 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4094 session_->flow_control_state());
4096 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
4097 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4098 ASSERT_TRUE(stream1.get() != nullptr);
4100 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4101 stream1->SetDelegate(&delegate1);
4103 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4105 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
4106 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
4107 ASSERT_TRUE(stream2.get() != nullptr);
4109 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4110 stream2->SetDelegate(&delegate2);
4112 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4114 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4115 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4117 StallSessionSend();
4119 scoped_ptr<SpdyHeaderBlock> headers1(
4120 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
4121 EXPECT_EQ(ERR_IO_PENDING,
4122 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4123 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4124 EXPECT_EQ(kDefaultURL, stream1->GetUrlFromHeaders().spec());
4126 base::RunLoop().RunUntilIdle();
4127 EXPECT_EQ(1u, stream1->stream_id());
4128 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4130 scoped_ptr<SpdyHeaderBlock> headers2(
4131 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
4132 EXPECT_EQ(ERR_IO_PENDING,
4133 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4134 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4135 EXPECT_EQ(kDefaultURL, stream2->GetUrlFromHeaders().spec());
4137 base::RunLoop().RunUntilIdle();
4138 EXPECT_EQ(3u, stream2->stream_id());
4139 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4141 // This should unstall only stream2.
4142 UnstallSessionSend(kBodyDataSize);
4144 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4145 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4147 base::RunLoop().RunUntilIdle();
4149 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4150 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4152 // This should then unstall stream1.
4153 UnstallSessionSend(kBodyDataSize);
4155 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4156 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4158 base::RunLoop().RunUntilIdle();
4160 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4161 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4163 EXPECT_TRUE(delegate1.send_headers_completed());
4164 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4165 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4167 EXPECT_TRUE(delegate2.send_headers_completed());
4168 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4169 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4171 EXPECT_FALSE(session_);
4172 EXPECT_TRUE(data.AllWriteDataConsumed());
4173 EXPECT_TRUE(data.AllReadDataConsumed());
4176 // Delegate that closes a given stream after sending its body.
4177 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4178 public:
4179 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4180 base::StringPiece data)
4181 : StreamDelegateWithBody(stream, data) {}
4183 ~StreamClosingDelegate() override {}
4185 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4186 stream_to_close_ = stream_to_close;
4189 void OnDataSent() override {
4190 test::StreamDelegateWithBody::OnDataSent();
4191 if (stream_to_close_.get()) {
4192 stream_to_close_->Close();
4193 EXPECT_FALSE(stream_to_close_);
4197 private:
4198 base::WeakPtr<SpdyStream> stream_to_close_;
4201 // Cause a stall by reducing the flow control send window to
4202 // 0. Unstalling the session should properly handle deleted streams.
4203 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4204 session_deps_.host_resolver->set_synchronous_mode(true);
4206 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4207 kDefaultURL, 1, kBodyDataSize, LOWEST, nullptr, 0));
4208 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4209 kDefaultURL, 3, kBodyDataSize, LOWEST, nullptr, 0));
4210 scoped_ptr<SpdyFrame> req3(spdy_util_.ConstructSpdyPost(
4211 kDefaultURL, 5, kBodyDataSize, LOWEST, nullptr, 0));
4212 scoped_ptr<SpdyFrame> body2(
4213 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4214 MockWrite writes[] = {
4215 CreateMockWrite(*req1, 0),
4216 CreateMockWrite(*req2, 1),
4217 CreateMockWrite(*req3, 2),
4218 CreateMockWrite(*body2, 3),
4221 scoped_ptr<SpdyFrame> resp2(
4222 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
4223 MockRead reads[] = {
4224 CreateMockRead(*resp2, 4),
4225 MockRead(ASYNC, ERR_IO_PENDING, 5),
4226 MockRead(ASYNC, 0, 6) // EOF
4229 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4230 session_deps_.socket_factory->AddSocketDataProvider(&data);
4232 CreateNetworkSession();
4233 CreateInsecureSpdySession();
4234 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4235 session_->flow_control_state());
4237 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
4238 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4239 ASSERT_TRUE(stream1.get() != nullptr);
4241 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4242 stream1->SetDelegate(&delegate1);
4244 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4246 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
4247 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4248 ASSERT_TRUE(stream2.get() != nullptr);
4250 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4251 stream2->SetDelegate(&delegate2);
4253 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4255 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
4256 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4257 ASSERT_TRUE(stream3.get() != nullptr);
4259 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4260 stream3->SetDelegate(&delegate3);
4262 EXPECT_FALSE(stream3->HasUrlFromHeaders());
4264 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4265 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4266 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4268 StallSessionSend();
4270 scoped_ptr<SpdyHeaderBlock> headers1(
4271 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
4272 EXPECT_EQ(ERR_IO_PENDING,
4273 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4274 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4275 EXPECT_EQ(kDefaultURL, stream1->GetUrlFromHeaders().spec());
4277 base::RunLoop().RunUntilIdle();
4278 EXPECT_EQ(1u, stream1->stream_id());
4279 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4281 scoped_ptr<SpdyHeaderBlock> headers2(
4282 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
4283 EXPECT_EQ(ERR_IO_PENDING,
4284 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4285 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4286 EXPECT_EQ(kDefaultURL, stream2->GetUrlFromHeaders().spec());
4288 base::RunLoop().RunUntilIdle();
4289 EXPECT_EQ(3u, stream2->stream_id());
4290 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4292 scoped_ptr<SpdyHeaderBlock> headers3(
4293 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
4294 EXPECT_EQ(ERR_IO_PENDING,
4295 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4296 EXPECT_TRUE(stream3->HasUrlFromHeaders());
4297 EXPECT_EQ(kDefaultURL, stream3->GetUrlFromHeaders().spec());
4299 base::RunLoop().RunUntilIdle();
4300 EXPECT_EQ(5u, stream3->stream_id());
4301 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4303 SpdyStreamId stream_id1 = stream1->stream_id();
4304 SpdyStreamId stream_id2 = stream2->stream_id();
4305 SpdyStreamId stream_id3 = stream3->stream_id();
4307 // Close stream1 preemptively.
4308 session_->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4309 EXPECT_FALSE(stream1);
4311 EXPECT_FALSE(session_->IsStreamActive(stream_id1));
4312 EXPECT_TRUE(session_->IsStreamActive(stream_id2));
4313 EXPECT_TRUE(session_->IsStreamActive(stream_id3));
4315 // Unstall stream2, which should then close stream3.
4316 delegate2.set_stream_to_close(stream3);
4317 UnstallSessionSend(kBodyDataSize);
4319 base::RunLoop().RunUntilIdle();
4320 EXPECT_FALSE(stream3);
4322 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4323 EXPECT_FALSE(session_->IsStreamActive(stream_id1));
4324 EXPECT_TRUE(session_->IsStreamActive(stream_id2));
4325 EXPECT_FALSE(session_->IsStreamActive(stream_id3));
4327 data.CompleteRead();
4328 base::RunLoop().RunUntilIdle();
4329 EXPECT_FALSE(stream2);
4330 EXPECT_FALSE(session_);
4332 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4333 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4334 EXPECT_EQ(OK, delegate3.WaitForClose());
4336 EXPECT_TRUE(delegate1.send_headers_completed());
4337 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4339 EXPECT_TRUE(delegate2.send_headers_completed());
4340 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4341 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4343 EXPECT_TRUE(delegate3.send_headers_completed());
4344 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4346 EXPECT_TRUE(data.AllWriteDataConsumed());
4349 // Cause a stall by reducing the flow control send window to
4350 // 0. Unstalling the session should properly handle the session itself
4351 // being closed.
4352 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4353 session_deps_.host_resolver->set_synchronous_mode(true);
4355 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4356 kDefaultURL, 1, kBodyDataSize, LOWEST, nullptr, 0));
4357 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4358 kDefaultURL, 3, kBodyDataSize, LOWEST, nullptr, 0));
4359 scoped_ptr<SpdyFrame> body1(
4360 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4361 MockWrite writes[] = {
4362 CreateMockWrite(*req1, 0),
4363 CreateMockWrite(*req2, 1),
4366 MockRead reads[] = {
4367 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
4370 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4371 session_deps_.socket_factory->AddSocketDataProvider(&data);
4373 CreateNetworkSession();
4374 CreateInsecureSpdySession();
4375 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4376 session_->flow_control_state());
4378 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
4379 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4380 ASSERT_TRUE(stream1.get() != nullptr);
4382 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4383 stream1->SetDelegate(&delegate1);
4385 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4387 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
4388 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4389 ASSERT_TRUE(stream2.get() != nullptr);
4391 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4392 stream2->SetDelegate(&delegate2);
4394 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4396 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4397 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4399 StallSessionSend();
4401 scoped_ptr<SpdyHeaderBlock> headers1(
4402 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
4403 EXPECT_EQ(ERR_IO_PENDING,
4404 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4405 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4406 EXPECT_EQ(kDefaultURL, stream1->GetUrlFromHeaders().spec());
4408 base::RunLoop().RunUntilIdle();
4409 EXPECT_EQ(1u, stream1->stream_id());
4410 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4412 scoped_ptr<SpdyHeaderBlock> headers2(
4413 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
4414 EXPECT_EQ(ERR_IO_PENDING,
4415 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4416 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4417 EXPECT_EQ(kDefaultURL, stream2->GetUrlFromHeaders().spec());
4419 base::RunLoop().RunUntilIdle();
4420 EXPECT_EQ(3u, stream2->stream_id());
4421 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4423 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4425 // Unstall stream1.
4426 UnstallSessionSend(kBodyDataSize);
4428 // Close the session (since we can't do it from within the delegate
4429 // method, since it's in the stream's loop).
4430 session_->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4431 data.CompleteRead();
4432 base::RunLoop().RunUntilIdle();
4433 EXPECT_FALSE(session_);
4435 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4437 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4438 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4440 EXPECT_TRUE(delegate1.send_headers_completed());
4441 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4443 EXPECT_TRUE(delegate2.send_headers_completed());
4444 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4446 EXPECT_TRUE(data.AllWriteDataConsumed());
4449 TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4450 scoped_ptr<SpdyFrame> req(
4451 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4452 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4453 0, GOAWAY_FLOW_CONTROL_ERROR,
4454 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4455 "the receive window size of 1"));
4456 MockWrite writes[] = {
4457 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 4),
4460 scoped_ptr<SpdyFrame> resp(
4461 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4462 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4463 MockRead reads[] = {
4464 MockRead(ASYNC, ERR_IO_PENDING, 1),
4465 CreateMockRead(*resp, 2),
4466 CreateMockRead(*body, 3),
4469 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4470 session_deps_.socket_factory->AddSocketDataProvider(&data);
4472 CreateNetworkSession();
4473 CreateInsecureSpdySession();
4475 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4476 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4477 ASSERT_TRUE(spdy_stream.get() != nullptr);
4478 test::StreamDelegateDoNothing delegate(spdy_stream);
4479 spdy_stream->SetDelegate(&delegate);
4481 scoped_ptr<SpdyHeaderBlock> headers(
4482 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
4483 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4485 // Write request.
4486 base::RunLoop().RunUntilIdle();
4488 // Put session on the edge of overflowing it's recv window.
4489 session_->session_recv_window_size_ = 1;
4491 // Read response headers & body. Body overflows the session window, and a
4492 // goaway is written.
4493 data.CompleteRead();
4494 base::RunLoop().RunUntilIdle();
4496 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4497 EXPECT_FALSE(session_);
4500 TEST_P(SpdySessionTest, SplitHeaders) {
4501 GURL kStreamUrl("http://www.example.org/foo.dat");
4502 SpdyHeaderBlock headers;
4503 spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4504 headers["alpha"] = "beta";
4506 SpdyHeaderBlock request_headers;
4507 SpdyHeaderBlock response_headers;
4509 SplitPushedHeadersToRequestAndResponse(
4510 headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4512 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4513 std::string alpha_val =
4514 (it == response_headers.end()) ? std::string() : it->second;
4515 EXPECT_EQ("beta", alpha_val);
4517 GURL request_url =
4518 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4519 EXPECT_EQ(kStreamUrl, request_url);
4522 // Regression. Sorta. Push streams and client streams were sharing a single
4523 // limit for a long time.
4524 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4525 SettingsMap new_settings;
4526 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4527 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4528 scoped_ptr<SpdyFrame> settings_frame(
4529 spdy_util_.ConstructSpdySettings(new_settings));
4530 scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4531 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4532 MockRead reads[] = {
4533 CreateMockRead(*settings_frame, 0),
4534 MockRead(ASYNC, ERR_IO_PENDING, 3),
4535 CreateMockRead(*pushed, 4),
4536 MockRead(ASYNC, ERR_IO_PENDING, 5),
4537 MockRead(ASYNC, 0, 6),
4540 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4541 scoped_ptr<SpdyFrame> req(
4542 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4543 MockWrite writes[] = {
4544 CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4547 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4548 session_deps_.socket_factory->AddSocketDataProvider(&data);
4550 CreateNetworkSession();
4551 CreateInsecureSpdySession();
4553 // Read the settings frame.
4554 base::RunLoop().RunUntilIdle();
4556 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4557 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4558 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4559 EXPECT_EQ(0u, spdy_stream1->stream_id());
4560 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4561 spdy_stream1->SetDelegate(&delegate1);
4563 EXPECT_EQ(0u, session_->num_active_streams());
4564 EXPECT_EQ(1u, session_->num_created_streams());
4565 EXPECT_EQ(0u, session_->num_pushed_streams());
4566 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4568 scoped_ptr<SpdyHeaderBlock> headers(
4569 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
4570 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4571 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4573 // Run until 1st stream is activated.
4574 EXPECT_EQ(0u, delegate1.stream_id());
4575 base::RunLoop().RunUntilIdle();
4576 EXPECT_EQ(1u, delegate1.stream_id());
4577 EXPECT_EQ(1u, session_->num_active_streams());
4578 EXPECT_EQ(0u, session_->num_created_streams());
4579 EXPECT_EQ(0u, session_->num_pushed_streams());
4580 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4582 // Run until pushed stream is created.
4583 data.CompleteRead();
4584 base::RunLoop().RunUntilIdle();
4585 EXPECT_EQ(2u, session_->num_active_streams());
4586 EXPECT_EQ(0u, session_->num_created_streams());
4587 EXPECT_EQ(1u, session_->num_pushed_streams());
4588 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4590 // Second stream should not be stalled, although we have 2 active streams, but
4591 // one of them is push stream and should not be taken into account when we
4592 // create streams on the client.
4593 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4594 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4595 EXPECT_TRUE(spdy_stream2);
4596 EXPECT_EQ(2u, session_->num_active_streams());
4597 EXPECT_EQ(1u, session_->num_created_streams());
4598 EXPECT_EQ(1u, session_->num_pushed_streams());
4599 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4601 // Read EOF.
4602 data.CompleteRead();
4603 base::RunLoop().RunUntilIdle();
4604 EXPECT_FALSE(session_);
4607 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4608 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4609 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4610 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4611 nullptr, 0, 4, 1, "http://www.example.org/b.dat"));
4612 MockRead reads[] = {
4613 MockRead(ASYNC, ERR_IO_PENDING, 1),
4614 CreateMockRead(*push_a, 2),
4615 MockRead(ASYNC, ERR_IO_PENDING, 3),
4616 CreateMockRead(*push_b, 4),
4617 MockRead(ASYNC, ERR_IO_PENDING, 6),
4618 MockRead(ASYNC, 0, 7),
4621 scoped_ptr<SpdyFrame> req(
4622 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4623 scoped_ptr<SpdyFrame> rst(
4624 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4625 MockWrite writes[] = {
4626 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
4629 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4630 session_deps_.socket_factory->AddSocketDataProvider(&data);
4632 CreateNetworkSession();
4633 CreateInsecureSpdySession();
4634 session_->set_max_concurrent_pushed_streams(1);
4636 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4637 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4638 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4639 EXPECT_EQ(0u, spdy_stream1->stream_id());
4640 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4641 spdy_stream1->SetDelegate(&delegate1);
4643 EXPECT_EQ(0u, session_->num_active_streams());
4644 EXPECT_EQ(1u, session_->num_created_streams());
4645 EXPECT_EQ(0u, session_->num_pushed_streams());
4646 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4648 scoped_ptr<SpdyHeaderBlock> headers(
4649 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
4650 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4651 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4653 // Run until 1st stream is activated.
4654 EXPECT_EQ(0u, delegate1.stream_id());
4655 base::RunLoop().RunUntilIdle();
4656 EXPECT_EQ(1u, delegate1.stream_id());
4657 EXPECT_EQ(1u, session_->num_active_streams());
4658 EXPECT_EQ(0u, session_->num_created_streams());
4659 EXPECT_EQ(0u, session_->num_pushed_streams());
4660 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4662 // Run until pushed stream is created.
4663 data.CompleteRead();
4664 base::RunLoop().RunUntilIdle();
4665 EXPECT_EQ(2u, session_->num_active_streams());
4666 EXPECT_EQ(0u, session_->num_created_streams());
4667 EXPECT_EQ(1u, session_->num_pushed_streams());
4668 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4670 // Reset incoming pushed stream.
4671 data.CompleteRead();
4672 base::RunLoop().RunUntilIdle();
4673 EXPECT_EQ(2u, session_->num_active_streams());
4674 EXPECT_EQ(0u, session_->num_created_streams());
4675 EXPECT_EQ(1u, session_->num_pushed_streams());
4676 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4678 // Read EOF.
4679 data.CompleteRead();
4680 base::RunLoop().RunUntilIdle();
4681 EXPECT_FALSE(session_);
4684 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4685 // Streams in reserved remote state exist only in HTTP/2.
4686 if (spdy_util_.spdy_version() < HTTP2)
4687 return;
4689 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4690 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4691 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4692 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/b.dat",
4693 push_headers.get());
4694 scoped_ptr<SpdyFrame> push_b(
4695 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4696 scoped_ptr<SpdyFrame> headers_b(
4697 spdy_util_.ConstructSpdyPushHeaders(4, nullptr, 0));
4698 MockRead reads[] = {
4699 MockRead(ASYNC, ERR_IO_PENDING, 1),
4700 CreateMockRead(*push_a, 2),
4701 MockRead(ASYNC, ERR_IO_PENDING, 3),
4702 CreateMockRead(*push_b, 4),
4703 MockRead(ASYNC, ERR_IO_PENDING, 5),
4704 CreateMockRead(*headers_b, 6),
4705 MockRead(ASYNC, ERR_IO_PENDING, 8),
4706 MockRead(ASYNC, 0, 9),
4709 scoped_ptr<SpdyFrame> req(
4710 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4711 scoped_ptr<SpdyFrame> rst(
4712 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4713 MockWrite writes[] = {
4714 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 7),
4717 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4718 session_deps_.socket_factory->AddSocketDataProvider(&data);
4720 CreateNetworkSession();
4721 CreateInsecureSpdySession();
4722 session_->set_max_concurrent_pushed_streams(1);
4724 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4725 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4726 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4727 EXPECT_EQ(0u, spdy_stream1->stream_id());
4728 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4729 spdy_stream1->SetDelegate(&delegate1);
4731 EXPECT_EQ(0u, session_->num_active_streams());
4732 EXPECT_EQ(1u, session_->num_created_streams());
4733 EXPECT_EQ(0u, session_->num_pushed_streams());
4734 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4736 scoped_ptr<SpdyHeaderBlock> headers(
4737 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
4738 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4739 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4741 // Run until 1st stream is activated.
4742 EXPECT_EQ(0u, delegate1.stream_id());
4743 base::RunLoop().RunUntilIdle();
4744 EXPECT_EQ(1u, delegate1.stream_id());
4745 EXPECT_EQ(1u, session_->num_active_streams());
4746 EXPECT_EQ(0u, session_->num_created_streams());
4747 EXPECT_EQ(0u, session_->num_pushed_streams());
4748 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4750 // Run until pushed stream is created.
4751 data.CompleteRead();
4752 base::RunLoop().RunUntilIdle();
4753 EXPECT_EQ(2u, session_->num_active_streams());
4754 EXPECT_EQ(0u, session_->num_created_streams());
4755 EXPECT_EQ(1u, session_->num_pushed_streams());
4756 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4758 // Accept promised stream. It should not count towards pushed stream limit.
4759 data.CompleteRead();
4760 base::RunLoop().RunUntilIdle();
4761 EXPECT_EQ(3u, session_->num_active_streams());
4762 EXPECT_EQ(0u, session_->num_created_streams());
4763 EXPECT_EQ(2u, session_->num_pushed_streams());
4764 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4766 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4767 // while we accept only one.
4768 data.CompleteRead();
4769 base::RunLoop().RunUntilIdle();
4770 EXPECT_EQ(2u, session_->num_active_streams());
4771 EXPECT_EQ(0u, session_->num_created_streams());
4772 EXPECT_EQ(1u, session_->num_pushed_streams());
4773 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4775 // Read EOF.
4776 data.CompleteRead();
4777 base::RunLoop().RunUntilIdle();
4778 EXPECT_FALSE(session_);
4781 TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
4782 // Streams in reserved remote state exist only in HTTP/2.
4783 if (spdy_util_.spdy_version() < HTTP2)
4784 return;
4786 const char kPushedUrl[] = "http://www.example.org/a.dat";
4787 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4788 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
4789 scoped_ptr<SpdyFrame> push_promise(
4790 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
4791 scoped_ptr<SpdyFrame> headers_frame(
4792 spdy_util_.ConstructSpdyPushHeaders(2, nullptr, 0));
4793 MockRead reads[] = {
4794 MockRead(ASYNC, ERR_IO_PENDING, 1),
4795 CreateMockRead(*push_promise, 2),
4796 MockRead(ASYNC, ERR_IO_PENDING, 3),
4797 CreateMockRead(*headers_frame, 4),
4798 MockRead(ASYNC, ERR_IO_PENDING, 6),
4799 MockRead(ASYNC, 0, 7),
4802 scoped_ptr<SpdyFrame> req(
4803 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4804 scoped_ptr<SpdyFrame> rst(
4805 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
4806 MockWrite writes[] = {
4807 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
4810 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4811 session_deps_.socket_factory->AddSocketDataProvider(&data);
4813 CreateNetworkSession();
4814 CreateInsecureSpdySession();
4816 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4817 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4818 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4819 EXPECT_EQ(0u, spdy_stream1->stream_id());
4820 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4821 spdy_stream1->SetDelegate(&delegate1);
4823 EXPECT_EQ(0u, session_->num_active_streams());
4824 EXPECT_EQ(1u, session_->num_created_streams());
4825 EXPECT_EQ(0u, session_->num_pushed_streams());
4826 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4828 scoped_ptr<SpdyHeaderBlock> headers(
4829 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
4830 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4831 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4833 // Run until 1st stream is activated.
4834 EXPECT_EQ(0u, delegate1.stream_id());
4835 base::RunLoop().RunUntilIdle();
4836 EXPECT_EQ(1u, delegate1.stream_id());
4837 EXPECT_EQ(1u, session_->num_active_streams());
4838 EXPECT_EQ(0u, session_->num_created_streams());
4839 EXPECT_EQ(0u, session_->num_pushed_streams());
4840 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4842 // Run until pushed stream is created.
4843 data.CompleteRead();
4844 base::RunLoop().RunUntilIdle();
4845 EXPECT_EQ(2u, session_->num_active_streams());
4846 EXPECT_EQ(0u, session_->num_created_streams());
4847 EXPECT_EQ(1u, session_->num_pushed_streams());
4848 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4850 base::WeakPtr<SpdyStream> pushed_stream;
4851 int rv =
4852 session_->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
4853 ASSERT_EQ(OK, rv);
4854 ASSERT_TRUE(pushed_stream.get() != nullptr);
4855 test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
4856 pushed_stream->SetDelegate(&delegate2);
4858 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4859 // that all our counters are in consistent state.
4860 data.CompleteRead();
4861 base::RunLoop().RunUntilIdle();
4862 EXPECT_EQ(1u, session_->num_active_streams());
4863 EXPECT_EQ(0u, session_->num_created_streams());
4864 EXPECT_EQ(0u, session_->num_pushed_streams());
4865 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4867 // Read EOF.
4868 data.CompleteRead();
4869 base::RunLoop().RunUntilIdle();
4870 EXPECT_TRUE(data.AllWriteDataConsumed());
4871 EXPECT_TRUE(data.AllReadDataConsumed());
4874 TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
4875 session_deps_.host_resolver->set_synchronous_mode(true);
4877 MockRead reads[] = {
4878 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
4881 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
4882 session_deps_.socket_factory->AddSocketDataProvider(&data);
4884 CreateNetworkSession();
4885 CreateInsecureSpdySession();
4887 session_->stream_hi_water_mark_ = 5;
4888 // Low client (odd) ids are fine.
4889 EXPECT_TRUE(session_->OnUnknownFrame(3, 0));
4890 // Client id exceeding watermark.
4891 EXPECT_FALSE(session_->OnUnknownFrame(9, 0));
4893 session_->last_accepted_push_stream_id_ = 6;
4894 // Low server (even) ids are fine.
4895 EXPECT_TRUE(session_->OnUnknownFrame(2, 0));
4896 // Server id exceeding last accepted id.
4897 EXPECT_FALSE(session_->OnUnknownFrame(8, 0));
4900 TEST(MapFramerErrorToProtocolError, MapsValues) {
4901 CHECK_EQ(
4902 SPDY_ERROR_INVALID_CONTROL_FRAME,
4903 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4904 CHECK_EQ(
4905 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4906 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4907 CHECK_EQ(
4908 SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
4909 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
4910 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
4911 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
4914 TEST(MapFramerErrorToNetError, MapsValue) {
4915 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
4916 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4917 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4918 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
4919 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4920 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4921 CHECK_EQ(
4922 ERR_SPDY_FRAME_SIZE_ERROR,
4923 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
4926 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
4927 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
4928 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
4929 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
4930 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
4931 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
4932 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
4933 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY,
4934 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY));
4935 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED,
4936 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED));
4939 TEST(MapNetErrorToGoAwayStatus, MapsValue) {
4940 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
4941 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
4942 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
4943 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
4944 CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
4945 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
4946 CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
4947 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
4948 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
4949 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
4950 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
4953 TEST(CanPoolTest, CanPool) {
4954 // Load a cert that is valid for:
4955 // www.example.org
4956 // mail.example.org
4957 // www.example.com
4959 TransportSecurityState tss;
4960 SSLInfo ssl_info;
4961 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
4962 "spdy_pooling.pem");
4964 EXPECT_TRUE(SpdySession::CanPool(
4965 &tss, ssl_info, "www.example.org", "www.example.org"));
4966 EXPECT_TRUE(SpdySession::CanPool(
4967 &tss, ssl_info, "www.example.org", "mail.example.org"));
4968 EXPECT_TRUE(SpdySession::CanPool(
4969 &tss, ssl_info, "www.example.org", "mail.example.com"));
4970 EXPECT_FALSE(SpdySession::CanPool(
4971 &tss, ssl_info, "www.example.org", "mail.google.com"));
4974 TEST(CanPoolTest, CanNotPoolWithCertErrors) {
4975 // Load a cert that is valid for:
4976 // www.example.org
4977 // mail.example.org
4978 // www.example.com
4980 TransportSecurityState tss;
4981 SSLInfo ssl_info;
4982 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
4983 "spdy_pooling.pem");
4984 ssl_info.cert_status = CERT_STATUS_REVOKED;
4986 EXPECT_FALSE(SpdySession::CanPool(
4987 &tss, ssl_info, "www.example.org", "mail.example.org"));
4990 TEST(CanPoolTest, CanNotPoolWithClientCerts) {
4991 // Load a cert that is valid for:
4992 // www.example.org
4993 // mail.example.org
4994 // www.example.com
4996 TransportSecurityState tss;
4997 SSLInfo ssl_info;
4998 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
4999 "spdy_pooling.pem");
5000 ssl_info.client_cert_sent = true;
5002 EXPECT_FALSE(SpdySession::CanPool(
5003 &tss, ssl_info, "www.example.org", "mail.example.org"));
5006 TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
5007 // Load a cert that is valid for:
5008 // www.example.org
5009 // mail.example.org
5010 // www.example.com
5012 TransportSecurityState tss;
5013 SSLInfo ssl_info;
5014 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5015 "spdy_pooling.pem");
5016 ssl_info.channel_id_sent = true;
5018 EXPECT_TRUE(SpdySession::CanPool(
5019 &tss, ssl_info, "www.example.org", "mail.example.org"));
5020 EXPECT_FALSE(SpdySession::CanPool(
5021 &tss, ssl_info, "www.example.org", "www.example.com"));
5024 TEST(CanPoolTest, CanNotPoolWithBadPins) {
5025 uint8 primary_pin = 1;
5026 uint8 backup_pin = 2;
5027 uint8 bad_pin = 3;
5028 TransportSecurityState tss;
5029 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5031 SSLInfo ssl_info;
5032 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5033 "spdy_pooling.pem");
5034 ssl_info.is_issued_by_known_root = true;
5035 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
5037 EXPECT_FALSE(SpdySession::CanPool(
5038 &tss, ssl_info, "www.example.org", "mail.example.org"));
5041 TEST(CanPoolTest, CanPoolWithAcceptablePins) {
5042 uint8 primary_pin = 1;
5043 uint8 backup_pin = 2;
5044 TransportSecurityState tss;
5045 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5047 SSLInfo ssl_info;
5048 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5049 "spdy_pooling.pem");
5050 ssl_info.is_issued_by_known_root = true;
5051 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
5053 EXPECT_TRUE(SpdySession::CanPool(
5054 &tss, ssl_info, "www.example.org", "mail.example.org"));
5057 } // namespace net