Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / net / spdy / spdy_session_unittest.cc
blobfdcbb0aa5c3dfe108dae5a2507d09654b7fa916e
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 base::TimeTicks TheNearFuture() {
44 return base::TimeTicks::Now() + g_time_delta;
47 base::TimeTicks SlowReads() {
48 g_time_delta +=
49 base::TimeDelta::FromMilliseconds(2 * kYieldAfterDurationMilliseconds);
50 return base::TimeTicks::Now() + g_time_delta;
53 } // namespace
55 class SpdySessionTest : public PlatformTest,
56 public ::testing::WithParamInterface<NextProto> {
57 public:
58 // Functions used with RunResumeAfterUnstallTest().
60 void StallSessionOnly(SpdyStream* stream) { StallSessionSend(); }
62 void StallStreamOnly(SpdyStream* stream) { StallStreamSend(stream); }
64 void StallSessionStream(SpdyStream* stream) {
65 StallSessionSend();
66 StallStreamSend(stream);
69 void StallStreamSession(SpdyStream* stream) {
70 StallStreamSend(stream);
71 StallSessionSend();
74 void UnstallSessionOnly(SpdyStream* stream, int32 delta_window_size) {
75 UnstallSessionSend(delta_window_size);
78 void UnstallStreamOnly(SpdyStream* stream, int32 delta_window_size) {
79 UnstallStreamSend(stream, delta_window_size);
82 void UnstallSessionStream(SpdyStream* stream, int32 delta_window_size) {
83 UnstallSessionSend(delta_window_size);
84 UnstallStreamSend(stream, delta_window_size);
87 void UnstallStreamSession(SpdyStream* stream, int32 delta_window_size) {
88 UnstallStreamSend(stream, delta_window_size);
89 UnstallSessionSend(delta_window_size);
92 protected:
93 SpdySessionTest()
94 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
95 HttpNetworkSession::NORMAL_SOCKET_POOL)),
96 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
97 HttpNetworkSession::NORMAL_SOCKET_POOL)),
98 spdy_util_(GetParam()),
99 session_deps_(GetParam()),
100 spdy_session_pool_(nullptr),
101 test_url_(kDefaultURL),
102 test_host_port_pair_(HostPortPair::FromURL(test_url_)),
103 key_(test_host_port_pair_,
104 ProxyServer::Direct(),
105 PRIVACY_MODE_DISABLED) {}
107 virtual ~SpdySessionTest() {
108 // Important to restore the per-pool limit first, since the pool limit must
109 // always be greater than group limit, and the tests reduce both limits.
110 ClientSocketPoolManager::set_max_sockets_per_pool(
111 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
112 ClientSocketPoolManager::set_max_sockets_per_group(
113 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
116 void SetUp() override {
117 g_time_delta = base::TimeDelta();
118 session_deps_.net_log = log_.bound().net_log();
121 void CreateNetworkSession() {
122 DCHECK(!http_session_);
123 DCHECK(!spdy_session_pool_);
124 http_session_ =
125 SpdySessionDependencies::SpdyCreateSession(&session_deps_);
126 spdy_session_pool_ = http_session_->spdy_session_pool();
129 void CreateInsecureSpdySession() {
130 DCHECK(!session_);
131 session_ =
132 ::net::CreateInsecureSpdySession(http_session_, key_, log_.bound());
135 void StallSessionSend() {
136 // Reduce the send window size to 0 to stall.
137 while (session_->session_send_window_size_ > 0) {
138 session_->DecreaseSendWindowSize(std::min(
139 kMaxSpdyFrameChunkSize, session_->session_send_window_size_));
143 void UnstallSessionSend(int32 delta_window_size) {
144 session_->IncreaseSendWindowSize(delta_window_size);
147 void StallStreamSend(SpdyStream* stream) {
148 // Reduce the send window size to 0 to stall.
149 while (stream->send_window_size() > 0) {
150 stream->DecreaseSendWindowSize(
151 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
155 void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) {
156 stream->IncreaseSendWindowSize(delta_window_size);
159 void RunResumeAfterUnstallTest(
160 const base::Callback<void(SpdyStream*)>& stall_function,
161 const base::Callback<void(SpdyStream*, int32)>& unstall_function);
163 // Original socket limits. Some tests set these. Safest to always restore
164 // them once each test has been run.
165 int old_max_group_sockets_;
166 int old_max_pool_sockets_;
168 SpdyTestUtil spdy_util_;
169 SpdySessionDependencies session_deps_;
170 scoped_refptr<HttpNetworkSession> http_session_;
171 base::WeakPtr<SpdySession> session_;
172 SpdySessionPool* spdy_session_pool_;
173 GURL test_url_;
174 HostPortPair test_host_port_pair_;
175 SpdySessionKey key_;
176 BoundTestNetLog log_;
179 INSTANTIATE_TEST_CASE_P(NextProto,
180 SpdySessionTest,
181 testing::Values(kProtoSPDY31,
182 kProtoHTTP2));
184 // Try to create a SPDY session that will fail during
185 // initialization. Nothing should blow up.
186 TEST_P(SpdySessionTest, InitialReadError) {
187 CreateNetworkSession();
189 session_ = TryCreateFakeSpdySessionExpectingFailure(spdy_session_pool_, key_,
190 ERR_CONNECTION_CLOSED);
191 EXPECT_TRUE(session_);
192 // Flush the read.
193 base::RunLoop().RunUntilIdle();
194 EXPECT_FALSE(session_);
197 namespace {
199 // A helper class that vends a callback that, when fired, destroys a
200 // given SpdyStreamRequest.
201 class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
202 public:
203 StreamRequestDestroyingCallback() {}
205 ~StreamRequestDestroyingCallback() override {}
207 void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) {
208 request_ = request.Pass();
211 CompletionCallback MakeCallback() {
212 return base::Bind(&StreamRequestDestroyingCallback::OnComplete,
213 base::Unretained(this));
216 private:
217 void OnComplete(int result) {
218 request_.reset();
219 SetResult(result);
222 scoped_ptr<SpdyStreamRequest> request_;
225 } // namespace
227 // Request kInitialMaxConcurrentStreams streams. Request two more
228 // streams, but have the callback for one destroy the second stream
229 // request. Close the session. Nothing should blow up. This is a
230 // regression test for http://crbug.com/250841 .
231 TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
232 session_deps_.host_resolver->set_synchronous_mode(true);
234 MockRead reads[] = {MockRead(ASYNC, 0, 0), };
236 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
237 session_deps_.socket_factory->AddSocketDataProvider(&data);
239 CreateNetworkSession();
240 CreateInsecureSpdySession();
242 // Create the maximum number of concurrent streams.
243 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
244 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
245 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
246 ASSERT_TRUE(spdy_stream != nullptr);
249 SpdyStreamRequest request1;
250 scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest);
252 StreamRequestDestroyingCallback callback1;
253 ASSERT_EQ(
254 ERR_IO_PENDING,
255 request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
256 MEDIUM, BoundNetLog(), callback1.MakeCallback()));
258 // |callback2| is never called.
259 TestCompletionCallback callback2;
260 ASSERT_EQ(ERR_IO_PENDING, request2->StartRequest(
261 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
262 MEDIUM, BoundNetLog(), callback2.callback()));
264 callback1.SetRequestToDestroy(request2.Pass());
266 session_->CloseSessionOnError(ERR_ABORTED, "Aborting session");
268 EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
271 // A session receiving a GOAWAY frame with no active streams should close.
272 TEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
273 session_deps_.host_resolver->set_synchronous_mode(true);
275 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
276 MockRead reads[] = {
277 CreateMockRead(*goaway, 0),
279 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
280 session_deps_.socket_factory->AddSocketDataProvider(&data);
282 CreateNetworkSession();
283 CreateInsecureSpdySession();
285 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
287 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
289 // Read and process the GOAWAY frame.
290 base::RunLoop().RunUntilIdle();
291 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
292 EXPECT_FALSE(session_);
295 // A session receiving a GOAWAY frame immediately with no active
296 // streams should then close.
297 TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
298 session_deps_.host_resolver->set_synchronous_mode(true);
300 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
301 MockRead reads[] = {
302 CreateMockRead(*goaway, 0, SYNCHRONOUS), MockRead(ASYNC, 0, 1) // EOF
304 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
305 session_deps_.socket_factory->AddSocketDataProvider(&data);
307 CreateNetworkSession();
309 session_ = TryCreateInsecureSpdySessionExpectingFailure(
310 http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
311 base::RunLoop().RunUntilIdle();
313 EXPECT_FALSE(session_);
314 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
315 EXPECT_FALSE(data.AllReadDataConsumed());
318 // A session receiving a GOAWAY frame with active streams should close
319 // when the last active stream is closed.
320 TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
321 session_deps_.host_resolver->set_synchronous_mode(true);
323 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
324 MockRead reads[] = {
325 MockRead(ASYNC, ERR_IO_PENDING, 2),
326 CreateMockRead(*goaway, 3),
327 MockRead(ASYNC, ERR_IO_PENDING, 4),
328 MockRead(ASYNC, 0, 5) // EOF
330 scoped_ptr<SpdyFrame> req1(
331 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
332 scoped_ptr<SpdyFrame> req2(
333 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
334 MockWrite writes[] = {
335 CreateMockWrite(*req1, 0),
336 CreateMockWrite(*req2, 1),
338 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
339 session_deps_.socket_factory->AddSocketDataProvider(&data);
341 CreateNetworkSession();
342 CreateInsecureSpdySession();
344 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
346 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
347 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
348 test::StreamDelegateDoNothing delegate1(spdy_stream1);
349 spdy_stream1->SetDelegate(&delegate1);
351 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
352 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
353 test::StreamDelegateDoNothing delegate2(spdy_stream2);
354 spdy_stream2->SetDelegate(&delegate2);
356 scoped_ptr<SpdyHeaderBlock> headers(
357 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
358 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
360 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
361 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
362 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
363 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
365 base::RunLoop().RunUntilIdle();
367 EXPECT_EQ(1u, spdy_stream1->stream_id());
368 EXPECT_EQ(3u, spdy_stream2->stream_id());
370 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
372 // Read and process the GOAWAY frame.
373 data.CompleteRead();
374 base::RunLoop().RunUntilIdle();
376 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
378 EXPECT_FALSE(session_->IsStreamActive(3));
379 EXPECT_FALSE(spdy_stream2);
380 EXPECT_TRUE(session_->IsStreamActive(1));
382 EXPECT_TRUE(session_->IsGoingAway());
384 // Should close the session.
385 spdy_stream1->Close();
386 EXPECT_FALSE(spdy_stream1);
388 EXPECT_TRUE(session_);
389 data.CompleteRead();
390 base::RunLoop().RunUntilIdle();
391 EXPECT_FALSE(session_);
394 // Have a session receive two GOAWAY frames, with the last one causing
395 // the last active stream to be closed. The session should then be
396 // closed after the second GOAWAY frame.
397 TEST_P(SpdySessionTest, GoAwayTwice) {
398 session_deps_.host_resolver->set_synchronous_mode(true);
400 scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
401 scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
402 MockRead reads[] = {
403 MockRead(ASYNC, ERR_IO_PENDING, 2),
404 CreateMockRead(*goaway1, 3),
405 MockRead(ASYNC, ERR_IO_PENDING, 4),
406 CreateMockRead(*goaway2, 5),
407 MockRead(ASYNC, ERR_IO_PENDING, 6),
408 MockRead(ASYNC, 0, 7) // EOF
410 scoped_ptr<SpdyFrame> req1(
411 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
412 scoped_ptr<SpdyFrame> req2(
413 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
414 MockWrite writes[] = {
415 CreateMockWrite(*req1, 0),
416 CreateMockWrite(*req2, 1),
418 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
419 session_deps_.socket_factory->AddSocketDataProvider(&data);
421 CreateNetworkSession();
422 CreateInsecureSpdySession();
424 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
426 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
427 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
428 test::StreamDelegateDoNothing delegate1(spdy_stream1);
429 spdy_stream1->SetDelegate(&delegate1);
431 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
432 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
433 test::StreamDelegateDoNothing delegate2(spdy_stream2);
434 spdy_stream2->SetDelegate(&delegate2);
436 scoped_ptr<SpdyHeaderBlock> headers(
437 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
438 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
440 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
441 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
442 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
443 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
445 base::RunLoop().RunUntilIdle();
447 EXPECT_EQ(1u, spdy_stream1->stream_id());
448 EXPECT_EQ(3u, spdy_stream2->stream_id());
450 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
452 // Read and process the first GOAWAY frame.
453 data.CompleteRead();
454 base::RunLoop().RunUntilIdle();
456 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
458 EXPECT_FALSE(session_->IsStreamActive(3));
459 EXPECT_FALSE(spdy_stream2);
460 EXPECT_TRUE(session_->IsStreamActive(1));
461 EXPECT_TRUE(session_->IsGoingAway());
463 // Read and process the second GOAWAY frame, which should close the
464 // session.
465 data.CompleteRead();
466 base::RunLoop().RunUntilIdle();
467 EXPECT_FALSE(session_);
470 // Have a session with active streams receive a GOAWAY frame and then
471 // close it. It should handle the close properly (i.e., not try to
472 // make itself unavailable in its pool twice).
473 TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
474 session_deps_.host_resolver->set_synchronous_mode(true);
476 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
477 MockRead reads[] = {
478 MockRead(ASYNC, ERR_IO_PENDING, 2),
479 CreateMockRead(*goaway, 3),
480 MockRead(ASYNC, ERR_IO_PENDING, 4),
481 MockRead(ASYNC, 0, 5) // EOF
483 scoped_ptr<SpdyFrame> req1(
484 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
485 scoped_ptr<SpdyFrame> req2(
486 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
487 MockWrite writes[] = {
488 CreateMockWrite(*req1, 0),
489 CreateMockWrite(*req2, 1),
491 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
492 session_deps_.socket_factory->AddSocketDataProvider(&data);
494 CreateNetworkSession();
495 CreateInsecureSpdySession();
497 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
499 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
500 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
501 test::StreamDelegateDoNothing delegate1(spdy_stream1);
502 spdy_stream1->SetDelegate(&delegate1);
504 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
505 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
506 test::StreamDelegateDoNothing delegate2(spdy_stream2);
507 spdy_stream2->SetDelegate(&delegate2);
509 scoped_ptr<SpdyHeaderBlock> headers(
510 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
511 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
513 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
514 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
515 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
516 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
518 base::RunLoop().RunUntilIdle();
520 EXPECT_EQ(1u, spdy_stream1->stream_id());
521 EXPECT_EQ(3u, spdy_stream2->stream_id());
523 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
525 // Read and process the GOAWAY frame.
526 data.CompleteRead();
527 base::RunLoop().RunUntilIdle();
529 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
531 EXPECT_FALSE(session_->IsStreamActive(3));
532 EXPECT_FALSE(spdy_stream2);
533 EXPECT_TRUE(session_->IsStreamActive(1));
534 EXPECT_TRUE(session_->IsGoingAway());
536 session_->CloseSessionOnError(ERR_ABORTED, "Aborting session");
537 EXPECT_FALSE(spdy_stream1);
539 data.CompleteRead();
540 base::RunLoop().RunUntilIdle();
541 EXPECT_FALSE(session_);
544 // Process a joint read buffer which causes the session to begin draining, and
545 // then processes a GOAWAY. The session should gracefully drain. Regression test
546 // for crbug.com/379469
547 TEST_P(SpdySessionTest, GoAwayWhileDraining) {
548 session_deps_.host_resolver->set_synchronous_mode(true);
550 scoped_ptr<SpdyFrame> req(
551 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
552 MockWrite writes[] = {
553 CreateMockWrite(*req, 0),
556 scoped_ptr<SpdyFrame> resp(
557 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
558 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
559 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
560 size_t joint_size = goaway->size() * 2 + body->size();
562 // Compose interleaved |goaway| and |body| frames into a single read.
563 scoped_ptr<char[]> buffer(new char[joint_size]);
565 size_t out = 0;
566 memcpy(&buffer[out], goaway->data(), goaway->size());
567 out += goaway->size();
568 memcpy(&buffer[out], body->data(), body->size());
569 out += body->size();
570 memcpy(&buffer[out], goaway->data(), goaway->size());
571 out += goaway->size();
572 ASSERT_EQ(out, joint_size);
574 SpdyFrame joint_frames(buffer.get(), joint_size, false);
576 MockRead reads[] = {
577 CreateMockRead(*resp, 1), CreateMockRead(joint_frames, 2),
578 MockRead(ASYNC, 0, 3) // EOF
581 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
582 session_deps_.socket_factory->AddSocketDataProvider(&data);
584 CreateNetworkSession();
585 CreateInsecureSpdySession();
587 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
588 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
589 test::StreamDelegateDoNothing delegate(spdy_stream);
590 spdy_stream->SetDelegate(&delegate);
592 scoped_ptr<SpdyHeaderBlock> headers(
593 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
594 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
595 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
597 base::RunLoop().RunUntilIdle();
599 // Stream and session closed gracefully.
600 EXPECT_TRUE(delegate.StreamIsClosed());
601 EXPECT_EQ(OK, delegate.WaitForClose());
602 EXPECT_EQ(kUploadData, delegate.TakeReceivedData());
603 EXPECT_FALSE(session_);
606 // Try to create a stream after receiving a GOAWAY frame. It should
607 // fail.
608 TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
609 session_deps_.host_resolver->set_synchronous_mode(true);
611 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
612 MockRead reads[] = {
613 MockRead(ASYNC, ERR_IO_PENDING, 1),
614 CreateMockRead(*goaway, 2),
615 MockRead(ASYNC, ERR_IO_PENDING, 3),
616 MockRead(ASYNC, 0, 4) // EOF
618 scoped_ptr<SpdyFrame> req(
619 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
620 MockWrite writes[] = {
621 CreateMockWrite(*req, 0),
623 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
624 session_deps_.socket_factory->AddSocketDataProvider(&data);
626 CreateNetworkSession();
627 CreateInsecureSpdySession();
629 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
631 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
632 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
633 test::StreamDelegateDoNothing delegate(spdy_stream);
634 spdy_stream->SetDelegate(&delegate);
636 scoped_ptr<SpdyHeaderBlock> headers(
637 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
638 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
639 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
641 base::RunLoop().RunUntilIdle();
643 EXPECT_EQ(1u, spdy_stream->stream_id());
645 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
647 // Read and process the GOAWAY frame.
648 data.CompleteRead();
649 base::RunLoop().RunUntilIdle();
651 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
652 EXPECT_TRUE(session_->IsStreamActive(1));
654 SpdyStreamRequest stream_request;
655 int rv = stream_request.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_,
656 test_url_, MEDIUM, BoundNetLog(),
657 CompletionCallback());
658 EXPECT_EQ(ERR_FAILED, rv);
660 EXPECT_TRUE(session_);
661 data.CompleteRead();
662 base::RunLoop().RunUntilIdle();
663 EXPECT_FALSE(session_);
666 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
667 // the stream being refused.
668 TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
669 session_deps_.host_resolver->set_synchronous_mode(true);
671 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
672 scoped_ptr<SpdyFrame> push(
673 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kDefaultURL));
674 MockRead reads[] = {
675 MockRead(ASYNC, ERR_IO_PENDING, 1),
676 CreateMockRead(*goaway, 2),
677 MockRead(ASYNC, ERR_IO_PENDING, 3),
678 CreateMockRead(*push, 4),
679 MockRead(ASYNC, 0, 6) // EOF
681 scoped_ptr<SpdyFrame> req(
682 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
683 scoped_ptr<SpdyFrame> rst(
684 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
685 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5)};
686 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
687 session_deps_.socket_factory->AddSocketDataProvider(&data);
689 CreateNetworkSession();
690 CreateInsecureSpdySession();
692 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
694 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
695 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
696 test::StreamDelegateDoNothing delegate(spdy_stream);
697 spdy_stream->SetDelegate(&delegate);
699 scoped_ptr<SpdyHeaderBlock> headers(
700 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
701 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
702 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
704 base::RunLoop().RunUntilIdle();
706 EXPECT_EQ(1u, spdy_stream->stream_id());
708 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
710 // Read and process the GOAWAY frame.
711 data.CompleteRead();
712 base::RunLoop().RunUntilIdle();
714 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
715 EXPECT_TRUE(session_->IsStreamActive(1));
717 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
718 // and EOF.
719 data.CompleteRead();
720 base::RunLoop().RunUntilIdle();
721 EXPECT_FALSE(session_);
724 // A session observing a network change with active streams should close
725 // when the last active stream is closed.
726 TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
727 session_deps_.host_resolver->set_synchronous_mode(true);
729 MockRead reads[] = {
730 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
732 scoped_ptr<SpdyFrame> req1(
733 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
734 MockWrite writes[] = {
735 CreateMockWrite(*req1, 0),
737 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
738 session_deps_.socket_factory->AddSocketDataProvider(&data);
740 CreateNetworkSession();
741 CreateInsecureSpdySession();
743 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
745 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
746 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
747 test::StreamDelegateDoNothing delegate(spdy_stream);
748 spdy_stream->SetDelegate(&delegate);
750 scoped_ptr<SpdyHeaderBlock> headers(
751 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
753 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
754 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
756 base::RunLoop().RunUntilIdle();
758 EXPECT_EQ(1u, spdy_stream->stream_id());
760 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
762 spdy_session_pool_->OnIPAddressChanged();
764 // The SpdySessionPool behavior differs based on how the OSs reacts to
765 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
766 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
767 // For OSs where the TCP connections will close upon relevant network
768 // changes, SpdySessionPool doesn't need to force them to close, so in these
769 // cases verify the session has become unavailable but remains open and the
770 // pre-existing stream is still active.
771 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
773 EXPECT_TRUE(session_->IsGoingAway());
775 EXPECT_TRUE(session_->IsStreamActive(1));
777 // Should close the session.
778 spdy_stream->Close();
779 #endif
780 EXPECT_FALSE(spdy_stream);
782 data.CompleteRead();
783 base::RunLoop().RunUntilIdle();
784 EXPECT_FALSE(session_);
787 TEST_P(SpdySessionTest, ClientPing) {
788 session_deps_.enable_ping = true;
789 session_deps_.host_resolver->set_synchronous_mode(true);
791 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
792 MockRead reads[] = {
793 CreateMockRead(*read_ping, 1),
794 MockRead(ASYNC, ERR_IO_PENDING, 2),
795 MockRead(ASYNC, 0, 3) // EOF
797 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
798 MockWrite writes[] = {
799 CreateMockWrite(*write_ping, 0),
801 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
802 session_deps_.socket_factory->AddSocketDataProvider(&data);
804 CreateNetworkSession();
805 CreateInsecureSpdySession();
807 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
808 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
809 ASSERT_TRUE(spdy_stream1.get() != nullptr);
810 test::StreamDelegateSendImmediate delegate(spdy_stream1, nullptr);
811 spdy_stream1->SetDelegate(&delegate);
813 base::TimeTicks before_ping_time = base::TimeTicks::Now();
815 session_->set_connection_at_risk_of_loss_time(
816 base::TimeDelta::FromSeconds(-1));
817 session_->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
819 session_->SendPrefacePingIfNoneInFlight();
821 base::RunLoop().RunUntilIdle();
823 session_->CheckPingStatus(before_ping_time);
825 EXPECT_EQ(0, session_->pings_in_flight());
826 EXPECT_GE(session_->next_ping_id(), 1U);
827 EXPECT_FALSE(session_->check_ping_status_pending());
828 EXPECT_GE(session_->last_activity_time(), before_ping_time);
830 data.CompleteRead();
831 base::RunLoop().RunUntilIdle();
833 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
835 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
836 EXPECT_FALSE(session_);
839 TEST_P(SpdySessionTest, ServerPing) {
840 session_deps_.host_resolver->set_synchronous_mode(true);
842 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
843 MockRead reads[] = {
844 CreateMockRead(*read_ping),
845 MockRead(SYNCHRONOUS, 0, 0) // EOF
847 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
848 MockWrite writes[] = {
849 CreateMockWrite(*write_ping),
851 StaticSocketDataProvider data(
852 reads, arraysize(reads), writes, arraysize(writes));
853 session_deps_.socket_factory->AddSocketDataProvider(&data);
855 CreateNetworkSession();
856 CreateInsecureSpdySession();
858 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
859 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
860 ASSERT_TRUE(spdy_stream1.get() != nullptr);
861 test::StreamDelegateSendImmediate delegate(spdy_stream1, nullptr);
862 spdy_stream1->SetDelegate(&delegate);
864 // Flush the read completion task.
865 base::RunLoop().RunUntilIdle();
867 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
869 EXPECT_FALSE(session_);
870 EXPECT_FALSE(spdy_stream1);
873 // Cause a ping to be sent out while producing a write. The write loop
874 // should handle this properly, i.e. another DoWriteLoop task should
875 // not be posted. This is a regression test for
876 // http://crbug.com/261043 .
877 TEST_P(SpdySessionTest, PingAndWriteLoop) {
878 session_deps_.enable_ping = true;
879 session_deps_.time_func = TheNearFuture;
881 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
882 scoped_ptr<SpdyFrame> req(
883 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
884 MockWrite writes[] = {
885 CreateMockWrite(*req, 0),
886 CreateMockWrite(*write_ping, 1),
889 MockRead reads[] = {
890 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
893 session_deps_.host_resolver->set_synchronous_mode(true);
895 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
896 session_deps_.socket_factory->AddSocketDataProvider(&data);
898 CreateNetworkSession();
899 CreateInsecureSpdySession();
901 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
902 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
903 test::StreamDelegateDoNothing delegate(spdy_stream);
904 spdy_stream->SetDelegate(&delegate);
906 scoped_ptr<SpdyHeaderBlock> headers(
907 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
908 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
910 // Shift time so that a ping will be sent out.
911 g_time_delta = base::TimeDelta::FromSeconds(11);
913 base::RunLoop().RunUntilIdle();
914 session_->CloseSessionOnError(ERR_ABORTED, "Aborting");
916 data.CompleteRead();
917 base::RunLoop().RunUntilIdle();
918 EXPECT_FALSE(session_);
921 TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
922 const SpdyStreamId kLastStreamId = 0x7fffffff;
923 session_deps_.host_resolver->set_synchronous_mode(true);
925 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
926 // fixed to allow for two stream ID assignments, and three concurrent
927 // streams. Four streams are started, and two are activated. Verify the
928 // session goes away, and that the created (but not activated) and
929 // stalled streams are aborted. Also verify the activated streams complete,
930 // at which point the session closes.
932 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
933 nullptr, 0, false, kLastStreamId - 2, MEDIUM, true));
934 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
935 nullptr, 0, false, kLastStreamId, MEDIUM, true));
937 MockWrite writes[] = {
938 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
941 scoped_ptr<SpdyFrame> resp1(
942 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId - 2));
943 scoped_ptr<SpdyFrame> resp2(
944 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId));
946 scoped_ptr<SpdyFrame> body1(
947 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
948 scoped_ptr<SpdyFrame> body2(
949 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
951 MockRead reads[] = {
952 CreateMockRead(*resp1, 2),
953 CreateMockRead(*resp2, 3),
954 MockRead(ASYNC, ERR_IO_PENDING, 4),
955 CreateMockRead(*body1, 5),
956 CreateMockRead(*body2, 6),
957 MockRead(ASYNC, 0, 7) // EOF
960 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
961 session_deps_.socket_factory->AddSocketDataProvider(&data);
963 CreateNetworkSession();
964 CreateInsecureSpdySession();
966 // Fix stream_hi_water_mark_ to allow for two stream activations.
967 session_->stream_hi_water_mark_ = kLastStreamId - 2;
968 // Fix max_concurrent_streams to allow for three stream creations.
969 session_->max_concurrent_streams_ = 3;
971 // Create three streams synchronously, and begin a fourth (which is stalled).
972 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
973 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
974 test::StreamDelegateDoNothing delegate1(stream1);
975 stream1->SetDelegate(&delegate1);
977 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
978 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
979 test::StreamDelegateDoNothing delegate2(stream2);
980 stream2->SetDelegate(&delegate2);
982 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
983 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
984 test::StreamDelegateDoNothing delegate3(stream3);
985 stream3->SetDelegate(&delegate3);
987 SpdyStreamRequest request4;
988 TestCompletionCallback callback4;
989 EXPECT_EQ(
990 ERR_IO_PENDING,
991 request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_,
992 MEDIUM, BoundNetLog(), callback4.callback()));
994 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
995 EXPECT_EQ(0u, session_->num_active_streams());
996 EXPECT_EQ(3u, session_->num_created_streams());
997 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(MEDIUM));
999 // Activate stream 1. One ID remains available.
1000 stream1->SendRequestHeaders(
1001 scoped_ptr<SpdyHeaderBlock>(
1002 spdy_util_.ConstructGetHeaderBlock(kDefaultURL)),
1003 NO_MORE_DATA_TO_SEND);
1004 base::RunLoop().RunUntilIdle();
1006 EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1007 EXPECT_EQ(1u, session_->num_active_streams());
1008 EXPECT_EQ(2u, session_->num_created_streams());
1009 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(MEDIUM));
1011 // Activate stream 2. ID space is exhausted.
1012 stream2->SendRequestHeaders(
1013 scoped_ptr<SpdyHeaderBlock>(
1014 spdy_util_.ConstructGetHeaderBlock(kDefaultURL)),
1015 NO_MORE_DATA_TO_SEND);
1016 base::RunLoop().RunUntilIdle();
1018 // Active streams remain active.
1019 EXPECT_EQ(kLastStreamId, stream2->stream_id());
1020 EXPECT_EQ(2u, session_->num_active_streams());
1022 // Session is going away. Created and stalled streams were aborted.
1023 EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session_->availability_state_);
1024 EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose());
1025 EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult());
1026 EXPECT_EQ(0u, session_->num_created_streams());
1027 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(MEDIUM));
1029 // Read responses on remaining active streams.
1030 data.CompleteRead();
1031 base::RunLoop().RunUntilIdle();
1032 EXPECT_EQ(OK, delegate1.WaitForClose());
1033 EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1034 EXPECT_EQ(OK, delegate2.WaitForClose());
1035 EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1037 // Session was destroyed.
1038 EXPECT_FALSE(session_);
1041 // Verifies that an unstalled pending stream creation racing with a new stream
1042 // creation doesn't violate the maximum stream concurrency. Regression test for
1043 // crbug.com/373858.
1044 TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) {
1045 session_deps_.host_resolver->set_synchronous_mode(true);
1047 MockRead reads[] = {
1048 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1051 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1052 session_deps_.socket_factory->AddSocketDataProvider(&data);
1054 CreateNetworkSession();
1055 CreateInsecureSpdySession();
1057 // Fix max_concurrent_streams to allow for one open stream.
1058 session_->max_concurrent_streams_ = 1;
1060 // Create two streams: one synchronously, and one which stalls.
1061 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1062 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1064 SpdyStreamRequest request2;
1065 TestCompletionCallback callback2;
1066 EXPECT_EQ(
1067 ERR_IO_PENDING,
1068 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_,
1069 MEDIUM, BoundNetLog(), callback2.callback()));
1071 EXPECT_EQ(1u, session_->num_created_streams());
1072 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(MEDIUM));
1074 // Cancel the first stream. A callback to unstall the second stream was
1075 // posted. Don't run it yet.
1076 stream1->Cancel();
1078 EXPECT_EQ(0u, session_->num_created_streams());
1079 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(MEDIUM));
1081 // Create a third stream prior to the second stream's callback.
1082 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1083 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1085 EXPECT_EQ(1u, session_->num_created_streams());
1086 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(MEDIUM));
1088 // Now run the message loop. The unstalled stream will re-stall itself.
1089 base::RunLoop().RunUntilIdle();
1090 EXPECT_EQ(1u, session_->num_created_streams());
1091 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(MEDIUM));
1093 // Cancel the third stream and run the message loop. Verify that the second
1094 // stream creation now completes.
1095 stream3->Cancel();
1096 base::RunLoop().RunUntilIdle();
1098 EXPECT_EQ(1u, session_->num_created_streams());
1099 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(MEDIUM));
1100 EXPECT_EQ(OK, callback2.WaitForResult());
1103 TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
1104 session_deps_.host_resolver->set_synchronous_mode(true);
1105 session_deps_.time_func = TheNearFuture;
1107 scoped_ptr<SpdyFrame> req(
1108 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
1109 scoped_ptr<SpdyFrame> rst(
1110 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
1111 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5)};
1113 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
1114 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
1115 scoped_ptr<SpdyFrame> push_a_body(
1116 spdy_util_.ConstructSpdyBodyFrame(2, false));
1117 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1118 // iterators inside. See http://crbug.com/443490
1119 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
1120 nullptr, 0, 4, 1, "http://www.example.org/0.dat"));
1121 MockRead reads[] = {
1122 CreateMockRead(*push_a, 1),
1123 CreateMockRead(*push_a_body, 2),
1124 MockRead(ASYNC, ERR_IO_PENDING, 3),
1125 CreateMockRead(*push_b, 4),
1126 MockRead(ASYNC, ERR_IO_PENDING, 6),
1127 MockRead(ASYNC, 0, 7) // EOF
1130 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1131 session_deps_.socket_factory->AddSocketDataProvider(&data);
1133 CreateNetworkSession();
1134 CreateInsecureSpdySession();
1136 // Process the principal request, and the first push stream request & body.
1137 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1138 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1139 test::StreamDelegateDoNothing delegate(spdy_stream);
1140 spdy_stream->SetDelegate(&delegate);
1142 scoped_ptr<SpdyHeaderBlock> headers(
1143 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1144 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1146 base::RunLoop().RunUntilIdle();
1148 // Verify that there is one unclaimed push stream.
1149 EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
1150 SpdySession::PushedStreamMap::iterator iter =
1151 session_->unclaimed_pushed_streams_.find(
1152 GURL("http://www.example.org/a.dat"));
1153 EXPECT_TRUE(session_->unclaimed_pushed_streams_.end() != iter);
1155 if (session_->flow_control_state_ ==
1156 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1157 // Unclaimed push body consumed bytes from the session window.
1158 EXPECT_EQ(
1159 SpdySession::GetDefaultInitialWindowSize(GetParam()) - kUploadDataSize,
1160 session_->session_recv_window_size_);
1161 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
1164 // Shift time to expire the push stream. Read the second SYN_STREAM,
1165 // and verify a RST_STREAM was written.
1166 g_time_delta = base::TimeDelta::FromSeconds(301);
1167 data.CompleteRead();
1168 base::RunLoop().RunUntilIdle();
1170 // Verify that the second pushed stream evicted the first pushed stream.
1171 EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
1172 iter = session_->unclaimed_pushed_streams_.find(
1173 GURL("http://www.example.org/0.dat"));
1174 EXPECT_TRUE(session_->unclaimed_pushed_streams_.end() != iter);
1176 if (session_->flow_control_state_ ==
1177 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1178 // Verify that the session window reclaimed the evicted stream body.
1179 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
1180 session_->session_recv_window_size_);
1181 EXPECT_EQ(kUploadDataSize, session_->session_unacked_recv_window_bytes_);
1184 // Read and process EOF.
1185 EXPECT_TRUE(session_);
1186 data.CompleteRead();
1187 base::RunLoop().RunUntilIdle();
1188 EXPECT_FALSE(session_);
1191 TEST_P(SpdySessionTest, FailedPing) {
1192 session_deps_.host_resolver->set_synchronous_mode(true);
1194 MockRead reads[] = {
1195 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1197 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
1198 scoped_ptr<SpdyFrame> goaway(
1199 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping."));
1200 MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)};
1202 StaticSocketDataProvider data(
1203 reads, arraysize(reads), writes, arraysize(writes));
1204 session_deps_.socket_factory->AddSocketDataProvider(&data);
1206 CreateNetworkSession();
1207 CreateInsecureSpdySession();
1209 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1210 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1211 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1212 test::StreamDelegateSendImmediate delegate(spdy_stream1, nullptr);
1213 spdy_stream1->SetDelegate(&delegate);
1215 session_->set_connection_at_risk_of_loss_time(
1216 base::TimeDelta::FromSeconds(0));
1217 session_->set_hung_interval(base::TimeDelta::FromSeconds(0));
1219 // Send a PING frame.
1220 session_->WritePingFrame(1, false);
1221 EXPECT_LT(0, session_->pings_in_flight());
1222 EXPECT_GE(session_->next_ping_id(), 1U);
1223 EXPECT_TRUE(session_->check_ping_status_pending());
1225 // Assert session is not closed.
1226 EXPECT_TRUE(session_->IsAvailable());
1227 EXPECT_LT(0u,
1228 session_->num_active_streams() + session_->num_created_streams());
1229 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1231 // We set last time we have received any data in 1 sec less than now.
1232 // CheckPingStatus will trigger timeout because hung interval is zero.
1233 base::TimeTicks now = base::TimeTicks::Now();
1234 session_->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
1235 session_->CheckPingStatus(now);
1236 base::RunLoop().RunUntilIdle();
1238 EXPECT_FALSE(session_);
1239 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1240 EXPECT_FALSE(spdy_stream1);
1243 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1244 // settings frame increasing the max concurrent streams by 1. Make
1245 // sure nothing blows up. This is a regression test for
1246 // http://crbug.com/57331 .
1247 TEST_P(SpdySessionTest, OnSettings) {
1248 session_deps_.host_resolver->set_synchronous_mode(true);
1250 const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1252 int seq = 0;
1253 std::vector<MockWrite> writes;
1254 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1255 if (GetParam() == kProtoHTTP2) {
1256 writes.push_back(CreateMockWrite(*settings_ack, ++seq));
1259 SettingsMap new_settings;
1260 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1261 new_settings[kSpdySettingsIds] =
1262 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1263 scoped_ptr<SpdyFrame> settings_frame(
1264 spdy_util_.ConstructSpdySettings(new_settings));
1265 MockRead reads[] = {
1266 CreateMockRead(*settings_frame, 0),
1267 MockRead(ASYNC, ERR_IO_PENDING, ++seq),
1268 MockRead(ASYNC, 0, ++seq),
1271 SequencedSocketData data(reads, arraysize(reads), vector_as_array(&writes),
1272 writes.size());
1273 session_deps_.socket_factory->AddSocketDataProvider(&data);
1275 CreateNetworkSession();
1276 CreateInsecureSpdySession();
1278 // Create the maximum number of concurrent streams.
1279 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1280 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1281 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1282 ASSERT_TRUE(spdy_stream != nullptr);
1285 StreamReleaserCallback stream_releaser;
1286 SpdyStreamRequest request;
1287 ASSERT_EQ(ERR_IO_PENDING,
1288 request.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1289 MEDIUM, BoundNetLog(),
1290 stream_releaser.MakeCallback(&request)));
1292 base::RunLoop().RunUntilIdle();
1294 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1296 data.CompleteRead();
1297 base::RunLoop().RunUntilIdle();
1298 EXPECT_FALSE(session_);
1300 EXPECT_TRUE(data.AllWriteDataConsumed());
1301 EXPECT_TRUE(data.AllReadDataConsumed());
1304 // Start with a persisted value for max concurrent streams. Receive a
1305 // settings frame increasing the max concurrent streams by 1 and which
1306 // also clears the persisted data. Verify that persisted data is
1307 // correct.
1308 TEST_P(SpdySessionTest, ClearSettings) {
1309 if (spdy_util_.spdy_version() >= HTTP2) {
1310 // HTTP/2 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1311 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in HTTP/2.
1312 return;
1314 session_deps_.host_resolver->set_synchronous_mode(true);
1316 SettingsMap new_settings;
1317 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1318 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1319 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1320 scoped_ptr<SpdyFrame> settings_frame(
1321 spdy_util_.ConstructSpdySettings(new_settings));
1322 uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1323 test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1324 MockRead reads[] = {
1325 CreateMockRead(*settings_frame, 0),
1326 MockRead(ASYNC, ERR_IO_PENDING, 1),
1327 MockRead(ASYNC, 0, 2),
1330 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
1331 session_deps_.socket_factory->AddSocketDataProvider(&data);
1333 CreateNetworkSession();
1335 // Initialize the SpdySetting with the default.
1336 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1337 test_host_port_pair_,
1338 SETTINGS_MAX_CONCURRENT_STREAMS,
1339 SETTINGS_FLAG_PLEASE_PERSIST,
1340 kInitialMaxConcurrentStreams);
1342 EXPECT_FALSE(
1343 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1344 test_host_port_pair_).empty());
1346 CreateInsecureSpdySession();
1348 // Create the maximum number of concurrent streams.
1349 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1350 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1351 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1352 ASSERT_TRUE(spdy_stream != nullptr);
1355 StreamReleaserCallback stream_releaser;
1357 SpdyStreamRequest request;
1358 ASSERT_EQ(ERR_IO_PENDING,
1359 request.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1360 MEDIUM, BoundNetLog(),
1361 stream_releaser.MakeCallback(&request)));
1363 base::RunLoop().RunUntilIdle();
1365 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1367 // Make sure that persisted data is cleared.
1368 EXPECT_TRUE(
1369 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1370 test_host_port_pair_).empty());
1372 // Make sure session's max_concurrent_streams is correct.
1373 EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1374 session_->max_concurrent_streams());
1376 data.CompleteRead();
1377 base::RunLoop().RunUntilIdle();
1378 EXPECT_FALSE(session_);
1381 // Start with max concurrent streams set to 1. Request two streams.
1382 // When the first completes, have the callback close its stream, which
1383 // should trigger the second stream creation. Then cancel that one
1384 // immediately. Don't crash. This is a regression test for
1385 // http://crbug.com/63532 .
1386 TEST_P(SpdySessionTest, CancelPendingCreateStream) {
1387 session_deps_.host_resolver->set_synchronous_mode(true);
1389 MockRead reads[] = {
1390 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1393 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1394 session_deps_.socket_factory->AddSocketDataProvider(&data);
1396 CreateNetworkSession();
1398 // Initialize the SpdySetting with 1 max concurrent streams.
1399 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1400 test_host_port_pair_,
1401 SETTINGS_MAX_CONCURRENT_STREAMS,
1402 SETTINGS_FLAG_PLEASE_PERSIST,
1405 CreateInsecureSpdySession();
1407 // Leave room for only one more stream to be created.
1408 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1409 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1410 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1411 ASSERT_TRUE(spdy_stream != nullptr);
1414 // Create 2 more streams. First will succeed. Second will be pending.
1415 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1416 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1417 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1419 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1420 // a valgrind error if the callback is invoked when it's not supposed to be.
1421 scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
1423 SpdyStreamRequest request;
1424 ASSERT_EQ(ERR_IO_PENDING,
1425 request.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
1426 MEDIUM, BoundNetLog(), callback->callback()));
1428 // Release the first one, this will allow the second to be created.
1429 spdy_stream1->Cancel();
1430 EXPECT_FALSE(spdy_stream1);
1432 request.CancelRequest();
1433 callback.reset();
1435 // Should not crash when running the pending callback.
1436 base::RunLoop().RunUntilIdle();
1439 TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
1440 session_deps_.host_resolver->set_synchronous_mode(true);
1442 MockRead reads[] = {
1443 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1446 SettingsMap settings;
1447 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1448 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
1449 scoped_ptr<SpdyFrame> settings_frame(
1450 spdy_util_.ConstructSpdySettings(settings));
1451 std::vector<MockWrite> writes;
1452 if (GetParam() == kProtoHTTP2) {
1453 writes.push_back(
1454 MockWrite(ASYNC,
1455 kHttp2ConnectionHeaderPrefix,
1456 kHttp2ConnectionHeaderPrefixSize));
1458 writes.push_back(CreateMockWrite(*settings_frame));
1460 SettingsMap server_settings;
1461 const uint32 initial_max_concurrent_streams = 1;
1462 server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1463 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1464 initial_max_concurrent_streams);
1465 scoped_ptr<SpdyFrame> server_settings_frame(
1466 spdy_util_.ConstructSpdySettings(server_settings));
1467 if (GetParam() <= kProtoSPDY31) {
1468 writes.push_back(CreateMockWrite(*server_settings_frame));
1471 StaticSocketDataProvider data(reads, arraysize(reads),
1472 vector_as_array(&writes), writes.size());
1473 session_deps_.socket_factory->AddSocketDataProvider(&data);
1475 CreateNetworkSession();
1477 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1478 test_host_port_pair_,
1479 SETTINGS_MAX_CONCURRENT_STREAMS,
1480 SETTINGS_FLAG_PLEASE_PERSIST,
1481 initial_max_concurrent_streams);
1483 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1484 pool_peer.SetEnableSendingInitialData(true);
1486 CreateInsecureSpdySession();
1488 base::RunLoop().RunUntilIdle();
1489 EXPECT_TRUE(data.AllWriteDataConsumed());
1492 TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
1493 CreateNetworkSession();
1495 base::WeakPtr<HttpServerProperties> test_http_server_properties =
1496 spdy_session_pool_->http_server_properties();
1497 SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
1498 test_http_server_properties->SetSpdySetting(
1499 test_host_port_pair_,
1500 SETTINGS_MAX_CONCURRENT_STREAMS,
1501 SETTINGS_FLAG_PLEASE_PERSIST,
1503 EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
1504 test_host_port_pair_).size());
1505 spdy_session_pool_->OnIPAddressChanged();
1506 EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
1507 test_host_port_pair_).size());
1510 TEST_P(SpdySessionTest, Initialize) {
1511 session_deps_.host_resolver->set_synchronous_mode(true);
1513 MockRead reads[] = {
1514 MockRead(ASYNC, 0, 0) // EOF
1517 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1518 session_deps_.socket_factory->AddSocketDataProvider(&data);
1520 CreateNetworkSession();
1521 CreateInsecureSpdySession();
1522 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1524 // Flush the read completion task.
1525 base::RunLoop().RunUntilIdle();
1527 TestNetLogEntry::List entries;
1528 log_.GetEntries(&entries);
1529 EXPECT_LT(0u, entries.size());
1531 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1532 int pos = ExpectLogContainsSomewhere(
1533 entries, 0, NetLog::TYPE_HTTP2_SESSION_INITIALIZED, NetLog::PHASE_NONE);
1534 EXPECT_LT(0, pos);
1536 TestNetLogEntry entry = entries[pos];
1537 NetLog::Source socket_source;
1538 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1539 &socket_source));
1540 EXPECT_TRUE(socket_source.IsValid());
1541 EXPECT_NE(log_.bound().source().id, socket_source.id);
1544 TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
1545 session_deps_.host_resolver->set_synchronous_mode(true);
1547 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
1548 MockRead reads[] = {
1549 CreateMockRead(*goaway),
1550 MockRead(SYNCHRONOUS, 0, 0) // EOF
1553 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1554 session_deps_.socket_factory->AddSocketDataProvider(&data);
1556 CreateNetworkSession();
1557 CreateInsecureSpdySession();
1558 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1560 // Flush the read completion task.
1561 base::RunLoop().RunUntilIdle();
1563 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1564 EXPECT_FALSE(session_);
1566 // Check that the NetLog was filled reasonably.
1567 TestNetLogEntry::List entries;
1568 log_.GetEntries(&entries);
1569 EXPECT_LT(0u, entries.size());
1571 // Check that we logged SPDY_SESSION_CLOSE correctly.
1572 int pos = ExpectLogContainsSomewhere(
1573 entries, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE, NetLog::PHASE_NONE);
1575 if (pos < static_cast<int>(entries.size())) {
1576 TestNetLogEntry entry = entries[pos];
1577 int error_code = 0;
1578 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1579 EXPECT_EQ(OK, error_code);
1580 } else {
1581 ADD_FAILURE();
1585 TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1586 session_deps_.host_resolver->set_synchronous_mode(true);
1588 MockRead reads[] = {
1589 MockRead(SYNCHRONOUS, 0, 0) // EOF
1592 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
1593 session_deps_.socket_factory->AddSocketDataProvider(&data);
1595 CreateNetworkSession();
1596 CreateInsecureSpdySession();
1597 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1599 // Flush the read completion task.
1600 base::RunLoop().RunUntilIdle();
1602 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1603 EXPECT_FALSE(session_);
1605 // Check that the NetLog was filled reasonably.
1606 TestNetLogEntry::List entries;
1607 log_.GetEntries(&entries);
1608 EXPECT_LT(0u, entries.size());
1610 // Check that we logged SPDY_SESSION_CLOSE correctly.
1611 int pos = ExpectLogContainsSomewhere(
1612 entries, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE, NetLog::PHASE_NONE);
1614 if (pos < static_cast<int>(entries.size())) {
1615 TestNetLogEntry entry = entries[pos];
1616 int error_code = 0;
1617 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1618 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1619 } else {
1620 ADD_FAILURE();
1624 TEST_P(SpdySessionTest, SynCompressionHistograms) {
1625 session_deps_.enable_compression = true;
1627 scoped_ptr<SpdyFrame> req(
1628 spdy_util_.ConstructSpdyGet(nullptr, 0, true, 1, MEDIUM, true));
1629 MockWrite writes[] = {
1630 CreateMockWrite(*req, 0),
1632 MockRead reads[] = {
1633 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
1635 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1636 session_deps_.socket_factory->AddSocketDataProvider(&data);
1638 CreateNetworkSession();
1639 CreateInsecureSpdySession();
1641 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1642 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1643 test::StreamDelegateDoNothing delegate(spdy_stream);
1644 spdy_stream->SetDelegate(&delegate);
1646 scoped_ptr<SpdyHeaderBlock> headers(
1647 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1648 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1649 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1651 // Write request headers & capture resulting histogram update.
1652 base::HistogramTester histogram_tester;
1654 base::RunLoop().RunUntilIdle();
1655 // Regression test of compression performance under the request fixture.
1656 switch (spdy_util_.spdy_version()) {
1657 case SPDY3:
1658 histogram_tester.ExpectBucketCount(
1659 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1660 break;
1661 case HTTP2:
1662 histogram_tester.ExpectBucketCount(
1663 "Net.SpdySynStreamCompressionPercentage", 81, 1);
1664 break;
1665 default:
1666 NOTREACHED();
1669 // Read and process EOF.
1670 EXPECT_TRUE(session_);
1671 data.CompleteRead();
1672 base::RunLoop().RunUntilIdle();
1673 EXPECT_FALSE(session_);
1676 // Queue up a low-priority SYN_STREAM followed by a high-priority
1677 // one. The high priority one should still send first and receive
1678 // first.
1679 TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1680 // Construct the request.
1681 scoped_ptr<SpdyFrame> req_highest(
1682 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, HIGHEST, true));
1683 scoped_ptr<SpdyFrame> req_lowest(
1684 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST, true));
1685 MockWrite writes[] = {
1686 CreateMockWrite(*req_highest, 0),
1687 CreateMockWrite(*req_lowest, 1),
1690 scoped_ptr<SpdyFrame> resp_highest(
1691 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
1692 scoped_ptr<SpdyFrame> body_highest(
1693 spdy_util_.ConstructSpdyBodyFrame(1, true));
1694 scoped_ptr<SpdyFrame> resp_lowest(
1695 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
1696 scoped_ptr<SpdyFrame> body_lowest(
1697 spdy_util_.ConstructSpdyBodyFrame(3, true));
1698 MockRead reads[] = {
1699 CreateMockRead(*resp_highest, 2),
1700 CreateMockRead(*body_highest, 3),
1701 CreateMockRead(*resp_lowest, 4),
1702 CreateMockRead(*body_lowest, 5),
1703 MockRead(ASYNC, 0, 6) // EOF
1706 session_deps_.host_resolver->set_synchronous_mode(true);
1708 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1709 session_deps_.socket_factory->AddSocketDataProvider(&data);
1711 CreateNetworkSession();
1712 CreateInsecureSpdySession();
1714 base::WeakPtr<SpdyStream> spdy_stream_lowest = CreateStreamSynchronously(
1715 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
1716 ASSERT_TRUE(spdy_stream_lowest);
1717 EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1718 test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1719 spdy_stream_lowest->SetDelegate(&delegate_lowest);
1721 base::WeakPtr<SpdyStream> spdy_stream_highest =
1722 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
1723 test_url_, HIGHEST, BoundNetLog());
1724 ASSERT_TRUE(spdy_stream_highest);
1725 EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1726 test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1727 spdy_stream_highest->SetDelegate(&delegate_highest);
1729 // Queue the lower priority one first.
1731 scoped_ptr<SpdyHeaderBlock> headers_lowest(
1732 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1733 spdy_stream_lowest->SendRequestHeaders(
1734 headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1735 EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1737 scoped_ptr<SpdyHeaderBlock> headers_highest(
1738 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1739 spdy_stream_highest->SendRequestHeaders(
1740 headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1741 EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1743 base::RunLoop().RunUntilIdle();
1745 EXPECT_FALSE(spdy_stream_lowest);
1746 EXPECT_FALSE(spdy_stream_highest);
1747 EXPECT_EQ(3u, delegate_lowest.stream_id());
1748 EXPECT_EQ(1u, delegate_highest.stream_id());
1751 TEST_P(SpdySessionTest, CancelStream) {
1752 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1753 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1754 scoped_ptr<SpdyFrame> req2(
1755 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
1756 MockWrite writes[] = {
1757 CreateMockWrite(*req2, 0),
1760 scoped_ptr<SpdyFrame> resp2(
1761 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
1762 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1763 MockRead reads[] = {
1764 CreateMockRead(*resp2, 1),
1765 MockRead(ASYNC, ERR_IO_PENDING, 2),
1766 CreateMockRead(*body2, 3),
1767 MockRead(ASYNC, 0, 4) // EOF
1770 session_deps_.host_resolver->set_synchronous_mode(true);
1772 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1773 session_deps_.socket_factory->AddSocketDataProvider(&data);
1775 CreateNetworkSession();
1776 CreateInsecureSpdySession();
1778 base::WeakPtr<SpdyStream> spdy_stream1 =
1779 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
1780 test_url_, HIGHEST, BoundNetLog());
1781 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1782 EXPECT_EQ(0u, spdy_stream1->stream_id());
1783 test::StreamDelegateDoNothing delegate1(spdy_stream1);
1784 spdy_stream1->SetDelegate(&delegate1);
1786 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
1787 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
1788 ASSERT_TRUE(spdy_stream2.get() != nullptr);
1789 EXPECT_EQ(0u, spdy_stream2->stream_id());
1790 test::StreamDelegateDoNothing delegate2(spdy_stream2);
1791 spdy_stream2->SetDelegate(&delegate2);
1793 scoped_ptr<SpdyHeaderBlock> headers(
1794 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1795 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1796 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1798 scoped_ptr<SpdyHeaderBlock> headers2(
1799 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1800 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1801 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1803 EXPECT_EQ(0u, spdy_stream1->stream_id());
1805 spdy_stream1->Cancel();
1806 EXPECT_FALSE(spdy_stream1);
1808 EXPECT_EQ(0u, delegate1.stream_id());
1810 base::RunLoop().RunUntilIdle();
1812 EXPECT_EQ(0u, delegate1.stream_id());
1813 EXPECT_EQ(1u, delegate2.stream_id());
1815 spdy_stream2->Cancel();
1816 EXPECT_FALSE(spdy_stream2);
1819 // Create two streams that are set to re-close themselves on close,
1820 // and then close the session. Nothing should blow up. Also a
1821 // regression test for http://crbug.com/139518 .
1822 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1823 session_deps_.host_resolver->set_synchronous_mode(true);
1826 // No actual data will be sent.
1827 MockWrite writes[] = {
1828 MockWrite(ASYNC, 0, 1) // EOF
1831 MockRead reads[] = {
1832 MockRead(ASYNC, 0, 0) // EOF
1834 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1835 session_deps_.socket_factory->AddSocketDataProvider(&data);
1837 CreateNetworkSession();
1838 CreateInsecureSpdySession();
1840 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1841 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, HIGHEST, BoundNetLog());
1842 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1843 EXPECT_EQ(0u, spdy_stream1->stream_id());
1845 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
1846 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, LOWEST, BoundNetLog());
1847 ASSERT_TRUE(spdy_stream2.get() != nullptr);
1848 EXPECT_EQ(0u, spdy_stream2->stream_id());
1850 test::ClosingDelegate delegate1(spdy_stream1);
1851 spdy_stream1->SetDelegate(&delegate1);
1853 test::ClosingDelegate delegate2(spdy_stream2);
1854 spdy_stream2->SetDelegate(&delegate2);
1856 scoped_ptr<SpdyHeaderBlock> headers(
1857 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1858 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1859 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1861 scoped_ptr<SpdyHeaderBlock> headers2(
1862 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1863 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1864 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1866 // Ensure that the streams have not yet been activated and assigned an id.
1867 EXPECT_EQ(0u, spdy_stream1->stream_id());
1868 EXPECT_EQ(0u, spdy_stream2->stream_id());
1870 // Ensure we don't crash while closing the session.
1871 session_->CloseSessionOnError(ERR_ABORTED, std::string());
1873 EXPECT_FALSE(spdy_stream1);
1874 EXPECT_FALSE(spdy_stream2);
1876 EXPECT_TRUE(delegate1.StreamIsClosed());
1877 EXPECT_TRUE(delegate2.StreamIsClosed());
1879 base::RunLoop().RunUntilIdle();
1880 EXPECT_FALSE(session_);
1883 // Create two streams that are set to close each other on close, and
1884 // then close the session. Nothing should blow up.
1885 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
1886 session_deps_.host_resolver->set_synchronous_mode(true);
1888 SequencedSocketData data(nullptr, 0, nullptr, 0);
1889 session_deps_.socket_factory->AddSocketDataProvider(&data);
1891 CreateNetworkSession();
1892 CreateInsecureSpdySession();
1894 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1895 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, HIGHEST, BoundNetLog());
1896 ASSERT_TRUE(spdy_stream1);
1897 EXPECT_EQ(0u, spdy_stream1->stream_id());
1899 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
1900 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, LOWEST, BoundNetLog());
1901 ASSERT_TRUE(spdy_stream2);
1902 EXPECT_EQ(0u, spdy_stream2->stream_id());
1904 // Make |spdy_stream1| close |spdy_stream2|.
1905 test::ClosingDelegate delegate1(spdy_stream2);
1906 spdy_stream1->SetDelegate(&delegate1);
1908 // Make |spdy_stream2| close |spdy_stream1|.
1909 test::ClosingDelegate delegate2(spdy_stream1);
1910 spdy_stream2->SetDelegate(&delegate2);
1912 scoped_ptr<SpdyHeaderBlock> headers(
1913 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1914 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1915 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1917 scoped_ptr<SpdyHeaderBlock> headers2(
1918 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1919 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1920 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1922 // Ensure that the streams have not yet been activated and assigned an id.
1923 EXPECT_EQ(0u, spdy_stream1->stream_id());
1924 EXPECT_EQ(0u, spdy_stream2->stream_id());
1926 // Ensure we don't crash while closing the session.
1927 session_->CloseSessionOnError(ERR_ABORTED, std::string());
1929 EXPECT_FALSE(spdy_stream1);
1930 EXPECT_FALSE(spdy_stream2);
1932 EXPECT_TRUE(delegate1.StreamIsClosed());
1933 EXPECT_TRUE(delegate2.StreamIsClosed());
1935 base::RunLoop().RunUntilIdle();
1936 EXPECT_FALSE(session_);
1939 // Create two streams that are set to re-close themselves on close,
1940 // activate them, and then close the session. Nothing should blow up.
1941 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
1942 session_deps_.host_resolver->set_synchronous_mode(true);
1944 scoped_ptr<SpdyFrame> req1(
1945 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
1946 scoped_ptr<SpdyFrame> req2(
1947 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
1948 MockWrite writes[] = {
1949 CreateMockWrite(*req1, 0),
1950 CreateMockWrite(*req2, 1),
1953 MockRead reads[] = {
1954 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
1957 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1958 session_deps_.socket_factory->AddSocketDataProvider(&data);
1960 CreateNetworkSession();
1961 CreateInsecureSpdySession();
1963 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
1964 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1965 ASSERT_TRUE(spdy_stream1.get() != nullptr);
1966 EXPECT_EQ(0u, spdy_stream1->stream_id());
1968 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
1969 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
1970 ASSERT_TRUE(spdy_stream2.get() != nullptr);
1971 EXPECT_EQ(0u, spdy_stream2->stream_id());
1973 test::ClosingDelegate delegate1(spdy_stream1);
1974 spdy_stream1->SetDelegate(&delegate1);
1976 test::ClosingDelegate delegate2(spdy_stream2);
1977 spdy_stream2->SetDelegate(&delegate2);
1979 scoped_ptr<SpdyHeaderBlock> headers(
1980 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1981 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1982 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1984 scoped_ptr<SpdyHeaderBlock> headers2(
1985 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
1986 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1987 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1989 // Ensure that the streams have not yet been activated and assigned an id.
1990 EXPECT_EQ(0u, spdy_stream1->stream_id());
1991 EXPECT_EQ(0u, spdy_stream2->stream_id());
1993 base::RunLoop().RunUntilIdle();
1995 EXPECT_EQ(1u, spdy_stream1->stream_id());
1996 EXPECT_EQ(3u, spdy_stream2->stream_id());
1998 // Ensure we don't crash while closing the session.
1999 session_->CloseSessionOnError(ERR_ABORTED, std::string());
2001 EXPECT_FALSE(spdy_stream1);
2002 EXPECT_FALSE(spdy_stream2);
2004 EXPECT_TRUE(delegate1.StreamIsClosed());
2005 EXPECT_TRUE(delegate2.StreamIsClosed());
2007 EXPECT_TRUE(session_);
2008 data.CompleteRead();
2009 base::RunLoop().RunUntilIdle();
2010 EXPECT_FALSE(session_);
2013 // Create two streams that are set to close each other on close,
2014 // activate them, and then close the session. Nothing should blow up.
2015 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2016 session_deps_.host_resolver->set_synchronous_mode(true);
2018 scoped_ptr<SpdyFrame> req1(
2019 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2020 scoped_ptr<SpdyFrame> req2(
2021 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
2022 MockWrite writes[] = {
2023 CreateMockWrite(*req1, 0),
2024 CreateMockWrite(*req2, 1),
2027 MockRead reads[] = {
2028 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
2031 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2032 session_deps_.socket_factory->AddSocketDataProvider(&data);
2034 CreateNetworkSession();
2035 CreateInsecureSpdySession();
2037 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2038 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2039 ASSERT_TRUE(spdy_stream1);
2040 EXPECT_EQ(0u, spdy_stream1->stream_id());
2042 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
2043 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2044 ASSERT_TRUE(spdy_stream2);
2045 EXPECT_EQ(0u, spdy_stream2->stream_id());
2047 // Make |spdy_stream1| close |spdy_stream2|.
2048 test::ClosingDelegate delegate1(spdy_stream2);
2049 spdy_stream1->SetDelegate(&delegate1);
2051 // Make |spdy_stream2| close |spdy_stream1|.
2052 test::ClosingDelegate delegate2(spdy_stream1);
2053 spdy_stream2->SetDelegate(&delegate2);
2055 scoped_ptr<SpdyHeaderBlock> headers(
2056 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2057 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2058 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2060 scoped_ptr<SpdyHeaderBlock> headers2(
2061 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2062 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2063 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2065 // Ensure that the streams have not yet been activated and assigned an id.
2066 EXPECT_EQ(0u, spdy_stream1->stream_id());
2067 EXPECT_EQ(0u, spdy_stream2->stream_id());
2069 base::RunLoop().RunUntilIdle();
2071 EXPECT_EQ(1u, spdy_stream1->stream_id());
2072 EXPECT_EQ(3u, spdy_stream2->stream_id());
2074 // Ensure we don't crash while closing the session.
2075 session_->CloseSessionOnError(ERR_ABORTED, std::string());
2077 EXPECT_FALSE(spdy_stream1);
2078 EXPECT_FALSE(spdy_stream2);
2080 EXPECT_TRUE(delegate1.StreamIsClosed());
2081 EXPECT_TRUE(delegate2.StreamIsClosed());
2083 EXPECT_TRUE(session_);
2084 data.CompleteRead();
2085 base::RunLoop().RunUntilIdle();
2086 EXPECT_FALSE(session_);
2089 // Delegate that closes a given session when the stream is closed.
2090 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2091 public:
2092 SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2093 const base::WeakPtr<SpdySession>& session_to_close)
2094 : StreamDelegateDoNothing(stream),
2095 session_to_close_(session_to_close) {}
2097 ~SessionClosingDelegate() override {}
2099 void OnClose(int status) override {
2100 session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2103 private:
2104 base::WeakPtr<SpdySession> session_to_close_;
2107 // Close an activated stream that closes its session. Nothing should
2108 // blow up. This is a regression test for https://crbug.com/263691.
2109 TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2110 session_deps_.host_resolver->set_synchronous_mode(true);
2112 scoped_ptr<SpdyFrame> req(
2113 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2114 scoped_ptr<SpdyFrame> rst(
2115 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2116 scoped_ptr<SpdyFrame> goaway(
2117 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2118 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2119 // despite being queued second.
2120 MockWrite writes[] = {
2121 CreateMockWrite(*req, 0),
2122 CreateMockWrite(*goaway, 1),
2123 CreateMockWrite(*rst, 3),
2126 MockRead reads[] = {
2127 MockRead(ASYNC, 0, 2) // EOF
2129 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2130 session_deps_.socket_factory->AddSocketDataProvider(&data);
2132 CreateNetworkSession();
2133 CreateInsecureSpdySession();
2135 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
2136 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2137 ASSERT_TRUE(spdy_stream.get() != nullptr);
2138 EXPECT_EQ(0u, spdy_stream->stream_id());
2140 SessionClosingDelegate delegate(spdy_stream, session_);
2141 spdy_stream->SetDelegate(&delegate);
2143 scoped_ptr<SpdyHeaderBlock> headers(
2144 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2145 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2146 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2148 EXPECT_EQ(0u, spdy_stream->stream_id());
2150 base::RunLoop().RunUntilIdle();
2152 EXPECT_EQ(1u, spdy_stream->stream_id());
2154 // Ensure we don't crash while closing the stream (which closes the
2155 // session).
2156 spdy_stream->Cancel();
2158 EXPECT_FALSE(spdy_stream);
2159 EXPECT_TRUE(delegate.StreamIsClosed());
2161 // Write the RST_STREAM & GOAWAY.
2162 base::RunLoop().RunUntilIdle();
2163 EXPECT_TRUE(data.AllWriteDataConsumed());
2164 EXPECT_TRUE(data.AllReadDataConsumed());
2167 TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2168 session_deps_.host_resolver->set_synchronous_mode(true);
2170 SequencedSocketData data(nullptr, 0, nullptr, 0);
2171 session_deps_.socket_factory->AddSocketDataProvider(&data);
2173 // Load a cert that is valid for:
2174 // www.example.org
2175 // mail.example.org
2176 // www.example.com
2177 base::FilePath certs_dir = GetTestCertsDirectory();
2178 scoped_refptr<X509Certificate> test_cert(
2179 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2180 ASSERT_NE(static_cast<X509Certificate*>(nullptr), test_cert.get());
2182 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2183 ssl.cert = test_cert;
2184 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2186 CreateNetworkSession();
2188 session_ = CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2190 EXPECT_TRUE(session_->VerifyDomainAuthentication("www.example.org"));
2191 EXPECT_TRUE(session_->VerifyDomainAuthentication("mail.example.org"));
2192 EXPECT_TRUE(session_->VerifyDomainAuthentication("mail.example.com"));
2193 EXPECT_FALSE(session_->VerifyDomainAuthentication("mail.google.com"));
2196 TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2197 session_deps_.host_resolver->set_synchronous_mode(true);
2199 SequencedSocketData data(nullptr, 0, nullptr, 0);
2200 session_deps_.socket_factory->AddSocketDataProvider(&data);
2202 // Load a cert that is valid for:
2203 // www.example.org
2204 // mail.example.org
2205 // www.example.com
2206 base::FilePath certs_dir = GetTestCertsDirectory();
2207 scoped_refptr<X509Certificate> test_cert(
2208 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2209 ASSERT_NE(static_cast<X509Certificate*>(nullptr), test_cert.get());
2211 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2212 ssl.channel_id_sent = true;
2213 ssl.cert = test_cert;
2214 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2216 CreateNetworkSession();
2218 session_ = CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2220 EXPECT_TRUE(session_->VerifyDomainAuthentication("www.example.org"));
2221 EXPECT_TRUE(session_->VerifyDomainAuthentication("mail.example.org"));
2222 EXPECT_FALSE(session_->VerifyDomainAuthentication("mail.example.com"));
2223 EXPECT_FALSE(session_->VerifyDomainAuthentication("mail.google.com"));
2226 TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2227 // TODO(rtenneti): Define a helper class/methods and move the common code in
2228 // this file.
2229 SettingsMap new_settings;
2230 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2231 const uint32 max_concurrent_streams = 1;
2232 new_settings[kSpdySettingsIds1] =
2233 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2235 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
2236 scoped_ptr<SpdyFrame> req1(
2237 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
2238 scoped_ptr<SpdyFrame> req2(
2239 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST, true));
2240 scoped_ptr<SpdyFrame> req3(
2241 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 5, LOWEST, true));
2242 MockWrite writes[] = {
2243 CreateMockWrite(*settings_ack, 1),
2244 CreateMockWrite(*req1, 2),
2245 CreateMockWrite(*req2, 5),
2246 CreateMockWrite(*req3, 8),
2249 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2250 // streams to 1.
2251 scoped_ptr<SpdyFrame> settings_frame(
2252 spdy_util_.ConstructSpdySettings(new_settings));
2254 scoped_ptr<SpdyFrame> resp1(
2255 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2256 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2258 scoped_ptr<SpdyFrame> resp2(
2259 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
2260 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2262 scoped_ptr<SpdyFrame> resp3(
2263 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 5));
2264 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2266 MockRead reads[] = {
2267 CreateMockRead(*settings_frame, 0),
2268 CreateMockRead(*resp1, 3),
2269 CreateMockRead(*body1, 4),
2270 CreateMockRead(*resp2, 6),
2271 CreateMockRead(*body2, 7),
2272 CreateMockRead(*resp3, 9),
2273 CreateMockRead(*body3, 10),
2274 MockRead(ASYNC, ERR_IO_PENDING, 11),
2275 MockRead(ASYNC, 0, 12) // EOF
2278 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2279 session_deps_.socket_factory->AddSocketDataProvider(&data);
2281 CreateNetworkSession();
2282 CreateInsecureSpdySession();
2284 // Read the settings frame.
2285 base::RunLoop().RunUntilIdle();
2287 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2288 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
2289 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2290 EXPECT_EQ(0u, spdy_stream1->stream_id());
2291 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2292 spdy_stream1->SetDelegate(&delegate1);
2294 TestCompletionCallback callback2;
2295 SpdyStreamRequest request2;
2296 ASSERT_EQ(
2297 ERR_IO_PENDING,
2298 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_,
2299 LOWEST, BoundNetLog(), callback2.callback()));
2301 TestCompletionCallback callback3;
2302 SpdyStreamRequest request3;
2303 ASSERT_EQ(
2304 ERR_IO_PENDING,
2305 request3.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_,
2306 LOWEST, BoundNetLog(), callback3.callback()));
2308 EXPECT_EQ(0u, session_->num_active_streams());
2309 EXPECT_EQ(1u, session_->num_created_streams());
2310 EXPECT_EQ(2u, session_->pending_create_stream_queue_size(LOWEST));
2312 scoped_ptr<SpdyHeaderBlock> headers(
2313 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2314 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2315 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2317 // Run until 1st stream is activated and then closed.
2318 EXPECT_EQ(0u, delegate1.stream_id());
2319 base::RunLoop().RunUntilIdle();
2320 EXPECT_FALSE(spdy_stream1);
2321 EXPECT_EQ(1u, delegate1.stream_id());
2323 EXPECT_EQ(0u, session_->num_active_streams());
2324 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(LOWEST));
2326 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2327 // create the 2nd stream.
2328 base::RunLoop().RunUntilIdle();
2330 EXPECT_EQ(0u, session_->num_active_streams());
2331 EXPECT_EQ(1u, session_->num_created_streams());
2332 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(LOWEST));
2334 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2335 test::StreamDelegateDoNothing delegate2(stream2);
2336 stream2->SetDelegate(&delegate2);
2337 scoped_ptr<SpdyHeaderBlock> headers2(
2338 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2339 stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2340 EXPECT_TRUE(stream2->HasUrlFromHeaders());
2342 // Run until 2nd stream is activated and then closed.
2343 EXPECT_EQ(0u, delegate2.stream_id());
2344 base::RunLoop().RunUntilIdle();
2345 EXPECT_FALSE(stream2);
2346 EXPECT_EQ(3u, delegate2.stream_id());
2348 EXPECT_EQ(0u, session_->num_active_streams());
2349 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2351 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2352 // create the 3rd stream.
2353 base::RunLoop().RunUntilIdle();
2355 EXPECT_EQ(0u, session_->num_active_streams());
2356 EXPECT_EQ(1u, session_->num_created_streams());
2357 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2359 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2360 test::StreamDelegateDoNothing delegate3(stream3);
2361 stream3->SetDelegate(&delegate3);
2362 scoped_ptr<SpdyHeaderBlock> headers3(
2363 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2364 stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2365 EXPECT_TRUE(stream3->HasUrlFromHeaders());
2367 // Run until 2nd stream is activated and then closed.
2368 EXPECT_EQ(0u, delegate3.stream_id());
2369 base::RunLoop().RunUntilIdle();
2370 EXPECT_FALSE(stream3);
2371 EXPECT_EQ(5u, delegate3.stream_id());
2373 EXPECT_EQ(0u, session_->num_active_streams());
2374 EXPECT_EQ(0u, session_->num_created_streams());
2375 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2377 data.CompleteRead();
2378 base::RunLoop().RunUntilIdle();
2381 TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2382 session_deps_.host_resolver->set_synchronous_mode(true);
2384 MockRead reads[] = {
2385 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2388 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
2389 session_deps_.socket_factory->AddSocketDataProvider(&data);
2391 CreateNetworkSession();
2392 CreateInsecureSpdySession();
2394 // Leave room for only one more stream to be created.
2395 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2396 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
2397 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2398 ASSERT_TRUE(spdy_stream != nullptr);
2401 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2402 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, LOWEST, BoundNetLog());
2403 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2404 EXPECT_EQ(0u, spdy_stream1->stream_id());
2406 TestCompletionCallback callback2;
2407 SpdyStreamRequest request2;
2408 ASSERT_EQ(ERR_IO_PENDING, request2.StartRequest(
2409 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
2410 LOWEST, BoundNetLog(), callback2.callback()));
2412 TestCompletionCallback callback3;
2413 SpdyStreamRequest request3;
2414 ASSERT_EQ(ERR_IO_PENDING, request3.StartRequest(
2415 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_,
2416 LOWEST, BoundNetLog(), callback3.callback()));
2418 EXPECT_EQ(0u, session_->num_active_streams());
2419 EXPECT_EQ(kInitialMaxConcurrentStreams, session_->num_created_streams());
2420 EXPECT_EQ(2u, session_->pending_create_stream_queue_size(LOWEST));
2422 // Cancel the first stream; this will allow the second stream to be created.
2423 EXPECT_TRUE(spdy_stream1);
2424 spdy_stream1->Cancel();
2425 EXPECT_FALSE(spdy_stream1);
2427 EXPECT_EQ(OK, callback2.WaitForResult());
2428 EXPECT_EQ(0u, session_->num_active_streams());
2429 EXPECT_EQ(kInitialMaxConcurrentStreams, session_->num_created_streams());
2430 EXPECT_EQ(1u, session_->pending_create_stream_queue_size(LOWEST));
2432 // Cancel the second stream; this will allow the third stream to be created.
2433 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2434 spdy_stream2->Cancel();
2435 EXPECT_FALSE(spdy_stream2);
2437 EXPECT_EQ(OK, callback3.WaitForResult());
2438 EXPECT_EQ(0u, session_->num_active_streams());
2439 EXPECT_EQ(kInitialMaxConcurrentStreams, session_->num_created_streams());
2440 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2442 // Cancel the third stream.
2443 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2444 spdy_stream3->Cancel();
2445 EXPECT_FALSE(spdy_stream3);
2446 EXPECT_EQ(0u, session_->num_active_streams());
2447 EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session_->num_created_streams());
2448 EXPECT_EQ(0u, session_->pending_create_stream_queue_size(LOWEST));
2451 // Test that SpdySession::DoReadLoop reads data from the socket
2452 // without yielding. This test makes 32k - 1 bytes of data available
2453 // on the socket for reading. It then verifies that it has read all
2454 // the available data without yielding.
2455 TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2456 session_deps_.host_resolver->set_synchronous_mode(true);
2458 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2460 scoped_ptr<SpdyFrame> req1(
2461 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2462 MockWrite writes[] = {
2463 CreateMockWrite(*req1, 0),
2466 // Build buffer of size kYieldAfterBytesRead / 4
2467 // (-spdy_data_frame_size).
2468 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
2469 const int kPayloadSize =
2470 kYieldAfterBytesRead / 4 - framer.GetControlFrameHeaderSize();
2471 TestDataStream test_stream;
2472 scoped_refptr<IOBuffer> payload(new IOBuffer(kPayloadSize));
2473 char* payload_data = payload->data();
2474 test_stream.GetBytes(payload_data, kPayloadSize);
2476 scoped_ptr<SpdyFrame> partial_data_frame(
2477 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2478 scoped_ptr<SpdyFrame> finish_data_frame(
2479 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2481 scoped_ptr<SpdyFrame> resp1(
2482 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2484 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2485 // bytes.
2486 MockRead reads[] = {
2487 CreateMockRead(*resp1, 1),
2488 MockRead(ASYNC, ERR_IO_PENDING, 2),
2489 CreateMockRead(*partial_data_frame, 3),
2490 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2491 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2492 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2493 MockRead(ASYNC, 0, 7) // EOF
2496 // Create SpdySession and SpdyStream and send the request.
2497 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2498 session_deps_.socket_factory->AddSocketDataProvider(&data);
2500 CreateNetworkSession();
2501 CreateInsecureSpdySession();
2503 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2504 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2505 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2506 EXPECT_EQ(0u, spdy_stream1->stream_id());
2507 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2508 spdy_stream1->SetDelegate(&delegate1);
2510 scoped_ptr<SpdyHeaderBlock> headers1(
2511 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2512 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2513 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2515 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2516 // post a task.
2517 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2519 // Run until 1st read.
2520 EXPECT_EQ(0u, delegate1.stream_id());
2521 base::RunLoop().RunUntilIdle();
2522 EXPECT_EQ(1u, delegate1.stream_id());
2523 EXPECT_EQ(0u, observer.executed_count());
2525 // Read all the data and verify SpdySession::DoReadLoop has not
2526 // posted a task.
2527 data.CompleteRead();
2528 base::RunLoop().RunUntilIdle();
2529 EXPECT_FALSE(spdy_stream1);
2531 // Verify task observer's executed_count is zero, which indicates DoRead read
2532 // all the available data.
2533 EXPECT_EQ(0u, observer.executed_count());
2534 EXPECT_TRUE(data.AllWriteDataConsumed());
2535 EXPECT_TRUE(data.AllReadDataConsumed());
2538 // Test that SpdySession::DoReadLoop yields if more than
2539 // |kYieldAfterDurationMilliseconds| has passed. This test uses a mock time
2540 // function that makes the response frame look very slow to read.
2541 TEST_P(SpdySessionTest, TestYieldingSlowReads) {
2542 session_deps_.host_resolver->set_synchronous_mode(true);
2543 session_deps_.time_func = SlowReads;
2545 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2547 scoped_ptr<SpdyFrame> req1(
2548 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2549 MockWrite writes[] = {
2550 CreateMockWrite(*req1, 0),
2553 scoped_ptr<SpdyFrame> resp1(
2554 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2556 MockRead reads[] = {
2557 CreateMockRead(*resp1, 1), MockRead(ASYNC, 0, 2) // EOF
2560 // Create SpdySession and SpdyStream and send the request.
2561 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2562 session_deps_.socket_factory->AddSocketDataProvider(&data);
2564 CreateNetworkSession();
2565 CreateInsecureSpdySession();
2567 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2568 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2569 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2570 EXPECT_EQ(0u, spdy_stream1->stream_id());
2571 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2572 spdy_stream1->SetDelegate(&delegate1);
2574 scoped_ptr<SpdyHeaderBlock> headers1(
2575 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2576 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2577 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2579 // Set up the TaskObserver to verify that SpdySession::DoReadLoop posts a
2580 // task.
2581 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2583 EXPECT_EQ(0u, delegate1.stream_id());
2584 EXPECT_EQ(0u, observer.executed_count());
2586 // Read all the data and verify that SpdySession::DoReadLoop has posted a
2587 // task.
2588 base::RunLoop().RunUntilIdle();
2589 EXPECT_EQ(1u, delegate1.stream_id());
2590 EXPECT_FALSE(spdy_stream1);
2592 // Verify task that the observer's executed_count is 1, which indicates DoRead
2593 // has posted only one task and thus yielded though there is data available
2594 // for it to read.
2595 EXPECT_EQ(1u, observer.executed_count());
2596 EXPECT_TRUE(data.AllWriteDataConsumed());
2597 EXPECT_TRUE(data.AllReadDataConsumed());
2600 // Test that SpdySession::DoReadLoop yields while reading the
2601 // data. This test makes 32k + 1 bytes of data available on the socket
2602 // for reading. It then verifies that DoRead has yielded even though
2603 // there is data available for it to read (i.e, socket()->Read didn't
2604 // return ERR_IO_PENDING during socket reads).
2605 TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2606 session_deps_.host_resolver->set_synchronous_mode(true);
2608 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2610 scoped_ptr<SpdyFrame> req1(
2611 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2612 MockWrite writes[] = {
2613 CreateMockWrite(*req1, 0),
2616 // Build buffer of size kYieldAfterBytesRead / 4
2617 // (-spdy_data_frame_size).
2618 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
2619 const int kPayloadSize =
2620 kYieldAfterBytesRead / 4 - framer.GetControlFrameHeaderSize();
2621 TestDataStream test_stream;
2622 scoped_refptr<IOBuffer> payload(new IOBuffer(kPayloadSize));
2623 char* payload_data = payload->data();
2624 test_stream.GetBytes(payload_data, kPayloadSize);
2626 scoped_ptr<SpdyFrame> partial_data_frame(
2627 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2628 scoped_ptr<SpdyFrame> finish_data_frame(
2629 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2631 scoped_ptr<SpdyFrame> resp1(
2632 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2634 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2635 MockRead reads[] = {
2636 CreateMockRead(*resp1, 1),
2637 MockRead(ASYNC, ERR_IO_PENDING, 2),
2638 CreateMockRead(*partial_data_frame, 3),
2639 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2640 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2641 CreateMockRead(*partial_data_frame, 6, SYNCHRONOUS),
2642 CreateMockRead(*finish_data_frame, 7, SYNCHRONOUS),
2643 MockRead(ASYNC, 0, 8) // EOF
2646 // Create SpdySession and SpdyStream and send the request.
2647 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2648 session_deps_.socket_factory->AddSocketDataProvider(&data);
2650 CreateNetworkSession();
2651 CreateInsecureSpdySession();
2653 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2654 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2655 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2656 EXPECT_EQ(0u, spdy_stream1->stream_id());
2657 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2658 spdy_stream1->SetDelegate(&delegate1);
2660 scoped_ptr<SpdyHeaderBlock> headers1(
2661 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2662 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2663 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2665 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a task.
2666 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2668 // Run until 1st read.
2669 EXPECT_EQ(0u, delegate1.stream_id());
2670 base::RunLoop().RunUntilIdle();
2671 EXPECT_EQ(1u, delegate1.stream_id());
2672 EXPECT_EQ(0u, observer.executed_count());
2674 // Read all the data and verify SpdySession::DoReadLoop has posted a task.
2675 data.CompleteRead();
2676 base::RunLoop().RunUntilIdle();
2677 EXPECT_FALSE(spdy_stream1);
2679 // Verify task observer's executed_count is 1, which indicates DoRead has
2680 // posted only one task and thus yielded though there is data available for it
2681 // to read.
2682 EXPECT_EQ(1u, observer.executed_count());
2683 EXPECT_TRUE(data.AllWriteDataConsumed());
2684 EXPECT_TRUE(data.AllReadDataConsumed());
2687 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2688 // + async, by doing the following MockReads.
2690 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2691 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2693 // The above reads 26K synchronously. Since that is less that 32K, we
2694 // will attempt to read again. However, that DoRead() will return
2695 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2696 // yield. When we come back, DoRead() will read the results from the
2697 // async read, and rest of the data synchronously.
2698 TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2699 session_deps_.host_resolver->set_synchronous_mode(true);
2701 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2703 scoped_ptr<SpdyFrame> req1(
2704 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2705 MockWrite writes[] = {
2706 CreateMockWrite(*req1, 0),
2709 // Build buffer of size kYieldAfterBytesRead / 4
2710 // (-spdy_data_frame_size).
2711 ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
2712 TestDataStream test_stream;
2713 const int kEightKPayloadSize =
2714 kYieldAfterBytesRead / 4 - framer.GetControlFrameHeaderSize();
2715 scoped_refptr<IOBuffer> eightk_payload(new IOBuffer(kEightKPayloadSize));
2716 char* eightk_payload_data = eightk_payload->data();
2717 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2719 // Build buffer of 2k size.
2720 TestDataStream test_stream2;
2721 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2722 scoped_refptr<IOBuffer> twok_payload(new IOBuffer(kTwoKPayloadSize));
2723 char* twok_payload_data = twok_payload->data();
2724 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2726 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2727 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2728 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2729 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2730 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2731 1, "h", 1, DATA_FLAG_FIN));
2733 scoped_ptr<SpdyFrame> resp1(
2734 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2736 MockRead reads[] = {
2737 CreateMockRead(*resp1, 1),
2738 MockRead(ASYNC, ERR_IO_PENDING, 2),
2739 CreateMockRead(*eightk_data_frame, 3),
2740 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2741 CreateMockRead(*eightk_data_frame, 5, SYNCHRONOUS),
2742 CreateMockRead(*twok_data_frame, 6, SYNCHRONOUS),
2743 CreateMockRead(*eightk_data_frame, 7, ASYNC),
2744 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2745 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2746 CreateMockRead(*eightk_data_frame, 10, SYNCHRONOUS),
2747 CreateMockRead(*twok_data_frame, 11, SYNCHRONOUS),
2748 CreateMockRead(*finish_data_frame, 12, SYNCHRONOUS),
2749 MockRead(ASYNC, 0, 13) // EOF
2752 // Create SpdySession and SpdyStream and send the request.
2753 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2754 session_deps_.socket_factory->AddSocketDataProvider(&data);
2756 CreateNetworkSession();
2757 CreateInsecureSpdySession();
2759 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2760 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2761 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2762 EXPECT_EQ(0u, spdy_stream1->stream_id());
2763 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2764 spdy_stream1->SetDelegate(&delegate1);
2766 scoped_ptr<SpdyHeaderBlock> headers1(
2767 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2768 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2769 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2771 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2772 // posting of tasks.
2773 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2775 // Run until 1st read.
2776 EXPECT_EQ(0u, delegate1.stream_id());
2777 base::RunLoop().RunUntilIdle();
2778 EXPECT_EQ(1u, delegate1.stream_id());
2779 EXPECT_EQ(0u, observer.executed_count());
2781 // Read all the data and verify SpdySession::DoReadLoop has posted a
2782 // task.
2783 data.CompleteRead();
2784 base::RunLoop().RunUntilIdle();
2785 EXPECT_FALSE(spdy_stream1);
2787 // Verify task observer's executed_count is 1, which indicates DoRead has
2788 // posted only one task and thus yielded though there is data available for
2789 // it to read.
2790 EXPECT_EQ(1u, observer.executed_count());
2791 EXPECT_TRUE(data.AllWriteDataConsumed());
2792 EXPECT_TRUE(data.AllReadDataConsumed());
2795 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2796 // nothing blows up.
2797 TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
2798 session_deps_.host_resolver->set_synchronous_mode(true);
2800 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2802 scoped_ptr<SpdyFrame> req1(
2803 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
2804 MockWrite writes[] = {
2805 CreateMockWrite(*req1, 0),
2808 scoped_ptr<SpdyFrame> resp1(
2809 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
2810 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2811 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
2813 MockRead reads[] = {
2814 CreateMockRead(*resp1, 1),
2815 MockRead(ASYNC, ERR_IO_PENDING, 2),
2816 CreateMockRead(*body1, 3),
2817 CreateMockRead(*goaway, 4),
2820 // Create SpdySession and SpdyStream and send the request.
2821 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2822 session_deps_.socket_factory->AddSocketDataProvider(&data);
2824 CreateNetworkSession();
2825 CreateInsecureSpdySession();
2827 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
2828 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
2829 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2830 spdy_stream1->SetDelegate(&delegate1);
2831 ASSERT_TRUE(spdy_stream1.get() != nullptr);
2832 EXPECT_EQ(0u, spdy_stream1->stream_id());
2834 scoped_ptr<SpdyHeaderBlock> headers1(
2835 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
2836 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2837 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2839 // Run until 1st read.
2840 EXPECT_EQ(0u, spdy_stream1->stream_id());
2841 base::RunLoop().RunUntilIdle();
2842 EXPECT_EQ(1u, spdy_stream1->stream_id());
2844 // Run until GoAway.
2845 data.CompleteRead();
2846 base::RunLoop().RunUntilIdle();
2847 EXPECT_FALSE(spdy_stream1);
2848 EXPECT_TRUE(data.AllWriteDataConsumed());
2849 EXPECT_TRUE(data.AllReadDataConsumed());
2850 EXPECT_FALSE(session_);
2853 // Within this framework, a SpdySession should be initialized with
2854 // flow control disabled for protocol version 2, with flow control
2855 // enabled only for streams for protocol version 3, and with flow
2856 // control enabled for streams and sessions for higher versions.
2857 TEST_P(SpdySessionTest, ProtocolNegotiation) {
2858 session_deps_.host_resolver->set_synchronous_mode(true);
2860 MockRead reads[] = {
2861 MockRead(SYNCHRONOUS, 0, 0) // EOF
2863 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
2864 session_deps_.socket_factory->AddSocketDataProvider(&data);
2866 CreateNetworkSession();
2867 session_ = CreateFakeSpdySession(spdy_session_pool_, key_);
2869 EXPECT_EQ(spdy_util_.spdy_version(),
2870 session_->buffered_spdy_framer_->protocol_version());
2871 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
2872 session_->flow_control_state());
2873 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
2874 session_->session_send_window_size_);
2875 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
2876 session_->session_recv_window_size_);
2877 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
2880 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2881 // pointers to the idle session are currently held.
2882 TEST_P(SpdySessionTest, CloseOneIdleConnection) {
2883 ClientSocketPoolManager::set_max_sockets_per_group(
2884 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2885 ClientSocketPoolManager::set_max_sockets_per_pool(
2886 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2888 MockRead reads[] = {
2889 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2891 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
2892 session_deps_.socket_factory->AddSocketDataProvider(&data);
2893 session_deps_.socket_factory->AddSocketDataProvider(&data);
2895 CreateNetworkSession();
2897 TransportClientSocketPool* pool =
2898 http_session_->GetTransportSocketPool(
2899 HttpNetworkSession::NORMAL_SOCKET_POOL);
2901 // Create an idle SPDY session.
2902 CreateInsecureSpdySession();
2903 EXPECT_FALSE(pool->IsStalled());
2905 // Trying to create a new connection should cause the pool to be stalled, and
2906 // post a task asynchronously to try and close the session.
2907 TestCompletionCallback callback2;
2908 HostPortPair host_port2("2.com", 80);
2909 scoped_refptr<TransportSocketParams> params2(
2910 new TransportSocketParams(
2911 host_port2, false, false, OnHostResolutionCallback(),
2912 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
2913 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
2914 EXPECT_EQ(ERR_IO_PENDING,
2915 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
2916 callback2.callback(), pool, BoundNetLog()));
2917 EXPECT_TRUE(pool->IsStalled());
2919 // The socket pool should close the connection asynchronously and establish a
2920 // new connection.
2921 EXPECT_EQ(OK, callback2.WaitForResult());
2922 EXPECT_FALSE(pool->IsStalled());
2923 EXPECT_FALSE(session_);
2926 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2927 // pointers to the idle session are currently held, in the case the SPDY session
2928 // has an alias.
2929 TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
2930 ClientSocketPoolManager::set_max_sockets_per_group(
2931 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2932 ClientSocketPoolManager::set_max_sockets_per_pool(
2933 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2935 MockRead reads[] = {
2936 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2938 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
2939 session_deps_.socket_factory->AddSocketDataProvider(&data);
2940 session_deps_.socket_factory->AddSocketDataProvider(&data);
2942 session_deps_.host_resolver->set_synchronous_mode(true);
2943 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2944 "1.com", "192.168.0.2", std::string());
2945 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2946 "2.com", "192.168.0.2", std::string());
2947 // Not strictly needed.
2948 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2949 "3.com", "192.168.0.3", std::string());
2951 CreateNetworkSession();
2953 TransportClientSocketPool* pool =
2954 http_session_->GetTransportSocketPool(
2955 HttpNetworkSession::NORMAL_SOCKET_POOL);
2957 // Create an idle SPDY session.
2958 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2959 PRIVACY_MODE_DISABLED);
2960 base::WeakPtr<SpdySession> session1 =
2961 ::net::CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2962 EXPECT_FALSE(pool->IsStalled());
2964 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
2965 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
2966 PRIVACY_MODE_DISABLED);
2967 HostResolver::RequestInfo info(key2.host_port_pair());
2968 AddressList addresses;
2969 // Pre-populate the DNS cache, since a synchronous resolution is required in
2970 // order to create the alias.
2971 session_deps_.host_resolver->Resolve(info, DEFAULT_PRIORITY, &addresses,
2972 CompletionCallback(), nullptr,
2973 BoundNetLog());
2974 // Get a session for |key2|, which should return the session created earlier.
2975 base::WeakPtr<SpdySession> session2 =
2976 spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
2977 ASSERT_EQ(session1.get(), session2.get());
2978 EXPECT_FALSE(pool->IsStalled());
2980 // Trying to create a new connection should cause the pool to be stalled, and
2981 // post a task asynchronously to try and close the session.
2982 TestCompletionCallback callback3;
2983 HostPortPair host_port3("3.com", 80);
2984 scoped_refptr<TransportSocketParams> params3(
2985 new TransportSocketParams(
2986 host_port3, false, false, OnHostResolutionCallback(),
2987 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
2988 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
2989 EXPECT_EQ(ERR_IO_PENDING,
2990 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
2991 callback3.callback(), pool, BoundNetLog()));
2992 EXPECT_TRUE(pool->IsStalled());
2994 // The socket pool should close the connection asynchronously and establish a
2995 // new connection.
2996 EXPECT_EQ(OK, callback3.WaitForResult());
2997 EXPECT_FALSE(pool->IsStalled());
2998 EXPECT_FALSE(session1);
2999 EXPECT_FALSE(session2);
3002 // Tests that when a SPDY session becomes idle, it closes itself if there is
3003 // a lower layer pool stalled on the per-pool socket limit.
3004 TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3005 ClientSocketPoolManager::set_max_sockets_per_group(
3006 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3007 ClientSocketPoolManager::set_max_sockets_per_pool(
3008 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3010 MockRead reads[] = {
3011 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3013 scoped_ptr<SpdyFrame> req1(
3014 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
3015 scoped_ptr<SpdyFrame> cancel1(
3016 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3017 MockWrite writes[] = {
3018 CreateMockWrite(*req1, 1),
3019 CreateMockWrite(*cancel1, 1),
3021 StaticSocketDataProvider data(reads, arraysize(reads),
3022 writes, arraysize(writes));
3023 session_deps_.socket_factory->AddSocketDataProvider(&data);
3025 MockRead http_reads[] = {
3026 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3028 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
3030 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3033 CreateNetworkSession();
3035 TransportClientSocketPool* pool =
3036 http_session_->GetTransportSocketPool(
3037 HttpNetworkSession::NORMAL_SOCKET_POOL);
3039 // Create a SPDY session.
3040 CreateInsecureSpdySession();
3041 EXPECT_FALSE(pool->IsStalled());
3043 // Create a stream using the session, and send a request.
3045 TestCompletionCallback callback1;
3046 base::WeakPtr<SpdyStream> spdy_stream1 =
3047 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session_,
3048 test_url_, DEFAULT_PRIORITY, BoundNetLog());
3049 ASSERT_TRUE(spdy_stream1.get());
3050 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3051 spdy_stream1->SetDelegate(&delegate1);
3053 scoped_ptr<SpdyHeaderBlock> headers1(
3054 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3055 EXPECT_EQ(ERR_IO_PENDING,
3056 spdy_stream1->SendRequestHeaders(
3057 headers1.Pass(), NO_MORE_DATA_TO_SEND));
3058 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3060 base::RunLoop().RunUntilIdle();
3062 // Trying to create a new connection should cause the pool to be stalled, and
3063 // post a task asynchronously to try and close the session.
3064 TestCompletionCallback callback2;
3065 HostPortPair host_port2("2.com", 80);
3066 scoped_refptr<TransportSocketParams> params2(
3067 new TransportSocketParams(
3068 host_port2, false, false, OnHostResolutionCallback(),
3069 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3070 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3071 EXPECT_EQ(ERR_IO_PENDING,
3072 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3073 callback2.callback(), pool, BoundNetLog()));
3074 EXPECT_TRUE(pool->IsStalled());
3076 // Running the message loop should cause the socket pool to ask the SPDY
3077 // session to close an idle socket, but since the socket is in use, nothing
3078 // happens.
3079 base::RunLoop().RunUntilIdle();
3080 EXPECT_TRUE(pool->IsStalled());
3081 EXPECT_FALSE(callback2.have_result());
3083 // Cancelling the request should result in the session's socket being
3084 // closed, since the pool is stalled.
3085 ASSERT_TRUE(spdy_stream1.get());
3086 spdy_stream1->Cancel();
3087 base::RunLoop().RunUntilIdle();
3088 ASSERT_FALSE(pool->IsStalled());
3089 EXPECT_EQ(OK, callback2.WaitForResult());
3092 // Verify that SpdySessionKey and therefore SpdySession is different when
3093 // privacy mode is enabled or disabled.
3094 TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3095 CreateNetworkSession();
3097 HostPortPair host_port_pair("www.example.org", 443);
3098 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3099 PRIVACY_MODE_ENABLED);
3100 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3101 PRIVACY_MODE_DISABLED);
3103 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3104 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3106 // Add SpdySession with PrivacyMode Enabled to the pool.
3107 base::WeakPtr<SpdySession> session_privacy_enabled =
3108 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3110 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3111 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3113 // Add SpdySession with PrivacyMode Disabled to the pool.
3114 base::WeakPtr<SpdySession> session_privacy_disabled =
3115 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3117 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3118 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3120 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3121 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3122 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3124 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3125 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3126 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3129 // Delegate that creates another stream when its stream is closed.
3130 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3131 public:
3132 StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3133 const base::WeakPtr<SpdySession>& session)
3134 : StreamDelegateDoNothing(stream),
3135 session_(session) {}
3137 ~StreamCreatingDelegate() override {}
3139 void OnClose(int status) override {
3140 GURL url(kDefaultURL);
3141 ignore_result(
3142 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3143 session_, url, MEDIUM, BoundNetLog()));
3146 private:
3147 const base::WeakPtr<SpdySession> session_;
3150 // Create another stream in response to a stream being reset. Nothing
3151 // should blow up. This is a regression test for
3152 // http://crbug.com/263690 .
3153 TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3154 session_deps_.host_resolver->set_synchronous_mode(true);
3156 scoped_ptr<SpdyFrame> req(
3157 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
3158 MockWrite writes[] = {
3159 CreateMockWrite(*req, 0),
3162 scoped_ptr<SpdyFrame> rst(
3163 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3164 MockRead reads[] = {
3165 MockRead(ASYNC, ERR_IO_PENDING, 1),
3166 CreateMockRead(*rst, 2),
3167 MockRead(ASYNC, ERR_IO_PENDING, 3),
3168 MockRead(ASYNC, 0, 4) // EOF
3170 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3171 session_deps_.socket_factory->AddSocketDataProvider(&data);
3173 CreateNetworkSession();
3174 CreateInsecureSpdySession();
3176 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
3177 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
3178 ASSERT_TRUE(spdy_stream.get() != nullptr);
3179 EXPECT_EQ(0u, spdy_stream->stream_id());
3181 StreamCreatingDelegate delegate(spdy_stream, session_);
3182 spdy_stream->SetDelegate(&delegate);
3184 scoped_ptr<SpdyHeaderBlock> headers(
3185 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3186 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3187 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3189 EXPECT_EQ(0u, spdy_stream->stream_id());
3191 base::RunLoop().RunUntilIdle();
3193 EXPECT_EQ(1u, spdy_stream->stream_id());
3195 // Cause the stream to be reset, which should cause another stream
3196 // to be created.
3197 data.CompleteRead();
3198 base::RunLoop().RunUntilIdle();
3200 EXPECT_FALSE(spdy_stream);
3201 EXPECT_TRUE(delegate.StreamIsClosed());
3202 EXPECT_EQ(0u, session_->num_active_streams());
3203 EXPECT_EQ(1u, session_->num_created_streams());
3205 data.CompleteRead();
3206 base::RunLoop().RunUntilIdle();
3207 EXPECT_FALSE(session_);
3210 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3211 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3212 // gets sent.
3213 SettingsMap new_settings;
3214 int32 window_size = 1;
3215 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3216 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3218 // Set up the socket so we read a SETTINGS frame that sets
3219 // INITIAL_WINDOW_SIZE.
3220 scoped_ptr<SpdyFrame> settings_frame(
3221 spdy_util_.ConstructSpdySettings(new_settings));
3222 MockRead reads[] = {
3223 CreateMockRead(*settings_frame, 0),
3224 MockRead(ASYNC, ERR_IO_PENDING, 1),
3225 MockRead(ASYNC, 0, 2) // EOF
3228 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3229 MockWrite writes[] = {
3230 CreateMockWrite(*settings_ack, 3),
3233 session_deps_.host_resolver->set_synchronous_mode(true);
3235 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3236 session_deps_.socket_factory->AddSocketDataProvider(&data);
3238 CreateNetworkSession();
3239 CreateInsecureSpdySession();
3240 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
3241 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
3242 ASSERT_TRUE(spdy_stream1.get() != nullptr);
3243 TestCompletionCallback callback1;
3244 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3246 // Process the SETTINGS frame.
3247 base::RunLoop().RunUntilIdle();
3248 EXPECT_EQ(session_->stream_initial_send_window_size(), window_size);
3249 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3251 // Release the first one, this will allow the second to be created.
3252 spdy_stream1->Cancel();
3253 EXPECT_FALSE(spdy_stream1);
3255 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
3256 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
3257 ASSERT_TRUE(spdy_stream2.get() != nullptr);
3258 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3259 spdy_stream2->Cancel();
3260 EXPECT_FALSE(spdy_stream2);
3262 EXPECT_TRUE(session_);
3263 data.CompleteRead();
3264 base::RunLoop().RunUntilIdle();
3265 EXPECT_FALSE(session_);
3268 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3269 // adjust the session receive window size. In addition,
3270 // SpdySession::IncreaseRecvWindowSize should trigger
3271 // sending a WINDOW_UPDATE frame for a large enough delta.
3272 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3273 session_deps_.host_resolver->set_synchronous_mode(true);
3275 const int32 initial_window_size =
3276 SpdySession::GetDefaultInitialWindowSize(GetParam());
3277 const int32 delta_window_size = 100;
3279 MockRead reads[] = {
3280 MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
3282 scoped_ptr<SpdyFrame> window_update(spdy_util_.ConstructSpdyWindowUpdate(
3283 kSessionFlowControlStreamId, initial_window_size + delta_window_size));
3284 MockWrite writes[] = {
3285 CreateMockWrite(*window_update, 0),
3287 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3288 session_deps_.socket_factory->AddSocketDataProvider(&data);
3290 CreateNetworkSession();
3291 CreateInsecureSpdySession();
3292 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3293 session_->flow_control_state());
3295 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3296 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3298 session_->IncreaseRecvWindowSize(delta_window_size);
3299 EXPECT_EQ(initial_window_size + delta_window_size,
3300 session_->session_recv_window_size_);
3301 EXPECT_EQ(delta_window_size, session_->session_unacked_recv_window_bytes_);
3303 // Should trigger sending a WINDOW_UPDATE frame.
3304 session_->IncreaseRecvWindowSize(initial_window_size);
3305 EXPECT_EQ(initial_window_size + delta_window_size + initial_window_size,
3306 session_->session_recv_window_size_);
3307 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3309 base::RunLoop().RunUntilIdle();
3311 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3312 session_->in_io_loop_ = true;
3313 session_->DecreaseRecvWindowSize(initial_window_size + delta_window_size +
3314 initial_window_size);
3315 session_->in_io_loop_ = false;
3316 EXPECT_EQ(0, session_->session_recv_window_size_);
3317 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3319 EXPECT_TRUE(session_);
3320 data.CompleteRead();
3321 base::RunLoop().RunUntilIdle();
3322 EXPECT_FALSE(session_);
3325 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3326 // adjust the session send window size when the "enable_spdy_31" flag
3327 // is set.
3328 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3329 session_deps_.host_resolver->set_synchronous_mode(true);
3331 MockRead reads[] = {
3332 MockRead(SYNCHRONOUS, 0, 0) // EOF
3334 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
3335 session_deps_.socket_factory->AddSocketDataProvider(&data);
3337 CreateNetworkSession();
3338 session_ = CreateFakeSpdySession(spdy_session_pool_, key_);
3339 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3340 session_->flow_control_state());
3342 const int32 initial_window_size =
3343 SpdySession::GetDefaultInitialWindowSize(GetParam());
3344 const int32 delta_window_size = 100;
3346 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3348 session_->IncreaseSendWindowSize(delta_window_size);
3349 EXPECT_EQ(initial_window_size + delta_window_size,
3350 session_->session_send_window_size_);
3352 session_->DecreaseSendWindowSize(delta_window_size);
3353 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3356 // Incoming data for an inactive stream should not cause the session
3357 // receive window size to decrease, but it should cause the unacked
3358 // bytes to increase.
3359 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3360 session_deps_.host_resolver->set_synchronous_mode(true);
3362 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3363 MockRead reads[] = {
3364 CreateMockRead(*resp, 0),
3365 MockRead(ASYNC, ERR_IO_PENDING, 1),
3366 MockRead(ASYNC, 0, 2) // EOF
3368 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
3369 session_deps_.socket_factory->AddSocketDataProvider(&data);
3371 CreateNetworkSession();
3372 CreateInsecureSpdySession();
3373 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3374 session_->flow_control_state());
3376 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3377 session_->session_recv_window_size_);
3378 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3380 base::RunLoop().RunUntilIdle();
3382 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3383 session_->session_recv_window_size_);
3384 EXPECT_EQ(kUploadDataSize, session_->session_unacked_recv_window_bytes_);
3386 EXPECT_TRUE(session_);
3387 data.CompleteRead();
3388 base::RunLoop().RunUntilIdle();
3389 EXPECT_FALSE(session_);
3392 // The frame header is not included in flow control, but frame payload
3393 // (including optional pad length and padding) is.
3394 TEST_P(SpdySessionTest, SessionFlowControlPadding) {
3395 // Padding only exists in HTTP/2.
3396 if (GetParam() < kProtoHTTP2)
3397 return;
3399 session_deps_.host_resolver->set_synchronous_mode(true);
3401 const int padding_length = 42;
3402 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(
3403 1, kUploadData, kUploadDataSize, false, padding_length));
3404 MockRead reads[] = {
3405 CreateMockRead(*resp, 0),
3406 MockRead(ASYNC, ERR_IO_PENDING, 1),
3407 MockRead(ASYNC, 0, 2) // EOF
3409 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
3410 session_deps_.socket_factory->AddSocketDataProvider(&data);
3412 CreateNetworkSession();
3413 CreateInsecureSpdySession();
3414 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3415 session_->flow_control_state());
3417 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3418 session_->session_recv_window_size_);
3419 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3421 base::RunLoop().RunUntilIdle();
3423 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3424 session_->session_recv_window_size_);
3425 EXPECT_EQ(kUploadDataSize + padding_length,
3426 session_->session_unacked_recv_window_bytes_);
3428 data.CompleteRead();
3429 base::RunLoop().RunUntilIdle();
3430 EXPECT_FALSE(session_);
3433 // Peer sends more data than stream level receiving flow control window.
3434 TEST_P(SpdySessionTest, StreamFlowControlTooMuchData) {
3435 const int32 stream_max_recv_window_size = 1024;
3436 const int32 data_frame_size = 2 * stream_max_recv_window_size;
3438 scoped_ptr<SpdyFrame> req(
3439 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
3440 scoped_ptr<SpdyFrame> rst(
3441 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
3442 MockWrite writes[] = {
3443 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
3446 scoped_ptr<SpdyFrame> resp(
3447 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3448 const std::string payload(data_frame_size, 'a');
3449 scoped_ptr<SpdyFrame> data_frame(spdy_util_.ConstructSpdyBodyFrame(
3450 1, payload.data(), data_frame_size, false));
3451 MockRead reads[] = {
3452 CreateMockRead(*resp, 1),
3453 MockRead(ASYNC, ERR_IO_PENDING, 2),
3454 CreateMockRead(*data_frame, 3),
3455 MockRead(ASYNC, ERR_IO_PENDING, 5),
3456 MockRead(ASYNC, 0, 6),
3459 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3460 session_deps_.socket_factory->AddSocketDataProvider(&data);
3461 CreateNetworkSession();
3463 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
3464 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
3465 CreateInsecureSpdySession();
3466 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM, session_->flow_control_state());
3468 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
3469 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
3470 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3472 test::StreamDelegateDoNothing delegate(spdy_stream);
3473 spdy_stream->SetDelegate(&delegate);
3475 scoped_ptr<SpdyHeaderBlock> headers(
3476 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3477 EXPECT_EQ(ERR_IO_PENDING, spdy_stream->SendRequestHeaders(
3478 headers.Pass(), NO_MORE_DATA_TO_SEND));
3480 // Request and response.
3481 base::RunLoop().RunUntilIdle();
3482 EXPECT_EQ(1u, spdy_stream->stream_id());
3484 // Too large data frame causes flow control error, should close stream.
3485 data.CompleteRead();
3486 base::RunLoop().RunUntilIdle();
3487 EXPECT_FALSE(spdy_stream);
3489 EXPECT_TRUE(session_);
3490 data.CompleteRead();
3491 base::RunLoop().RunUntilIdle();
3492 EXPECT_FALSE(session_);
3495 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3496 // deltas in the receiving window size when checking incoming frames for flow
3497 // control errors at session level.
3498 TEST_P(SpdySessionTest, SessionFlowControlTooMuchDataTwoDataFrames) {
3499 const int32 session_max_recv_window_size = 500;
3500 const int32 first_data_frame_size = 200;
3501 const int32 second_data_frame_size = 400;
3503 // First data frame should not trigger a WINDOW_UPDATE.
3504 ASSERT_GT(session_max_recv_window_size / 2, first_data_frame_size);
3505 // Second data frame would be fine had there been a WINDOW_UPDATE.
3506 ASSERT_GT(session_max_recv_window_size, second_data_frame_size);
3507 // But in fact, the two data frames together overflow the receiving window at
3508 // session level.
3509 ASSERT_LT(session_max_recv_window_size,
3510 first_data_frame_size + second_data_frame_size);
3512 session_deps_.host_resolver->set_synchronous_mode(true);
3514 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3515 0, GOAWAY_FLOW_CONTROL_ERROR,
3516 "delta_window_size is 400 in DecreaseRecvWindowSize, which is larger "
3517 "than the receive window size of 500"));
3518 MockWrite writes[] = {
3519 CreateMockWrite(*goaway, 4),
3522 const std::string first_data_frame(first_data_frame_size, 'a');
3523 scoped_ptr<SpdyFrame> first(spdy_util_.ConstructSpdyBodyFrame(
3524 1, first_data_frame.data(), first_data_frame_size, false));
3525 const std::string second_data_frame(second_data_frame_size, 'b');
3526 scoped_ptr<SpdyFrame> second(spdy_util_.ConstructSpdyBodyFrame(
3527 1, second_data_frame.data(), second_data_frame_size, false));
3528 MockRead reads[] = {
3529 CreateMockRead(*first, 0),
3530 MockRead(ASYNC, ERR_IO_PENDING, 1),
3531 CreateMockRead(*second, 2),
3532 MockRead(ASYNC, 0, 3),
3534 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3535 session_deps_.socket_factory->AddSocketDataProvider(&data);
3537 CreateNetworkSession();
3538 CreateInsecureSpdySession();
3539 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3540 session_->flow_control_state());
3541 // Setting session level receiving window size to smaller than initial is not
3542 // possible via SpdySessionPoolPeer.
3543 session_->session_recv_window_size_ = session_max_recv_window_size;
3545 // First data frame is immediately consumed and does not trigger
3546 // WINDOW_UPDATE.
3547 base::RunLoop().RunUntilIdle();
3548 EXPECT_EQ(first_data_frame_size,
3549 session_->session_unacked_recv_window_bytes_);
3550 EXPECT_EQ(session_max_recv_window_size, session_->session_recv_window_size_);
3551 EXPECT_EQ(SpdySession::STATE_AVAILABLE, session_->availability_state_);
3553 // Second data frame overflows receiving window, causes session to close.
3554 data.CompleteRead();
3555 base::RunLoop().RunUntilIdle();
3556 EXPECT_EQ(SpdySession::STATE_DRAINING, session_->availability_state_);
3559 // Regression test for a bug that was caused by including unsent WINDOW_UPDATE
3560 // deltas in the receiving window size when checking incoming data frames for
3561 // flow control errors at stream level.
3562 TEST_P(SpdySessionTest, StreamFlowControlTooMuchDataTwoDataFrames) {
3563 const int32 stream_max_recv_window_size = 500;
3564 const int32 first_data_frame_size = 200;
3565 const int32 second_data_frame_size = 400;
3567 // First data frame should not trigger a WINDOW_UPDATE.
3568 ASSERT_GT(stream_max_recv_window_size / 2, first_data_frame_size);
3569 // Second data frame would be fine had there been a WINDOW_UPDATE.
3570 ASSERT_GT(stream_max_recv_window_size, second_data_frame_size);
3571 // But in fact, they should overflow the receiving window at stream level.
3572 ASSERT_LT(stream_max_recv_window_size,
3573 first_data_frame_size + second_data_frame_size);
3575 scoped_ptr<SpdyFrame> req(
3576 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
3577 scoped_ptr<SpdyFrame> rst(
3578 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
3579 MockWrite writes[] = {
3580 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 6),
3583 scoped_ptr<SpdyFrame> resp(
3584 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3585 const std::string first_data_frame(first_data_frame_size, 'a');
3586 scoped_ptr<SpdyFrame> first(spdy_util_.ConstructSpdyBodyFrame(
3587 1, first_data_frame.data(), first_data_frame_size, false));
3588 const std::string second_data_frame(second_data_frame_size, 'b');
3589 scoped_ptr<SpdyFrame> second(spdy_util_.ConstructSpdyBodyFrame(
3590 1, second_data_frame.data(), second_data_frame_size, false));
3591 MockRead reads[] = {
3592 CreateMockRead(*resp, 1),
3593 MockRead(ASYNC, ERR_IO_PENDING, 2),
3594 CreateMockRead(*first, 3),
3595 MockRead(ASYNC, ERR_IO_PENDING, 4),
3596 CreateMockRead(*second, 5),
3597 MockRead(ASYNC, ERR_IO_PENDING, 7),
3598 MockRead(ASYNC, 0, 8),
3601 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3602 session_deps_.socket_factory->AddSocketDataProvider(&data);
3604 CreateNetworkSession();
3605 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
3606 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
3608 CreateInsecureSpdySession();
3609 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM, session_->flow_control_state());
3611 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
3612 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
3613 test::StreamDelegateDoNothing delegate(spdy_stream);
3614 spdy_stream->SetDelegate(&delegate);
3616 scoped_ptr<SpdyHeaderBlock> headers(
3617 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3618 EXPECT_EQ(ERR_IO_PENDING, spdy_stream->SendRequestHeaders(
3619 headers.Pass(), NO_MORE_DATA_TO_SEND));
3621 // Request and response.
3622 base::RunLoop().RunUntilIdle();
3623 EXPECT_TRUE(spdy_stream->IsLocallyClosed());
3624 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3626 // First data frame.
3627 data.CompleteRead();
3628 base::RunLoop().RunUntilIdle();
3629 EXPECT_TRUE(spdy_stream->IsLocallyClosed());
3630 EXPECT_EQ(stream_max_recv_window_size - first_data_frame_size,
3631 spdy_stream->recv_window_size());
3633 // Consume first data frame. This does not trigger a WINDOW_UPDATE.
3634 std::string received_data = delegate.TakeReceivedData();
3635 EXPECT_EQ(static_cast<size_t>(first_data_frame_size), received_data.size());
3636 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3638 // Second data frame overflows receiving window, causes the stream to close.
3639 data.CompleteRead();
3640 base::RunLoop().RunUntilIdle();
3641 EXPECT_FALSE(spdy_stream.get());
3643 // RST_STREAM
3644 EXPECT_TRUE(session_);
3645 data.CompleteRead();
3646 base::RunLoop().RunUntilIdle();
3647 EXPECT_FALSE(session_);
3650 // A delegate that drops any received data.
3651 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3652 public:
3653 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3654 base::StringPiece data)
3655 : StreamDelegateSendImmediate(stream, data) {}
3657 ~DropReceivedDataDelegate() override {}
3659 // Drop any received data.
3660 void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override {}
3663 // Send data back and forth but use a delegate that drops its received
3664 // data. The receive window should still increase to its original
3665 // value, i.e. we shouldn't "leak" receive window bytes.
3666 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3667 const int32 msg_data_size = 100;
3668 const std::string msg_data(msg_data_size, 'a');
3670 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3671 kDefaultURL, 1, msg_data_size, MEDIUM, nullptr, 0));
3672 scoped_ptr<SpdyFrame> msg(
3673 spdy_util_.ConstructSpdyBodyFrame(
3674 1, msg_data.data(), msg_data_size, false));
3675 MockWrite writes[] = {
3676 CreateMockWrite(*req, 0),
3677 CreateMockWrite(*msg, 2),
3680 scoped_ptr<SpdyFrame> resp(
3681 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3682 scoped_ptr<SpdyFrame> echo(
3683 spdy_util_.ConstructSpdyBodyFrame(
3684 1, msg_data.data(), msg_data_size, false));
3685 scoped_ptr<SpdyFrame> window_update(
3686 spdy_util_.ConstructSpdyWindowUpdate(
3687 kSessionFlowControlStreamId, msg_data_size));
3688 MockRead reads[] = {
3689 CreateMockRead(*resp, 1),
3690 CreateMockRead(*echo, 3),
3691 MockRead(ASYNC, ERR_IO_PENDING, 4),
3692 MockRead(ASYNC, 0, 5) // EOF
3695 // Create SpdySession and SpdyStream and send the request.
3696 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3697 session_deps_.host_resolver->set_synchronous_mode(true);
3698 session_deps_.socket_factory->AddSocketDataProvider(&data);
3700 CreateNetworkSession();
3701 CreateInsecureSpdySession();
3703 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
3704 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
3705 ASSERT_TRUE(stream.get() != nullptr);
3706 EXPECT_EQ(0u, stream->stream_id());
3708 DropReceivedDataDelegate delegate(stream, msg_data);
3709 stream->SetDelegate(&delegate);
3711 scoped_ptr<SpdyHeaderBlock> headers(
3712 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, msg_data_size));
3713 EXPECT_EQ(ERR_IO_PENDING,
3714 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3715 EXPECT_TRUE(stream->HasUrlFromHeaders());
3717 const int32 initial_window_size =
3718 SpdySession::GetDefaultInitialWindowSize(GetParam());
3719 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3720 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3722 base::RunLoop().RunUntilIdle();
3724 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3725 EXPECT_EQ(msg_data_size, session_->session_unacked_recv_window_bytes_);
3727 stream->Close();
3728 EXPECT_FALSE(stream);
3730 EXPECT_EQ(OK, delegate.WaitForClose());
3732 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3733 EXPECT_EQ(msg_data_size, session_->session_unacked_recv_window_bytes_);
3735 data.CompleteRead();
3736 base::RunLoop().RunUntilIdle();
3737 EXPECT_FALSE(session_);
3740 // Send data back and forth but close the stream before its data frame
3741 // can be written to the socket. The send window should then increase
3742 // to its original value, i.e. we shouldn't "leak" send window bytes.
3743 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3744 const int32 msg_data_size = 100;
3745 const std::string msg_data(msg_data_size, 'a');
3747 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3748 kDefaultURL, 1, msg_data_size, MEDIUM, nullptr, 0));
3749 MockWrite writes[] = {
3750 CreateMockWrite(*req, 0),
3753 scoped_ptr<SpdyFrame> resp(
3754 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3755 MockRead reads[] = {
3756 MockRead(ASYNC, ERR_IO_PENDING, 1),
3757 CreateMockRead(*resp, 2),
3758 MockRead(ASYNC, 0, 3) // EOF
3761 // Create SpdySession and SpdyStream and send the request.
3762 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3763 session_deps_.host_resolver->set_synchronous_mode(true);
3764 session_deps_.socket_factory->AddSocketDataProvider(&data);
3766 CreateNetworkSession();
3767 CreateInsecureSpdySession();
3769 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
3770 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
3771 ASSERT_TRUE(stream.get() != nullptr);
3772 EXPECT_EQ(0u, stream->stream_id());
3774 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3775 stream->SetDelegate(&delegate);
3777 scoped_ptr<SpdyHeaderBlock> headers(
3778 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, msg_data_size));
3779 EXPECT_EQ(ERR_IO_PENDING,
3780 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3781 EXPECT_TRUE(stream->HasUrlFromHeaders());
3783 const int32 initial_window_size =
3784 SpdySession::GetDefaultInitialWindowSize(GetParam());
3785 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3787 // Write request.
3788 base::RunLoop().RunUntilIdle();
3790 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3792 // Read response, but do not run the message loop, so that the body is not
3793 // written to the socket.
3794 data.CompleteRead();
3796 EXPECT_EQ(initial_window_size - msg_data_size,
3797 session_->session_send_window_size_);
3799 // Closing the stream should increase the session's send window.
3800 stream->Close();
3801 EXPECT_FALSE(stream);
3803 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3805 EXPECT_EQ(OK, delegate.WaitForClose());
3807 base::RunLoop().RunUntilIdle();
3808 EXPECT_FALSE(session_);
3810 EXPECT_TRUE(data.AllWriteDataConsumed());
3811 EXPECT_TRUE(data.AllReadDataConsumed());
3814 // Send data back and forth; the send and receive windows should
3815 // change appropriately.
3816 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
3817 const int32 msg_data_size = 100;
3818 const std::string msg_data(msg_data_size, 'a');
3820 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3821 kDefaultURL, 1, msg_data_size, MEDIUM, nullptr, 0));
3822 scoped_ptr<SpdyFrame> msg(
3823 spdy_util_.ConstructSpdyBodyFrame(
3824 1, msg_data.data(), msg_data_size, false));
3825 MockWrite writes[] = {
3826 CreateMockWrite(*req, 0),
3827 CreateMockWrite(*msg, 2),
3830 scoped_ptr<SpdyFrame> resp(
3831 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3832 scoped_ptr<SpdyFrame> echo(
3833 spdy_util_.ConstructSpdyBodyFrame(
3834 1, msg_data.data(), msg_data_size, false));
3835 scoped_ptr<SpdyFrame> window_update(
3836 spdy_util_.ConstructSpdyWindowUpdate(
3837 kSessionFlowControlStreamId, msg_data_size));
3838 MockRead reads[] = {
3839 CreateMockRead(*resp, 1),
3840 MockRead(ASYNC, ERR_IO_PENDING, 3),
3841 CreateMockRead(*echo, 4),
3842 MockRead(ASYNC, ERR_IO_PENDING, 5),
3843 CreateMockRead(*window_update, 6),
3844 MockRead(ASYNC, ERR_IO_PENDING, 7),
3845 MockRead(ASYNC, 0, 8) // EOF
3848 // Create SpdySession and SpdyStream and send the request.
3849 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3850 session_deps_.host_resolver->set_synchronous_mode(true);
3851 session_deps_.socket_factory->AddSocketDataProvider(&data);
3853 CreateNetworkSession();
3854 CreateInsecureSpdySession();
3856 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
3857 SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
3858 ASSERT_TRUE(stream.get() != nullptr);
3859 EXPECT_EQ(0u, stream->stream_id());
3861 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3862 stream->SetDelegate(&delegate);
3864 scoped_ptr<SpdyHeaderBlock> headers(
3865 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, msg_data_size));
3866 EXPECT_EQ(ERR_IO_PENDING,
3867 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3868 EXPECT_TRUE(stream->HasUrlFromHeaders());
3870 const int32 initial_window_size =
3871 SpdySession::GetDefaultInitialWindowSize(GetParam());
3872 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3873 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3874 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3876 // Send request and message.
3877 base::RunLoop().RunUntilIdle();
3879 EXPECT_EQ(initial_window_size - msg_data_size,
3880 session_->session_send_window_size_);
3881 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3882 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3884 // Read echo.
3885 data.CompleteRead();
3886 base::RunLoop().RunUntilIdle();
3888 EXPECT_EQ(initial_window_size - msg_data_size,
3889 session_->session_send_window_size_);
3890 EXPECT_EQ(initial_window_size - msg_data_size,
3891 session_->session_recv_window_size_);
3892 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3894 // Read window update.
3895 data.CompleteRead();
3896 base::RunLoop().RunUntilIdle();
3898 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3899 EXPECT_EQ(initial_window_size - msg_data_size,
3900 session_->session_recv_window_size_);
3901 EXPECT_EQ(0, session_->session_unacked_recv_window_bytes_);
3903 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
3905 // Draining the delegate's read queue should increase the session's
3906 // receive window.
3907 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3908 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3909 EXPECT_EQ(msg_data_size, session_->session_unacked_recv_window_bytes_);
3911 stream->Close();
3912 EXPECT_FALSE(stream);
3914 EXPECT_EQ(OK, delegate.WaitForClose());
3916 EXPECT_EQ(initial_window_size, session_->session_send_window_size_);
3917 EXPECT_EQ(initial_window_size, session_->session_recv_window_size_);
3918 EXPECT_EQ(msg_data_size, session_->session_unacked_recv_window_bytes_);
3920 data.CompleteRead();
3921 base::RunLoop().RunUntilIdle();
3922 EXPECT_FALSE(session_);
3925 // Given a stall function and an unstall function, runs a test to make
3926 // sure that a stream resumes after unstall.
3927 void SpdySessionTest::RunResumeAfterUnstallTest(
3928 const base::Callback<void(SpdyStream*)>& stall_function,
3929 const base::Callback<void(SpdyStream*, int32)>& unstall_function) {
3931 session_deps_.host_resolver->set_synchronous_mode(true);
3933 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
3934 kDefaultURL, 1, kBodyDataSize, LOWEST, nullptr, 0));
3935 scoped_ptr<SpdyFrame> body(
3936 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3937 MockWrite writes[] = {
3938 CreateMockWrite(*req, 0),
3939 CreateMockWrite(*body, 1),
3942 scoped_ptr<SpdyFrame> resp(
3943 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
3944 scoped_ptr<SpdyFrame> echo(
3945 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
3946 MockRead reads[] = {
3947 CreateMockRead(*resp, 2), MockRead(ASYNC, 0, 3) // EOF
3950 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
3951 session_deps_.socket_factory->AddSocketDataProvider(&data);
3953 CreateNetworkSession();
3954 CreateInsecureSpdySession();
3955 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3956 session_->flow_control_state());
3958 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
3959 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
3960 ASSERT_TRUE(stream.get() != nullptr);
3962 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
3963 stream->SetDelegate(&delegate);
3965 EXPECT_FALSE(stream->HasUrlFromHeaders());
3966 EXPECT_FALSE(stream->send_stalled_by_flow_control());
3968 scoped_ptr<SpdyHeaderBlock> headers(
3969 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
3970 EXPECT_EQ(ERR_IO_PENDING,
3971 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3972 EXPECT_TRUE(stream->HasUrlFromHeaders());
3973 EXPECT_EQ(kDefaultURL, stream->GetUrlFromHeaders().spec());
3975 stall_function.Run(stream.get());
3977 base::RunLoop().RunUntilIdle();
3979 EXPECT_TRUE(stream->send_stalled_by_flow_control());
3981 unstall_function.Run(stream.get(), kBodyDataSize);
3983 EXPECT_FALSE(stream->send_stalled_by_flow_control());
3985 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
3987 EXPECT_TRUE(delegate.send_headers_completed());
3988 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
3989 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
3990 EXPECT_FALSE(session_);
3991 EXPECT_TRUE(data.AllWriteDataConsumed());
3994 // Run the resume-after-unstall test with all possible stall and
3995 // unstall sequences.
3997 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
3998 RunResumeAfterUnstallTest(
3999 base::Bind(&SpdySessionTest::StallSessionOnly,
4000 base::Unretained(this)),
4001 base::Bind(&SpdySessionTest::UnstallSessionOnly,
4002 base::Unretained(this)));
4005 // Equivalent to
4006 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4007 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
4008 RunResumeAfterUnstallTest(
4009 base::Bind(&SpdySessionTest::StallStreamOnly,
4010 base::Unretained(this)),
4011 base::Bind(&SpdySessionTest::UnstallStreamOnly,
4012 base::Unretained(this)));
4015 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4016 RunResumeAfterUnstallTest(
4017 base::Bind(&SpdySessionTest::StallSessionStream,
4018 base::Unretained(this)),
4019 base::Bind(&SpdySessionTest::UnstallSessionStream,
4020 base::Unretained(this)));
4023 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4024 RunResumeAfterUnstallTest(
4025 base::Bind(&SpdySessionTest::StallStreamSession,
4026 base::Unretained(this)),
4027 base::Bind(&SpdySessionTest::UnstallSessionStream,
4028 base::Unretained(this)));
4031 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4032 RunResumeAfterUnstallTest(
4033 base::Bind(&SpdySessionTest::StallStreamSession,
4034 base::Unretained(this)),
4035 base::Bind(&SpdySessionTest::UnstallStreamSession,
4036 base::Unretained(this)));
4039 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4040 RunResumeAfterUnstallTest(
4041 base::Bind(&SpdySessionTest::StallSessionStream,
4042 base::Unretained(this)),
4043 base::Bind(&SpdySessionTest::UnstallStreamSession,
4044 base::Unretained(this)));
4047 // Cause a stall by reducing the flow control send window to 0. The
4048 // streams should resume in priority order when that window is then
4049 // increased.
4050 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4051 session_deps_.host_resolver->set_synchronous_mode(true);
4053 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4054 kDefaultURL, 1, kBodyDataSize, LOWEST, nullptr, 0));
4055 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4056 kDefaultURL, 3, kBodyDataSize, MEDIUM, nullptr, 0));
4057 scoped_ptr<SpdyFrame> body1(
4058 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4059 scoped_ptr<SpdyFrame> body2(
4060 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4061 MockWrite writes[] = {
4062 CreateMockWrite(*req1, 0),
4063 CreateMockWrite(*req2, 1),
4064 CreateMockWrite(*body2, 2),
4065 CreateMockWrite(*body1, 3),
4068 scoped_ptr<SpdyFrame> resp1(
4069 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4070 scoped_ptr<SpdyFrame> resp2(
4071 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
4072 MockRead reads[] = {
4073 CreateMockRead(*resp1, 4),
4074 CreateMockRead(*resp2, 5),
4075 MockRead(ASYNC, 0, 6) // EOF
4078 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4079 session_deps_.socket_factory->AddSocketDataProvider(&data);
4081 CreateNetworkSession();
4082 CreateInsecureSpdySession();
4083 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4084 session_->flow_control_state());
4086 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
4087 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4088 ASSERT_TRUE(stream1.get() != nullptr);
4090 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4091 stream1->SetDelegate(&delegate1);
4093 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4095 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
4096 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog());
4097 ASSERT_TRUE(stream2.get() != nullptr);
4099 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4100 stream2->SetDelegate(&delegate2);
4102 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4104 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4105 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4107 StallSessionSend();
4109 scoped_ptr<SpdyHeaderBlock> headers1(
4110 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
4111 EXPECT_EQ(ERR_IO_PENDING,
4112 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4113 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4114 EXPECT_EQ(kDefaultURL, stream1->GetUrlFromHeaders().spec());
4116 base::RunLoop().RunUntilIdle();
4117 EXPECT_EQ(1u, stream1->stream_id());
4118 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4120 scoped_ptr<SpdyHeaderBlock> headers2(
4121 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
4122 EXPECT_EQ(ERR_IO_PENDING,
4123 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4124 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4125 EXPECT_EQ(kDefaultURL, stream2->GetUrlFromHeaders().spec());
4127 base::RunLoop().RunUntilIdle();
4128 EXPECT_EQ(3u, stream2->stream_id());
4129 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4131 // This should unstall only stream2.
4132 UnstallSessionSend(kBodyDataSize);
4134 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4135 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4137 base::RunLoop().RunUntilIdle();
4139 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4140 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4142 // This should then unstall stream1.
4143 UnstallSessionSend(kBodyDataSize);
4145 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4146 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4148 base::RunLoop().RunUntilIdle();
4150 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4151 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4153 EXPECT_TRUE(delegate1.send_headers_completed());
4154 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4155 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4157 EXPECT_TRUE(delegate2.send_headers_completed());
4158 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4159 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4161 EXPECT_FALSE(session_);
4162 EXPECT_TRUE(data.AllWriteDataConsumed());
4163 EXPECT_TRUE(data.AllReadDataConsumed());
4166 // Delegate that closes a given stream after sending its body.
4167 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4168 public:
4169 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4170 base::StringPiece data)
4171 : StreamDelegateWithBody(stream, data) {}
4173 ~StreamClosingDelegate() override {}
4175 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4176 stream_to_close_ = stream_to_close;
4179 void OnDataSent() override {
4180 test::StreamDelegateWithBody::OnDataSent();
4181 if (stream_to_close_.get()) {
4182 stream_to_close_->Close();
4183 EXPECT_FALSE(stream_to_close_);
4187 private:
4188 base::WeakPtr<SpdyStream> stream_to_close_;
4191 // Cause a stall by reducing the flow control send window to
4192 // 0. Unstalling the session should properly handle deleted streams.
4193 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4194 session_deps_.host_resolver->set_synchronous_mode(true);
4196 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4197 kDefaultURL, 1, kBodyDataSize, LOWEST, nullptr, 0));
4198 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4199 kDefaultURL, 3, kBodyDataSize, LOWEST, nullptr, 0));
4200 scoped_ptr<SpdyFrame> req3(spdy_util_.ConstructSpdyPost(
4201 kDefaultURL, 5, kBodyDataSize, LOWEST, nullptr, 0));
4202 scoped_ptr<SpdyFrame> body2(
4203 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4204 MockWrite writes[] = {
4205 CreateMockWrite(*req1, 0),
4206 CreateMockWrite(*req2, 1),
4207 CreateMockWrite(*req3, 2),
4208 CreateMockWrite(*body2, 3),
4211 scoped_ptr<SpdyFrame> resp2(
4212 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
4213 MockRead reads[] = {
4214 CreateMockRead(*resp2, 4),
4215 MockRead(ASYNC, ERR_IO_PENDING, 5),
4216 MockRead(ASYNC, 0, 6) // EOF
4219 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4220 session_deps_.socket_factory->AddSocketDataProvider(&data);
4222 CreateNetworkSession();
4223 CreateInsecureSpdySession();
4224 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4225 session_->flow_control_state());
4227 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
4228 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4229 ASSERT_TRUE(stream1.get() != nullptr);
4231 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4232 stream1->SetDelegate(&delegate1);
4234 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4236 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
4237 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4238 ASSERT_TRUE(stream2.get() != nullptr);
4240 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4241 stream2->SetDelegate(&delegate2);
4243 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4245 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
4246 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4247 ASSERT_TRUE(stream3.get() != nullptr);
4249 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4250 stream3->SetDelegate(&delegate3);
4252 EXPECT_FALSE(stream3->HasUrlFromHeaders());
4254 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4255 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4256 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4258 StallSessionSend();
4260 scoped_ptr<SpdyHeaderBlock> headers1(
4261 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
4262 EXPECT_EQ(ERR_IO_PENDING,
4263 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4264 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4265 EXPECT_EQ(kDefaultURL, stream1->GetUrlFromHeaders().spec());
4267 base::RunLoop().RunUntilIdle();
4268 EXPECT_EQ(1u, stream1->stream_id());
4269 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4271 scoped_ptr<SpdyHeaderBlock> headers2(
4272 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
4273 EXPECT_EQ(ERR_IO_PENDING,
4274 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4275 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4276 EXPECT_EQ(kDefaultURL, stream2->GetUrlFromHeaders().spec());
4278 base::RunLoop().RunUntilIdle();
4279 EXPECT_EQ(3u, stream2->stream_id());
4280 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4282 scoped_ptr<SpdyHeaderBlock> headers3(
4283 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
4284 EXPECT_EQ(ERR_IO_PENDING,
4285 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4286 EXPECT_TRUE(stream3->HasUrlFromHeaders());
4287 EXPECT_EQ(kDefaultURL, stream3->GetUrlFromHeaders().spec());
4289 base::RunLoop().RunUntilIdle();
4290 EXPECT_EQ(5u, stream3->stream_id());
4291 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4293 SpdyStreamId stream_id1 = stream1->stream_id();
4294 SpdyStreamId stream_id2 = stream2->stream_id();
4295 SpdyStreamId stream_id3 = stream3->stream_id();
4297 // Close stream1 preemptively.
4298 session_->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4299 EXPECT_FALSE(stream1);
4301 EXPECT_FALSE(session_->IsStreamActive(stream_id1));
4302 EXPECT_TRUE(session_->IsStreamActive(stream_id2));
4303 EXPECT_TRUE(session_->IsStreamActive(stream_id3));
4305 // Unstall stream2, which should then close stream3.
4306 delegate2.set_stream_to_close(stream3);
4307 UnstallSessionSend(kBodyDataSize);
4309 base::RunLoop().RunUntilIdle();
4310 EXPECT_FALSE(stream3);
4312 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4313 EXPECT_FALSE(session_->IsStreamActive(stream_id1));
4314 EXPECT_TRUE(session_->IsStreamActive(stream_id2));
4315 EXPECT_FALSE(session_->IsStreamActive(stream_id3));
4317 data.CompleteRead();
4318 base::RunLoop().RunUntilIdle();
4319 EXPECT_FALSE(stream2);
4320 EXPECT_FALSE(session_);
4322 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4323 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4324 EXPECT_EQ(OK, delegate3.WaitForClose());
4326 EXPECT_TRUE(delegate1.send_headers_completed());
4327 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4329 EXPECT_TRUE(delegate2.send_headers_completed());
4330 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4331 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4333 EXPECT_TRUE(delegate3.send_headers_completed());
4334 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4336 EXPECT_TRUE(data.AllWriteDataConsumed());
4339 // Cause a stall by reducing the flow control send window to
4340 // 0. Unstalling the session should properly handle the session itself
4341 // being closed.
4342 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4343 session_deps_.host_resolver->set_synchronous_mode(true);
4345 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
4346 kDefaultURL, 1, kBodyDataSize, LOWEST, nullptr, 0));
4347 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
4348 kDefaultURL, 3, kBodyDataSize, LOWEST, nullptr, 0));
4349 scoped_ptr<SpdyFrame> body1(
4350 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4351 MockWrite writes[] = {
4352 CreateMockWrite(*req1, 0),
4353 CreateMockWrite(*req2, 1),
4356 MockRead reads[] = {
4357 MockRead(ASYNC, ERR_IO_PENDING, 2), MockRead(ASYNC, 0, 3) // EOF
4360 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4361 session_deps_.socket_factory->AddSocketDataProvider(&data);
4363 CreateNetworkSession();
4364 CreateInsecureSpdySession();
4365 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4366 session_->flow_control_state());
4368 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
4369 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4370 ASSERT_TRUE(stream1.get() != nullptr);
4372 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4373 stream1->SetDelegate(&delegate1);
4375 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4377 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
4378 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4379 ASSERT_TRUE(stream2.get() != nullptr);
4381 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4382 stream2->SetDelegate(&delegate2);
4384 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4386 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4387 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4389 StallSessionSend();
4391 scoped_ptr<SpdyHeaderBlock> headers1(
4392 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
4393 EXPECT_EQ(ERR_IO_PENDING,
4394 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4395 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4396 EXPECT_EQ(kDefaultURL, stream1->GetUrlFromHeaders().spec());
4398 base::RunLoop().RunUntilIdle();
4399 EXPECT_EQ(1u, stream1->stream_id());
4400 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4402 scoped_ptr<SpdyHeaderBlock> headers2(
4403 spdy_util_.ConstructPostHeaderBlock(kDefaultURL, kBodyDataSize));
4404 EXPECT_EQ(ERR_IO_PENDING,
4405 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4406 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4407 EXPECT_EQ(kDefaultURL, stream2->GetUrlFromHeaders().spec());
4409 base::RunLoop().RunUntilIdle();
4410 EXPECT_EQ(3u, stream2->stream_id());
4411 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4413 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4415 // Unstall stream1.
4416 UnstallSessionSend(kBodyDataSize);
4418 // Close the session (since we can't do it from within the delegate
4419 // method, since it's in the stream's loop).
4420 session_->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4421 data.CompleteRead();
4422 base::RunLoop().RunUntilIdle();
4423 EXPECT_FALSE(session_);
4425 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4427 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4428 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4430 EXPECT_TRUE(delegate1.send_headers_completed());
4431 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4433 EXPECT_TRUE(delegate2.send_headers_completed());
4434 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4436 EXPECT_TRUE(data.AllWriteDataConsumed());
4439 TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4440 scoped_ptr<SpdyFrame> req(
4441 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4442 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4443 0, GOAWAY_FLOW_CONTROL_ERROR,
4444 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4445 "the receive window size of 1"));
4446 MockWrite writes[] = {
4447 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 4),
4450 scoped_ptr<SpdyFrame> resp(
4451 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
4452 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4453 MockRead reads[] = {
4454 MockRead(ASYNC, ERR_IO_PENDING, 1),
4455 CreateMockRead(*resp, 2),
4456 CreateMockRead(*body, 3),
4459 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4460 session_deps_.socket_factory->AddSocketDataProvider(&data);
4462 CreateNetworkSession();
4463 CreateInsecureSpdySession();
4465 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4466 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4467 ASSERT_TRUE(spdy_stream.get() != nullptr);
4468 test::StreamDelegateDoNothing delegate(spdy_stream);
4469 spdy_stream->SetDelegate(&delegate);
4471 scoped_ptr<SpdyHeaderBlock> headers(
4472 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
4473 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4475 // Write request.
4476 base::RunLoop().RunUntilIdle();
4478 // Put session on the edge of overflowing it's recv window.
4479 session_->session_recv_window_size_ = 1;
4481 // Read response headers & body. Body overflows the session window, and a
4482 // goaway is written.
4483 data.CompleteRead();
4484 base::RunLoop().RunUntilIdle();
4486 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4487 EXPECT_FALSE(session_);
4490 TEST_P(SpdySessionTest, SplitHeaders) {
4491 GURL kStreamUrl("http://www.example.org/foo.dat");
4492 SpdyHeaderBlock headers;
4493 spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4494 headers["alpha"] = "beta";
4496 SpdyHeaderBlock request_headers;
4497 SpdyHeaderBlock response_headers;
4499 SplitPushedHeadersToRequestAndResponse(
4500 headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4502 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4503 std::string alpha_val =
4504 (it == response_headers.end()) ? std::string() : it->second;
4505 EXPECT_EQ("beta", alpha_val);
4507 GURL request_url =
4508 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4509 EXPECT_EQ(kStreamUrl, request_url);
4512 // Regression. Sorta. Push streams and client streams were sharing a single
4513 // limit for a long time.
4514 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4515 SettingsMap new_settings;
4516 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4517 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4518 scoped_ptr<SpdyFrame> settings_frame(
4519 spdy_util_.ConstructSpdySettings(new_settings));
4520 scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4521 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4522 MockRead reads[] = {
4523 CreateMockRead(*settings_frame, 0),
4524 MockRead(ASYNC, ERR_IO_PENDING, 3),
4525 CreateMockRead(*pushed, 4),
4526 MockRead(ASYNC, ERR_IO_PENDING, 5),
4527 MockRead(ASYNC, 0, 6),
4530 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4531 scoped_ptr<SpdyFrame> req(
4532 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4533 MockWrite writes[] = {
4534 CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4537 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4538 session_deps_.socket_factory->AddSocketDataProvider(&data);
4540 CreateNetworkSession();
4541 CreateInsecureSpdySession();
4543 // Read the settings frame.
4544 base::RunLoop().RunUntilIdle();
4546 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4547 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4548 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4549 EXPECT_EQ(0u, spdy_stream1->stream_id());
4550 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4551 spdy_stream1->SetDelegate(&delegate1);
4553 EXPECT_EQ(0u, session_->num_active_streams());
4554 EXPECT_EQ(1u, session_->num_created_streams());
4555 EXPECT_EQ(0u, session_->num_pushed_streams());
4556 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4558 scoped_ptr<SpdyHeaderBlock> headers(
4559 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
4560 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4561 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4563 // Run until 1st stream is activated.
4564 EXPECT_EQ(0u, delegate1.stream_id());
4565 base::RunLoop().RunUntilIdle();
4566 EXPECT_EQ(1u, delegate1.stream_id());
4567 EXPECT_EQ(1u, session_->num_active_streams());
4568 EXPECT_EQ(0u, session_->num_created_streams());
4569 EXPECT_EQ(0u, session_->num_pushed_streams());
4570 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4572 // Run until pushed stream is created.
4573 data.CompleteRead();
4574 base::RunLoop().RunUntilIdle();
4575 EXPECT_EQ(2u, session_->num_active_streams());
4576 EXPECT_EQ(0u, session_->num_created_streams());
4577 EXPECT_EQ(1u, session_->num_pushed_streams());
4578 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4580 // Second stream should not be stalled, although we have 2 active streams, but
4581 // one of them is push stream and should not be taken into account when we
4582 // create streams on the client.
4583 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4584 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4585 EXPECT_TRUE(spdy_stream2);
4586 EXPECT_EQ(2u, session_->num_active_streams());
4587 EXPECT_EQ(1u, session_->num_created_streams());
4588 EXPECT_EQ(1u, session_->num_pushed_streams());
4589 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4591 // Read EOF.
4592 data.CompleteRead();
4593 base::RunLoop().RunUntilIdle();
4594 EXPECT_FALSE(session_);
4597 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4598 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4599 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4600 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4601 nullptr, 0, 4, 1, "http://www.example.org/b.dat"));
4602 MockRead reads[] = {
4603 MockRead(ASYNC, ERR_IO_PENDING, 1),
4604 CreateMockRead(*push_a, 2),
4605 MockRead(ASYNC, ERR_IO_PENDING, 3),
4606 CreateMockRead(*push_b, 4),
4607 MockRead(ASYNC, ERR_IO_PENDING, 6),
4608 MockRead(ASYNC, 0, 7),
4611 scoped_ptr<SpdyFrame> req(
4612 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4613 scoped_ptr<SpdyFrame> rst(
4614 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4615 MockWrite writes[] = {
4616 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
4619 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4620 session_deps_.socket_factory->AddSocketDataProvider(&data);
4622 CreateNetworkSession();
4623 CreateInsecureSpdySession();
4624 session_->set_max_concurrent_pushed_streams(1);
4626 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4627 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4628 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4629 EXPECT_EQ(0u, spdy_stream1->stream_id());
4630 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4631 spdy_stream1->SetDelegate(&delegate1);
4633 EXPECT_EQ(0u, session_->num_active_streams());
4634 EXPECT_EQ(1u, session_->num_created_streams());
4635 EXPECT_EQ(0u, session_->num_pushed_streams());
4636 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4638 scoped_ptr<SpdyHeaderBlock> headers(
4639 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
4640 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4641 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4643 // Run until 1st stream is activated.
4644 EXPECT_EQ(0u, delegate1.stream_id());
4645 base::RunLoop().RunUntilIdle();
4646 EXPECT_EQ(1u, delegate1.stream_id());
4647 EXPECT_EQ(1u, session_->num_active_streams());
4648 EXPECT_EQ(0u, session_->num_created_streams());
4649 EXPECT_EQ(0u, session_->num_pushed_streams());
4650 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4652 // Run until pushed stream is created.
4653 data.CompleteRead();
4654 base::RunLoop().RunUntilIdle();
4655 EXPECT_EQ(2u, session_->num_active_streams());
4656 EXPECT_EQ(0u, session_->num_created_streams());
4657 EXPECT_EQ(1u, session_->num_pushed_streams());
4658 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4660 // Reset incoming pushed stream.
4661 data.CompleteRead();
4662 base::RunLoop().RunUntilIdle();
4663 EXPECT_EQ(2u, session_->num_active_streams());
4664 EXPECT_EQ(0u, session_->num_created_streams());
4665 EXPECT_EQ(1u, session_->num_pushed_streams());
4666 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4668 // Read EOF.
4669 data.CompleteRead();
4670 base::RunLoop().RunUntilIdle();
4671 EXPECT_FALSE(session_);
4674 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4675 // Streams in reserved remote state exist only in HTTP/2.
4676 if (spdy_util_.spdy_version() < HTTP2)
4677 return;
4679 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4680 nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
4681 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4682 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/b.dat",
4683 push_headers.get());
4684 scoped_ptr<SpdyFrame> push_b(
4685 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4686 scoped_ptr<SpdyFrame> headers_b(
4687 spdy_util_.ConstructSpdyPushHeaders(4, nullptr, 0));
4688 MockRead reads[] = {
4689 MockRead(ASYNC, ERR_IO_PENDING, 1),
4690 CreateMockRead(*push_a, 2),
4691 MockRead(ASYNC, ERR_IO_PENDING, 3),
4692 CreateMockRead(*push_b, 4),
4693 MockRead(ASYNC, ERR_IO_PENDING, 5),
4694 CreateMockRead(*headers_b, 6),
4695 MockRead(ASYNC, ERR_IO_PENDING, 8),
4696 MockRead(ASYNC, 0, 9),
4699 scoped_ptr<SpdyFrame> req(
4700 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4701 scoped_ptr<SpdyFrame> rst(
4702 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4703 MockWrite writes[] = {
4704 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 7),
4707 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4708 session_deps_.socket_factory->AddSocketDataProvider(&data);
4710 CreateNetworkSession();
4711 CreateInsecureSpdySession();
4712 session_->set_max_concurrent_pushed_streams(1);
4714 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4715 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4716 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4717 EXPECT_EQ(0u, spdy_stream1->stream_id());
4718 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4719 spdy_stream1->SetDelegate(&delegate1);
4721 EXPECT_EQ(0u, session_->num_active_streams());
4722 EXPECT_EQ(1u, session_->num_created_streams());
4723 EXPECT_EQ(0u, session_->num_pushed_streams());
4724 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4726 scoped_ptr<SpdyHeaderBlock> headers(
4727 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
4728 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4729 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4731 // Run until 1st stream is activated.
4732 EXPECT_EQ(0u, delegate1.stream_id());
4733 base::RunLoop().RunUntilIdle();
4734 EXPECT_EQ(1u, delegate1.stream_id());
4735 EXPECT_EQ(1u, session_->num_active_streams());
4736 EXPECT_EQ(0u, session_->num_created_streams());
4737 EXPECT_EQ(0u, session_->num_pushed_streams());
4738 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4740 // Run until pushed stream is created.
4741 data.CompleteRead();
4742 base::RunLoop().RunUntilIdle();
4743 EXPECT_EQ(2u, session_->num_active_streams());
4744 EXPECT_EQ(0u, session_->num_created_streams());
4745 EXPECT_EQ(1u, session_->num_pushed_streams());
4746 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4748 // Accept promised stream. It should not count towards pushed stream limit.
4749 data.CompleteRead();
4750 base::RunLoop().RunUntilIdle();
4751 EXPECT_EQ(3u, session_->num_active_streams());
4752 EXPECT_EQ(0u, session_->num_created_streams());
4753 EXPECT_EQ(2u, session_->num_pushed_streams());
4754 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4756 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4757 // while we accept only one.
4758 data.CompleteRead();
4759 base::RunLoop().RunUntilIdle();
4760 EXPECT_EQ(2u, session_->num_active_streams());
4761 EXPECT_EQ(0u, session_->num_created_streams());
4762 EXPECT_EQ(1u, session_->num_pushed_streams());
4763 EXPECT_EQ(1u, session_->num_active_pushed_streams());
4765 // Read EOF.
4766 data.CompleteRead();
4767 base::RunLoop().RunUntilIdle();
4768 EXPECT_FALSE(session_);
4771 TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
4772 // Streams in reserved remote state exist only in HTTP/2.
4773 if (spdy_util_.spdy_version() < HTTP2)
4774 return;
4776 const char kPushedUrl[] = "http://www.example.org/a.dat";
4777 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4778 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
4779 scoped_ptr<SpdyFrame> push_promise(
4780 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
4781 scoped_ptr<SpdyFrame> headers_frame(
4782 spdy_util_.ConstructSpdyPushHeaders(2, nullptr, 0));
4783 MockRead reads[] = {
4784 MockRead(ASYNC, ERR_IO_PENDING, 1),
4785 CreateMockRead(*push_promise, 2),
4786 MockRead(ASYNC, ERR_IO_PENDING, 3),
4787 CreateMockRead(*headers_frame, 4),
4788 MockRead(ASYNC, ERR_IO_PENDING, 6),
4789 MockRead(ASYNC, 0, 7),
4792 scoped_ptr<SpdyFrame> req(
4793 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
4794 scoped_ptr<SpdyFrame> rst(
4795 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
4796 MockWrite writes[] = {
4797 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
4800 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
4801 session_deps_.socket_factory->AddSocketDataProvider(&data);
4803 CreateNetworkSession();
4804 CreateInsecureSpdySession();
4806 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4807 SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, LOWEST, BoundNetLog());
4808 ASSERT_TRUE(spdy_stream1.get() != nullptr);
4809 EXPECT_EQ(0u, spdy_stream1->stream_id());
4810 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4811 spdy_stream1->SetDelegate(&delegate1);
4813 EXPECT_EQ(0u, session_->num_active_streams());
4814 EXPECT_EQ(1u, session_->num_created_streams());
4815 EXPECT_EQ(0u, session_->num_pushed_streams());
4816 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4818 scoped_ptr<SpdyHeaderBlock> headers(
4819 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
4820 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4821 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4823 // Run until 1st stream is activated.
4824 EXPECT_EQ(0u, delegate1.stream_id());
4825 base::RunLoop().RunUntilIdle();
4826 EXPECT_EQ(1u, delegate1.stream_id());
4827 EXPECT_EQ(1u, session_->num_active_streams());
4828 EXPECT_EQ(0u, session_->num_created_streams());
4829 EXPECT_EQ(0u, session_->num_pushed_streams());
4830 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4832 // Run until pushed stream is created.
4833 data.CompleteRead();
4834 base::RunLoop().RunUntilIdle();
4835 EXPECT_EQ(2u, session_->num_active_streams());
4836 EXPECT_EQ(0u, session_->num_created_streams());
4837 EXPECT_EQ(1u, session_->num_pushed_streams());
4838 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4840 base::WeakPtr<SpdyStream> pushed_stream;
4841 int rv =
4842 session_->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
4843 ASSERT_EQ(OK, rv);
4844 ASSERT_TRUE(pushed_stream.get() != nullptr);
4845 test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
4846 pushed_stream->SetDelegate(&delegate2);
4848 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4849 // that all our counters are in consistent state.
4850 data.CompleteRead();
4851 base::RunLoop().RunUntilIdle();
4852 EXPECT_EQ(1u, session_->num_active_streams());
4853 EXPECT_EQ(0u, session_->num_created_streams());
4854 EXPECT_EQ(0u, session_->num_pushed_streams());
4855 EXPECT_EQ(0u, session_->num_active_pushed_streams());
4857 // Read EOF.
4858 data.CompleteRead();
4859 base::RunLoop().RunUntilIdle();
4860 EXPECT_TRUE(data.AllWriteDataConsumed());
4861 EXPECT_TRUE(data.AllReadDataConsumed());
4864 TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
4865 session_deps_.host_resolver->set_synchronous_mode(true);
4867 MockRead reads[] = {
4868 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
4871 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
4872 session_deps_.socket_factory->AddSocketDataProvider(&data);
4874 CreateNetworkSession();
4875 CreateInsecureSpdySession();
4877 session_->stream_hi_water_mark_ = 5;
4878 // Low client (odd) ids are fine.
4879 EXPECT_TRUE(session_->OnUnknownFrame(3, 0));
4880 // Client id exceeding watermark.
4881 EXPECT_FALSE(session_->OnUnknownFrame(9, 0));
4883 session_->last_accepted_push_stream_id_ = 6;
4884 // Low server (even) ids are fine.
4885 EXPECT_TRUE(session_->OnUnknownFrame(2, 0));
4886 // Server id exceeding last accepted id.
4887 EXPECT_FALSE(session_->OnUnknownFrame(8, 0));
4890 TEST(MapFramerErrorToProtocolError, MapsValues) {
4891 CHECK_EQ(
4892 SPDY_ERROR_INVALID_CONTROL_FRAME,
4893 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4894 CHECK_EQ(
4895 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4896 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4897 CHECK_EQ(
4898 SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
4899 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
4900 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
4901 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
4904 TEST(MapFramerErrorToNetError, MapsValue) {
4905 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
4906 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4907 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4908 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
4909 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4910 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4911 CHECK_EQ(
4912 ERR_SPDY_FRAME_SIZE_ERROR,
4913 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
4916 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
4917 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
4918 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
4919 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
4920 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
4921 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
4922 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
4923 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY,
4924 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY));
4925 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED,
4926 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED));
4929 TEST(MapNetErrorToGoAwayStatus, MapsValue) {
4930 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
4931 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
4932 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
4933 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
4934 CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
4935 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
4936 CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
4937 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
4938 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
4939 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
4940 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
4943 TEST(CanPoolTest, CanPool) {
4944 // Load a cert that is valid for:
4945 // www.example.org
4946 // mail.example.org
4947 // www.example.com
4949 TransportSecurityState tss;
4950 SSLInfo ssl_info;
4951 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
4952 "spdy_pooling.pem");
4954 EXPECT_TRUE(SpdySession::CanPool(
4955 &tss, ssl_info, "www.example.org", "www.example.org"));
4956 EXPECT_TRUE(SpdySession::CanPool(
4957 &tss, ssl_info, "www.example.org", "mail.example.org"));
4958 EXPECT_TRUE(SpdySession::CanPool(
4959 &tss, ssl_info, "www.example.org", "mail.example.com"));
4960 EXPECT_FALSE(SpdySession::CanPool(
4961 &tss, ssl_info, "www.example.org", "mail.google.com"));
4964 TEST(CanPoolTest, CanNotPoolWithCertErrors) {
4965 // Load a cert that is valid for:
4966 // www.example.org
4967 // mail.example.org
4968 // www.example.com
4970 TransportSecurityState tss;
4971 SSLInfo ssl_info;
4972 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
4973 "spdy_pooling.pem");
4974 ssl_info.cert_status = CERT_STATUS_REVOKED;
4976 EXPECT_FALSE(SpdySession::CanPool(
4977 &tss, ssl_info, "www.example.org", "mail.example.org"));
4980 TEST(CanPoolTest, CanNotPoolWithClientCerts) {
4981 // Load a cert that is valid for:
4982 // www.example.org
4983 // mail.example.org
4984 // www.example.com
4986 TransportSecurityState tss;
4987 SSLInfo ssl_info;
4988 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
4989 "spdy_pooling.pem");
4990 ssl_info.client_cert_sent = true;
4992 EXPECT_FALSE(SpdySession::CanPool(
4993 &tss, ssl_info, "www.example.org", "mail.example.org"));
4996 TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
4997 // Load a cert that is valid for:
4998 // www.example.org
4999 // mail.example.org
5000 // www.example.com
5002 TransportSecurityState tss;
5003 SSLInfo ssl_info;
5004 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5005 "spdy_pooling.pem");
5006 ssl_info.channel_id_sent = true;
5008 EXPECT_TRUE(SpdySession::CanPool(
5009 &tss, ssl_info, "www.example.org", "mail.example.org"));
5010 EXPECT_FALSE(SpdySession::CanPool(
5011 &tss, ssl_info, "www.example.org", "www.example.com"));
5014 TEST(CanPoolTest, CanNotPoolWithBadPins) {
5015 uint8 primary_pin = 1;
5016 uint8 backup_pin = 2;
5017 uint8 bad_pin = 3;
5018 TransportSecurityState tss;
5019 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5021 SSLInfo ssl_info;
5022 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5023 "spdy_pooling.pem");
5024 ssl_info.is_issued_by_known_root = true;
5025 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
5027 EXPECT_FALSE(SpdySession::CanPool(
5028 &tss, ssl_info, "www.example.org", "mail.example.org"));
5031 TEST(CanPoolTest, CanPoolWithAcceptablePins) {
5032 uint8 primary_pin = 1;
5033 uint8 backup_pin = 2;
5034 TransportSecurityState tss;
5035 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5037 SSLInfo ssl_info;
5038 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5039 "spdy_pooling.pem");
5040 ssl_info.is_issued_by_known_root = true;
5041 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
5043 EXPECT_TRUE(SpdySession::CanPool(
5044 &tss, ssl_info, "www.example.org", "mail.example.org"));
5047 } // namespace net