Rename InputLatency::ScrollUpdate to Latency::ScrollUpdate
[chromium-blink-merge.git] / net / spdy / spdy_session_unittest.cc
bloba47060653ed8a4600972818db7698306d2cf6938
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/net_log_unittest.h"
19 #include "net/socket/client_socket_pool_manager.h"
20 #include "net/socket/next_proto.h"
21 #include "net/socket/socket_test_util.h"
22 #include "net/spdy/spdy_http_utils.h"
23 #include "net/spdy/spdy_session_pool.h"
24 #include "net/spdy/spdy_session_test_util.h"
25 #include "net/spdy/spdy_stream.h"
26 #include "net/spdy/spdy_stream_test_util.h"
27 #include "net/spdy/spdy_test_util_common.h"
28 #include "net/spdy/spdy_test_utils.h"
29 #include "net/test/cert_test_util.h"
30 #include "testing/platform_test.h"
32 namespace net {
34 namespace {
36 static const char kTestUrl[] = "http://www.example.org/";
37 static const char kTestHost[] = "www.example.org";
38 static const int kTestPort = 80;
40 const char kBodyData[] = "Body data";
41 const size_t kBodyDataSize = arraysize(kBodyData);
42 const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize);
44 static base::TimeDelta g_time_delta;
45 base::TimeTicks TheNearFuture() {
46 return base::TimeTicks::Now() + g_time_delta;
49 } // namespace
51 class SpdySessionTest : public PlatformTest,
52 public ::testing::WithParamInterface<NextProto> {
53 public:
54 // Functions used with RunResumeAfterUnstallTest().
56 void StallSessionOnly(SpdySession* session, SpdyStream* stream) {
57 StallSessionSend(session);
60 void StallStreamOnly(SpdySession* session, SpdyStream* stream) {
61 StallStreamSend(stream);
64 void StallSessionStream(SpdySession* session, SpdyStream* stream) {
65 StallSessionSend(session);
66 StallStreamSend(stream);
69 void StallStreamSession(SpdySession* session, SpdyStream* stream) {
70 StallStreamSend(stream);
71 StallSessionSend(session);
74 void UnstallSessionOnly(SpdySession* session,
75 SpdyStream* stream,
76 int32 delta_window_size) {
77 UnstallSessionSend(session, delta_window_size);
80 void UnstallStreamOnly(SpdySession* session,
81 SpdyStream* stream,
82 int32 delta_window_size) {
83 UnstallStreamSend(stream, delta_window_size);
86 void UnstallSessionStream(SpdySession* session,
87 SpdyStream* stream,
88 int32 delta_window_size) {
89 UnstallSessionSend(session, delta_window_size);
90 UnstallStreamSend(stream, delta_window_size);
93 void UnstallStreamSession(SpdySession* session,
94 SpdyStream* stream,
95 int32 delta_window_size) {
96 UnstallStreamSend(stream, delta_window_size);
97 UnstallSessionSend(session, delta_window_size);
100 protected:
101 SpdySessionTest()
102 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
103 HttpNetworkSession::NORMAL_SOCKET_POOL)),
104 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
105 HttpNetworkSession::NORMAL_SOCKET_POOL)),
106 spdy_util_(GetParam()),
107 session_deps_(GetParam()),
108 spdy_session_pool_(NULL),
109 test_url_(kTestUrl),
110 test_host_port_pair_(kTestHost, kTestPort),
111 key_(test_host_port_pair_, ProxyServer::Direct(),
112 PRIVACY_MODE_DISABLED) {
115 virtual ~SpdySessionTest() {
116 // Important to restore the per-pool limit first, since the pool limit must
117 // always be greater than group limit, and the tests reduce both limits.
118 ClientSocketPoolManager::set_max_sockets_per_pool(
119 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
120 ClientSocketPoolManager::set_max_sockets_per_group(
121 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
124 void SetUp() override { g_time_delta = base::TimeDelta(); }
126 void CreateDeterministicNetworkSession() {
127 http_session_ =
128 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
129 spdy_session_pool_ = http_session_->spdy_session_pool();
132 void CreateNetworkSession() {
133 http_session_ =
134 SpdySessionDependencies::SpdyCreateSession(&session_deps_);
135 spdy_session_pool_ = http_session_->spdy_session_pool();
138 void StallSessionSend(SpdySession* session) {
139 // Reduce the send window size to 0 to stall.
140 while (session->session_send_window_size_ > 0) {
141 session->DecreaseSendWindowSize(
142 std::min(kMaxSpdyFrameChunkSize, session->session_send_window_size_));
146 void UnstallSessionSend(SpdySession* session, int32 delta_window_size) {
147 session->IncreaseSendWindowSize(delta_window_size);
150 void StallStreamSend(SpdyStream* stream) {
151 // Reduce the send window size to 0 to stall.
152 while (stream->send_window_size() > 0) {
153 stream->DecreaseSendWindowSize(
154 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
158 void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) {
159 stream->IncreaseSendWindowSize(delta_window_size);
162 void RunResumeAfterUnstallTest(
163 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
164 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
165 unstall_function);
167 // Original socket limits. Some tests set these. Safest to always restore
168 // them once each test has been run.
169 int old_max_group_sockets_;
170 int old_max_pool_sockets_;
172 SpdyTestUtil spdy_util_;
173 SpdySessionDependencies session_deps_;
174 scoped_refptr<HttpNetworkSession> http_session_;
175 SpdySessionPool* spdy_session_pool_;
176 GURL test_url_;
177 HostPortPair test_host_port_pair_;
178 SpdySessionKey key_;
181 INSTANTIATE_TEST_CASE_P(NextProto,
182 SpdySessionTest,
183 testing::Values(kProtoSPDY31,
184 kProtoSPDY4_14,
185 kProtoSPDY4));
187 // Try to create a SPDY session that will fail during
188 // initialization. Nothing should blow up.
189 TEST_P(SpdySessionTest, InitialReadError) {
190 CreateDeterministicNetworkSession();
192 base::WeakPtr<SpdySession> session = TryCreateFakeSpdySessionExpectingFailure(
193 spdy_session_pool_, key_, ERR_CONNECTION_CLOSED);
194 EXPECT_TRUE(session);
195 // Flush the read.
196 base::RunLoop().RunUntilIdle();
197 EXPECT_FALSE(session);
200 namespace {
202 // A helper class that vends a callback that, when fired, destroys a
203 // given SpdyStreamRequest.
204 class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
205 public:
206 StreamRequestDestroyingCallback() {}
208 ~StreamRequestDestroyingCallback() override {}
210 void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) {
211 request_ = request.Pass();
214 CompletionCallback MakeCallback() {
215 return base::Bind(&StreamRequestDestroyingCallback::OnComplete,
216 base::Unretained(this));
219 private:
220 void OnComplete(int result) {
221 request_.reset();
222 SetResult(result);
225 scoped_ptr<SpdyStreamRequest> request_;
228 } // namespace
230 // Request kInitialMaxConcurrentStreams streams. Request two more
231 // streams, but have the callback for one destroy the second stream
232 // request. Close the session. Nothing should blow up. This is a
233 // regression test for http://crbug.com/250841 .
234 TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
235 session_deps_.host_resolver->set_synchronous_mode(true);
237 MockRead reads[] = {MockRead(ASYNC, 0, 0), };
239 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
240 MockConnect connect_data(SYNCHRONOUS, OK);
241 data.set_connect_data(connect_data);
242 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
244 CreateDeterministicNetworkSession();
246 base::WeakPtr<SpdySession> session =
247 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
249 // Create the maximum number of concurrent streams.
250 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
251 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
252 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog());
253 ASSERT_TRUE(spdy_stream != NULL);
256 SpdyStreamRequest request1;
257 scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest);
259 StreamRequestDestroyingCallback callback1;
260 ASSERT_EQ(ERR_IO_PENDING,
261 request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM,
262 session,
263 test_url_,
264 MEDIUM,
265 BoundNetLog(),
266 callback1.MakeCallback()));
268 // |callback2| is never called.
269 TestCompletionCallback callback2;
270 ASSERT_EQ(ERR_IO_PENDING,
271 request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM,
272 session,
273 test_url_,
274 MEDIUM,
275 BoundNetLog(),
276 callback2.callback()));
278 callback1.SetRequestToDestroy(request2.Pass());
280 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
282 EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
285 // A session receiving a GOAWAY frame with no active streams should close.
286 TEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
287 session_deps_.host_resolver->set_synchronous_mode(true);
289 MockConnect connect_data(SYNCHRONOUS, OK);
290 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
291 MockRead reads[] = {
292 CreateMockRead(*goaway, 0),
294 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
295 data.set_connect_data(connect_data);
296 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
298 CreateDeterministicNetworkSession();
300 base::WeakPtr<SpdySession> session =
301 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
303 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
305 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
307 // Read and process the GOAWAY frame.
308 data.RunFor(1);
309 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
310 base::RunLoop().RunUntilIdle();
311 EXPECT_TRUE(session == NULL);
314 // A session receiving a GOAWAY frame immediately with no active
315 // streams should then close.
316 TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
317 session_deps_.host_resolver->set_synchronous_mode(true);
319 MockConnect connect_data(SYNCHRONOUS, OK);
320 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
321 MockRead reads[] = {
322 CreateMockRead(*goaway, 0, SYNCHRONOUS),
324 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
325 data.set_connect_data(connect_data);
326 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
328 CreateDeterministicNetworkSession();
330 data.StopAfter(1);
332 base::WeakPtr<SpdySession> session =
333 TryCreateInsecureSpdySessionExpectingFailure(
334 http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
335 base::RunLoop().RunUntilIdle();
337 EXPECT_FALSE(session);
338 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
341 // A session receiving a GOAWAY frame with active streams should close
342 // when the last active stream is closed.
343 TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
344 session_deps_.host_resolver->set_synchronous_mode(true);
346 MockConnect connect_data(SYNCHRONOUS, OK);
347 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
348 MockRead reads[] = {
349 CreateMockRead(*goaway, 2),
350 MockRead(ASYNC, 0, 3) // EOF
352 scoped_ptr<SpdyFrame> req1(
353 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
354 scoped_ptr<SpdyFrame> req2(
355 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
356 MockWrite writes[] = {
357 CreateMockWrite(*req1, 0),
358 CreateMockWrite(*req2, 1),
360 DeterministicSocketData data(reads, arraysize(reads),
361 writes, arraysize(writes));
362 data.set_connect_data(connect_data);
363 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
365 CreateDeterministicNetworkSession();
367 base::WeakPtr<SpdySession> session =
368 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
370 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
372 GURL url(kDefaultURL);
373 base::WeakPtr<SpdyStream> spdy_stream1 =
374 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
375 session, url, MEDIUM, BoundNetLog());
376 test::StreamDelegateDoNothing delegate1(spdy_stream1);
377 spdy_stream1->SetDelegate(&delegate1);
379 base::WeakPtr<SpdyStream> spdy_stream2 =
380 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
381 session, url, MEDIUM, BoundNetLog());
382 test::StreamDelegateDoNothing delegate2(spdy_stream2);
383 spdy_stream2->SetDelegate(&delegate2);
385 scoped_ptr<SpdyHeaderBlock> headers(
386 spdy_util_.ConstructGetHeaderBlock(url.spec()));
387 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
389 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
390 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
391 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
392 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
394 data.RunFor(2);
396 EXPECT_EQ(1u, spdy_stream1->stream_id());
397 EXPECT_EQ(3u, spdy_stream2->stream_id());
399 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
401 // Read and process the GOAWAY frame.
402 data.RunFor(1);
404 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
406 EXPECT_FALSE(session->IsStreamActive(3));
407 EXPECT_EQ(NULL, spdy_stream2.get());
408 EXPECT_TRUE(session->IsStreamActive(1));
410 EXPECT_TRUE(session->IsGoingAway());
412 // Should close the session.
413 spdy_stream1->Close();
414 EXPECT_EQ(NULL, spdy_stream1.get());
416 base::MessageLoop::current()->RunUntilIdle();
417 EXPECT_TRUE(session == NULL);
420 // Have a session receive two GOAWAY frames, with the last one causing
421 // the last active stream to be closed. The session should then be
422 // closed after the second GOAWAY frame.
423 TEST_P(SpdySessionTest, GoAwayTwice) {
424 session_deps_.host_resolver->set_synchronous_mode(true);
426 MockConnect connect_data(SYNCHRONOUS, OK);
427 scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
428 scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
429 MockRead reads[] = {
430 CreateMockRead(*goaway1, 2),
431 CreateMockRead(*goaway2, 3),
432 MockRead(ASYNC, 0, 4) // EOF
434 scoped_ptr<SpdyFrame> req1(
435 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
436 scoped_ptr<SpdyFrame> req2(
437 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
438 MockWrite writes[] = {
439 CreateMockWrite(*req1, 0),
440 CreateMockWrite(*req2, 1),
442 DeterministicSocketData data(reads, arraysize(reads),
443 writes, arraysize(writes));
444 data.set_connect_data(connect_data);
445 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
447 CreateDeterministicNetworkSession();
449 base::WeakPtr<SpdySession> session =
450 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
452 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
454 GURL url(kDefaultURL);
455 base::WeakPtr<SpdyStream> spdy_stream1 =
456 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
457 session, url, MEDIUM, BoundNetLog());
458 test::StreamDelegateDoNothing delegate1(spdy_stream1);
459 spdy_stream1->SetDelegate(&delegate1);
461 base::WeakPtr<SpdyStream> spdy_stream2 =
462 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
463 session, url, MEDIUM, BoundNetLog());
464 test::StreamDelegateDoNothing delegate2(spdy_stream2);
465 spdy_stream2->SetDelegate(&delegate2);
467 scoped_ptr<SpdyHeaderBlock> headers(
468 spdy_util_.ConstructGetHeaderBlock(url.spec()));
469 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
471 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
472 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
473 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
474 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
476 data.RunFor(2);
478 EXPECT_EQ(1u, spdy_stream1->stream_id());
479 EXPECT_EQ(3u, spdy_stream2->stream_id());
481 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
483 // Read and process the first GOAWAY frame.
484 data.RunFor(1);
486 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
488 EXPECT_FALSE(session->IsStreamActive(3));
489 EXPECT_EQ(NULL, spdy_stream2.get());
490 EXPECT_TRUE(session->IsStreamActive(1));
491 EXPECT_TRUE(session->IsGoingAway());
493 // Read and process the second GOAWAY frame, which should close the
494 // session.
495 data.RunFor(1);
496 base::MessageLoop::current()->RunUntilIdle();
497 EXPECT_TRUE(session == NULL);
500 // Have a session with active streams receive a GOAWAY frame and then
501 // close it. It should handle the close properly (i.e., not try to
502 // make itself unavailable in its pool twice).
503 TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
504 session_deps_.host_resolver->set_synchronous_mode(true);
506 MockConnect connect_data(SYNCHRONOUS, OK);
507 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
508 MockRead reads[] = {
509 CreateMockRead(*goaway, 2),
510 MockRead(ASYNC, 0, 3) // EOF
512 scoped_ptr<SpdyFrame> req1(
513 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
514 scoped_ptr<SpdyFrame> req2(
515 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
516 MockWrite writes[] = {
517 CreateMockWrite(*req1, 0),
518 CreateMockWrite(*req2, 1),
520 DeterministicSocketData data(reads, arraysize(reads),
521 writes, arraysize(writes));
522 data.set_connect_data(connect_data);
523 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
525 CreateDeterministicNetworkSession();
527 base::WeakPtr<SpdySession> session =
528 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
530 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
532 GURL url(kDefaultURL);
533 base::WeakPtr<SpdyStream> spdy_stream1 =
534 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
535 session, url, MEDIUM, BoundNetLog());
536 test::StreamDelegateDoNothing delegate1(spdy_stream1);
537 spdy_stream1->SetDelegate(&delegate1);
539 base::WeakPtr<SpdyStream> spdy_stream2 =
540 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
541 session, url, MEDIUM, BoundNetLog());
542 test::StreamDelegateDoNothing delegate2(spdy_stream2);
543 spdy_stream2->SetDelegate(&delegate2);
545 scoped_ptr<SpdyHeaderBlock> headers(
546 spdy_util_.ConstructGetHeaderBlock(url.spec()));
547 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
549 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
550 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
551 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
552 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
554 data.RunFor(2);
556 EXPECT_EQ(1u, spdy_stream1->stream_id());
557 EXPECT_EQ(3u, spdy_stream2->stream_id());
559 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
561 // Read and process the GOAWAY frame.
562 data.RunFor(1);
564 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
566 EXPECT_FALSE(session->IsStreamActive(3));
567 EXPECT_EQ(NULL, spdy_stream2.get());
568 EXPECT_TRUE(session->IsStreamActive(1));
569 EXPECT_TRUE(session->IsGoingAway());
571 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
572 EXPECT_EQ(NULL, spdy_stream1.get());
574 base::MessageLoop::current()->RunUntilIdle();
575 EXPECT_TRUE(session == NULL);
578 // Process a joint read buffer which causes the session to begin draining, and
579 // then processes a GOAWAY. The session should gracefully drain. Regression test
580 // for crbug.com/379469
581 TEST_P(SpdySessionTest, GoAwayWhileDraining) {
582 session_deps_.host_resolver->set_synchronous_mode(true);
584 scoped_ptr<SpdyFrame> req(
585 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
586 MockWrite writes[] = {
587 CreateMockWrite(*req, 0),
590 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
591 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
592 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
593 size_t joint_size = goaway->size() * 2 + body->size();
595 // Compose interleaved |goaway| and |body| frames into a single read.
596 scoped_ptr<char[]> buffer(new char[joint_size]);
598 size_t out = 0;
599 memcpy(&buffer[out], goaway->data(), goaway->size());
600 out += goaway->size();
601 memcpy(&buffer[out], body->data(), body->size());
602 out += body->size();
603 memcpy(&buffer[out], goaway->data(), goaway->size());
604 out += goaway->size();
605 ASSERT_EQ(out, joint_size);
607 SpdyFrame joint_frames(buffer.get(), joint_size, false);
609 MockRead reads[] = {
610 CreateMockRead(*resp, 1), CreateMockRead(joint_frames, 2),
611 MockRead(ASYNC, 0, 3) // EOF
614 MockConnect connect_data(SYNCHRONOUS, OK);
615 DeterministicSocketData data(
616 reads, arraysize(reads), writes, arraysize(writes));
617 data.set_connect_data(connect_data);
618 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
620 CreateDeterministicNetworkSession();
621 base::WeakPtr<SpdySession> session =
622 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
624 GURL url(kDefaultURL);
625 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
626 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
627 test::StreamDelegateDoNothing delegate(spdy_stream);
628 spdy_stream->SetDelegate(&delegate);
630 scoped_ptr<SpdyHeaderBlock> headers(
631 spdy_util_.ConstructGetHeaderBlock(url.spec()));
632 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
633 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
635 data.RunFor(3);
636 base::MessageLoop::current()->RunUntilIdle();
638 // Stream and session closed gracefully.
639 EXPECT_TRUE(delegate.StreamIsClosed());
640 EXPECT_EQ(OK, delegate.WaitForClose());
641 EXPECT_EQ(kUploadData, delegate.TakeReceivedData());
642 EXPECT_TRUE(session == NULL);
645 // Try to create a stream after receiving a GOAWAY frame. It should
646 // fail.
647 TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
648 session_deps_.host_resolver->set_synchronous_mode(true);
650 MockConnect connect_data(SYNCHRONOUS, OK);
651 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
652 MockRead reads[] = {
653 CreateMockRead(*goaway, 1),
654 MockRead(ASYNC, 0, 2) // EOF
656 scoped_ptr<SpdyFrame> req(
657 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
658 MockWrite writes[] = {
659 CreateMockWrite(*req, 0),
661 DeterministicSocketData data(reads, arraysize(reads),
662 writes, arraysize(writes));
663 data.set_connect_data(connect_data);
664 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
666 CreateDeterministicNetworkSession();
668 base::WeakPtr<SpdySession> session =
669 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
671 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
673 GURL url(kDefaultURL);
674 base::WeakPtr<SpdyStream> spdy_stream =
675 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
676 session, url, MEDIUM, BoundNetLog());
677 test::StreamDelegateDoNothing delegate(spdy_stream);
678 spdy_stream->SetDelegate(&delegate);
680 scoped_ptr<SpdyHeaderBlock> headers(
681 spdy_util_.ConstructGetHeaderBlock(url.spec()));
682 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
683 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
685 data.RunFor(1);
687 EXPECT_EQ(1u, spdy_stream->stream_id());
689 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
691 // Read and process the GOAWAY frame.
692 data.RunFor(1);
694 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
695 EXPECT_TRUE(session->IsStreamActive(1));
697 SpdyStreamRequest stream_request;
698 int rv = stream_request.StartRequest(
699 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog(),
700 CompletionCallback());
701 EXPECT_EQ(ERR_FAILED, rv);
703 // Read and process EOF.
704 data.RunFor(1);
706 EXPECT_TRUE(session == NULL);
709 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
710 // the stream being refused.
711 TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
712 session_deps_.host_resolver->set_synchronous_mode(true);
714 MockConnect connect_data(SYNCHRONOUS, OK);
715 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
716 scoped_ptr<SpdyFrame>
717 push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kDefaultURL));
718 MockRead reads[] = {
719 CreateMockRead(*goaway, 1),
720 CreateMockRead(*push, 2),
721 MockRead(ASYNC, 0, 4) // EOF
723 scoped_ptr<SpdyFrame> req(
724 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
725 scoped_ptr<SpdyFrame> rst(
726 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
727 MockWrite writes[] = {
728 CreateMockWrite(*req, 0),
729 CreateMockWrite(*rst, 3)
731 DeterministicSocketData data(reads, arraysize(reads),
732 writes, arraysize(writes));
733 data.set_connect_data(connect_data);
734 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
736 CreateDeterministicNetworkSession();
738 base::WeakPtr<SpdySession> session =
739 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
741 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
743 GURL url(kDefaultURL);
744 base::WeakPtr<SpdyStream> spdy_stream =
745 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
746 session, url, MEDIUM, BoundNetLog());
747 test::StreamDelegateDoNothing delegate(spdy_stream);
748 spdy_stream->SetDelegate(&delegate);
750 scoped_ptr<SpdyHeaderBlock> headers(
751 spdy_util_.ConstructGetHeaderBlock(url.spec()));
752 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
753 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
755 data.RunFor(1);
757 EXPECT_EQ(1u, spdy_stream->stream_id());
759 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
761 // Read and process the GOAWAY frame.
762 data.RunFor(1);
764 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
765 EXPECT_TRUE(session->IsStreamActive(1));
767 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
768 // and EOF.
769 data.RunFor(3);
770 base::MessageLoop::current()->RunUntilIdle();
771 EXPECT_TRUE(session == NULL);
774 // A session observing a network change with active streams should close
775 // when the last active stream is closed.
776 TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
777 session_deps_.host_resolver->set_synchronous_mode(true);
779 MockConnect connect_data(SYNCHRONOUS, OK);
780 MockRead reads[] = {
781 MockRead(ASYNC, 0, 1) // EOF
783 scoped_ptr<SpdyFrame> req1(
784 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
785 MockWrite writes[] = {
786 CreateMockWrite(*req1, 0),
788 DeterministicSocketData data(reads, arraysize(reads),
789 writes, arraysize(writes));
790 data.set_connect_data(connect_data);
791 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
793 CreateDeterministicNetworkSession();
795 base::WeakPtr<SpdySession> session =
796 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
798 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
800 base::WeakPtr<SpdyStream> spdy_stream =
801 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session,
802 GURL(kDefaultURL), MEDIUM, BoundNetLog());
803 test::StreamDelegateDoNothing delegate(spdy_stream);
804 spdy_stream->SetDelegate(&delegate);
806 scoped_ptr<SpdyHeaderBlock> headers(
807 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
809 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
810 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
812 data.RunFor(1);
814 EXPECT_EQ(1u, spdy_stream->stream_id());
816 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
818 spdy_session_pool_->OnIPAddressChanged();
820 // The SpdySessionPool behavior differs based on how the OSs reacts to
821 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
822 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
823 // For OSs where the TCP connections will close upon relevant network
824 // changes, SpdySessionPool doesn't need to force them to close, so in these
825 // cases verify the session has become unavailable but remains open and the
826 // pre-existing stream is still active.
827 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
829 EXPECT_TRUE(session->IsGoingAway());
831 EXPECT_TRUE(session->IsStreamActive(1));
833 // Should close the session.
834 spdy_stream->Close();
835 #endif
836 EXPECT_EQ(NULL, spdy_stream.get());
838 base::MessageLoop::current()->RunUntilIdle();
839 EXPECT_TRUE(session == NULL);
842 TEST_P(SpdySessionTest, ClientPing) {
843 session_deps_.enable_ping = true;
844 session_deps_.host_resolver->set_synchronous_mode(true);
846 MockConnect connect_data(SYNCHRONOUS, OK);
847 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
848 MockRead reads[] = {
849 CreateMockRead(*read_ping, 1),
850 MockRead(ASYNC, 0, 0, 2) // EOF
852 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
853 MockWrite writes[] = {
854 CreateMockWrite(*write_ping, 0),
856 DeterministicSocketData data(
857 reads, arraysize(reads), writes, arraysize(writes));
858 data.set_connect_data(connect_data);
859 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
861 CreateDeterministicNetworkSession();
863 base::WeakPtr<SpdySession> session =
864 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
866 base::WeakPtr<SpdyStream> spdy_stream1 =
867 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
868 session, test_url_, MEDIUM, BoundNetLog());
869 ASSERT_TRUE(spdy_stream1.get() != NULL);
870 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
871 spdy_stream1->SetDelegate(&delegate);
873 base::TimeTicks before_ping_time = base::TimeTicks::Now();
875 session->set_connection_at_risk_of_loss_time(
876 base::TimeDelta::FromSeconds(-1));
877 session->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
879 session->SendPrefacePingIfNoneInFlight();
881 data.RunFor(2);
883 session->CheckPingStatus(before_ping_time);
885 EXPECT_EQ(0, session->pings_in_flight());
886 EXPECT_GE(session->next_ping_id(), 1U);
887 EXPECT_FALSE(session->check_ping_status_pending());
888 EXPECT_GE(session->last_activity_time(), before_ping_time);
890 data.RunFor(1);
892 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
894 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
895 EXPECT_TRUE(session == NULL);
898 TEST_P(SpdySessionTest, ServerPing) {
899 session_deps_.host_resolver->set_synchronous_mode(true);
901 MockConnect connect_data(SYNCHRONOUS, OK);
902 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
903 MockRead reads[] = {
904 CreateMockRead(*read_ping),
905 MockRead(SYNCHRONOUS, 0, 0) // EOF
907 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
908 MockWrite writes[] = {
909 CreateMockWrite(*write_ping),
911 StaticSocketDataProvider data(
912 reads, arraysize(reads), writes, arraysize(writes));
913 data.set_connect_data(connect_data);
914 session_deps_.socket_factory->AddSocketDataProvider(&data);
916 CreateNetworkSession();
918 base::WeakPtr<SpdySession> session =
919 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
921 base::WeakPtr<SpdyStream> spdy_stream1 =
922 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
923 session, test_url_, MEDIUM, BoundNetLog());
924 ASSERT_TRUE(spdy_stream1.get() != NULL);
925 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
926 spdy_stream1->SetDelegate(&delegate);
928 // Flush the read completion task.
929 base::MessageLoop::current()->RunUntilIdle();
931 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
933 EXPECT_TRUE(session == NULL);
934 EXPECT_EQ(NULL, spdy_stream1.get());
937 // Cause a ping to be sent out while producing a write. The write loop
938 // should handle this properly, i.e. another DoWriteLoop task should
939 // not be posted. This is a regression test for
940 // http://crbug.com/261043 .
941 TEST_P(SpdySessionTest, PingAndWriteLoop) {
942 session_deps_.enable_ping = true;
943 session_deps_.time_func = TheNearFuture;
945 MockConnect connect_data(SYNCHRONOUS, OK);
946 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
947 scoped_ptr<SpdyFrame> req(
948 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
949 MockWrite writes[] = {
950 CreateMockWrite(*req, 0),
951 CreateMockWrite(*write_ping, 1),
954 MockRead reads[] = {
955 MockRead(ASYNC, 0, 2) // EOF
958 session_deps_.host_resolver->set_synchronous_mode(true);
960 DeterministicSocketData data(reads, arraysize(reads),
961 writes, arraysize(writes));
962 data.set_connect_data(connect_data);
963 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
965 CreateDeterministicNetworkSession();
967 base::WeakPtr<SpdySession> session =
968 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
970 GURL url(kDefaultURL);
971 base::WeakPtr<SpdyStream> spdy_stream =
972 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
973 session, url, LOWEST, BoundNetLog());
974 test::StreamDelegateDoNothing delegate(spdy_stream);
975 spdy_stream->SetDelegate(&delegate);
977 scoped_ptr<SpdyHeaderBlock> headers(
978 spdy_util_.ConstructGetHeaderBlock(url.spec()));
979 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
981 // Shift time so that a ping will be sent out.
982 g_time_delta = base::TimeDelta::FromSeconds(11);
984 data.RunFor(2);
986 session->CloseSessionOnError(ERR_ABORTED, "Aborting");
989 TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
990 const SpdyStreamId kLastStreamId = 0x7fffffff;
991 session_deps_.host_resolver->set_synchronous_mode(true);
993 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
994 // fixed to allow for two stream ID assignments, and three concurrent
995 // streams. Four streams are started, and two are activated. Verify the
996 // session goes away, and that the created (but not activated) and
997 // stalled streams are aborted. Also verify the activated streams complete,
998 // at which point the session closes.
1000 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
1001 NULL, 0, false, kLastStreamId - 2, MEDIUM, true));
1002 scoped_ptr<SpdyFrame> req2(
1003 spdy_util_.ConstructSpdyGet(NULL, 0, false, kLastStreamId, MEDIUM, true));
1005 MockWrite writes[] = {
1006 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
1009 scoped_ptr<SpdyFrame> resp1(
1010 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId - 2));
1011 scoped_ptr<SpdyFrame> resp2(
1012 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId));
1014 scoped_ptr<SpdyFrame> body1(
1015 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
1016 scoped_ptr<SpdyFrame> body2(
1017 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
1019 MockRead reads[] = {
1020 CreateMockRead(*resp1, 2), CreateMockRead(*resp2, 3),
1021 CreateMockRead(*body1, 4), CreateMockRead(*body2, 5),
1022 MockRead(ASYNC, 0, 6) // EOF
1025 DeterministicSocketData data(
1026 reads, arraysize(reads), writes, arraysize(writes));
1028 MockConnect connect_data(SYNCHRONOUS, OK);
1029 data.set_connect_data(connect_data);
1030 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1032 CreateDeterministicNetworkSession();
1033 base::WeakPtr<SpdySession> session =
1034 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1036 // Fix stream_hi_water_mark_ to allow for two stream activations.
1037 session->stream_hi_water_mark_ = kLastStreamId - 2;
1038 // Fix max_concurrent_streams to allow for three stream creations.
1039 session->max_concurrent_streams_ = 3;
1041 // Create three streams synchronously, and begin a fourth (which is stalled).
1042 GURL url(kDefaultURL);
1043 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1044 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1045 test::StreamDelegateDoNothing delegate1(stream1);
1046 stream1->SetDelegate(&delegate1);
1048 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
1049 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1050 test::StreamDelegateDoNothing delegate2(stream2);
1051 stream2->SetDelegate(&delegate2);
1053 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1054 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1055 test::StreamDelegateDoNothing delegate3(stream3);
1056 stream3->SetDelegate(&delegate3);
1058 SpdyStreamRequest request4;
1059 TestCompletionCallback callback4;
1060 EXPECT_EQ(ERR_IO_PENDING,
1061 request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1062 session,
1063 url,
1064 MEDIUM,
1065 BoundNetLog(),
1066 callback4.callback()));
1068 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1069 EXPECT_EQ(0u, session->num_active_streams());
1070 EXPECT_EQ(3u, session->num_created_streams());
1071 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1073 // Activate stream 1. One ID remains available.
1074 stream1->SendRequestHeaders(
1075 scoped_ptr<SpdyHeaderBlock>(
1076 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1077 NO_MORE_DATA_TO_SEND);
1078 data.RunFor(1);
1080 EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1081 EXPECT_EQ(1u, session->num_active_streams());
1082 EXPECT_EQ(2u, session->num_created_streams());
1083 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1085 // Activate stream 2. ID space is exhausted.
1086 stream2->SendRequestHeaders(
1087 scoped_ptr<SpdyHeaderBlock>(
1088 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1089 NO_MORE_DATA_TO_SEND);
1090 data.RunFor(1);
1092 // Active streams remain active.
1093 EXPECT_EQ(kLastStreamId, stream2->stream_id());
1094 EXPECT_EQ(2u, session->num_active_streams());
1096 // Session is going away. Created and stalled streams were aborted.
1097 EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session->availability_state_);
1098 EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose());
1099 EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult());
1100 EXPECT_EQ(0u, session->num_created_streams());
1101 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1103 // Read responses on remaining active streams.
1104 data.RunFor(4);
1105 EXPECT_EQ(OK, delegate1.WaitForClose());
1106 EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1107 EXPECT_EQ(OK, delegate2.WaitForClose());
1108 EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1110 // Session was destroyed.
1111 base::MessageLoop::current()->RunUntilIdle();
1112 EXPECT_FALSE(session.get());
1115 // Verifies that an unstalled pending stream creation racing with a new stream
1116 // creation doesn't violate the maximum stream concurrency. Regression test for
1117 // crbug.com/373858.
1118 TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) {
1119 session_deps_.host_resolver->set_synchronous_mode(true);
1121 MockRead reads[] = {
1122 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1125 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1127 MockConnect connect_data(SYNCHRONOUS, OK);
1128 data.set_connect_data(connect_data);
1129 session_deps_.socket_factory->AddSocketDataProvider(&data);
1131 CreateNetworkSession();
1132 base::WeakPtr<SpdySession> session =
1133 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1135 // Fix max_concurrent_streams to allow for one open stream.
1136 session->max_concurrent_streams_ = 1;
1138 // Create two streams: one synchronously, and one which stalls.
1139 GURL url(kDefaultURL);
1140 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1141 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1143 SpdyStreamRequest request2;
1144 TestCompletionCallback callback2;
1145 EXPECT_EQ(ERR_IO_PENDING,
1146 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1147 session,
1148 url,
1149 MEDIUM,
1150 BoundNetLog(),
1151 callback2.callback()));
1153 EXPECT_EQ(1u, session->num_created_streams());
1154 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1156 // Cancel the first stream. A callback to unstall the second stream was
1157 // posted. Don't run it yet.
1158 stream1->Cancel();
1160 EXPECT_EQ(0u, session->num_created_streams());
1161 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1163 // Create a third stream prior to the second stream's callback.
1164 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1165 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1167 EXPECT_EQ(1u, session->num_created_streams());
1168 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1170 // NOW run the message loop. The unstalled stream will re-stall itself.
1171 base::MessageLoop::current()->RunUntilIdle();
1172 EXPECT_EQ(1u, session->num_created_streams());
1173 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1175 // Cancel the third stream and run the message loop. Verify that the second
1176 // stream creation now completes.
1177 stream3->Cancel();
1178 base::MessageLoop::current()->RunUntilIdle();
1180 EXPECT_EQ(1u, session->num_created_streams());
1181 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1182 EXPECT_EQ(OK, callback2.WaitForResult());
1185 TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
1186 session_deps_.host_resolver->set_synchronous_mode(true);
1187 session_deps_.time_func = TheNearFuture;
1189 scoped_ptr<SpdyFrame> req(
1190 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1191 scoped_ptr<SpdyFrame> rst(
1192 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
1194 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
1195 NULL, 0, 2, 1, "http://www.example.org/a.dat"));
1196 scoped_ptr<SpdyFrame> push_a_body(
1197 spdy_util_.ConstructSpdyBodyFrame(2, false));
1198 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1199 // iterators inside. See http://crbug.com/443490
1200 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
1201 NULL, 0, 4, 1, "http://www.example.org/0.dat"));
1202 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)};
1203 MockRead reads[] = {
1204 CreateMockRead(*push_a, 1), CreateMockRead(*push_a_body, 2),
1205 CreateMockRead(*push_b, 3), MockRead(ASYNC, 0, 5), // EOF
1207 DeterministicSocketData data(
1208 reads, arraysize(reads), writes, arraysize(writes));
1210 MockConnect connect_data(SYNCHRONOUS, OK);
1211 data.set_connect_data(connect_data);
1212 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1214 CreateDeterministicNetworkSession();
1215 base::WeakPtr<SpdySession> session =
1216 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1218 // Process the principal request, and the first push stream request & body.
1219 GURL url(kDefaultURL);
1220 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1221 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1222 test::StreamDelegateDoNothing delegate(spdy_stream);
1223 spdy_stream->SetDelegate(&delegate);
1225 scoped_ptr<SpdyHeaderBlock> headers(
1226 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1227 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1229 data.RunFor(3);
1231 // Verify that there is one unclaimed push stream.
1232 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1233 SpdySession::PushedStreamMap::iterator iter =
1234 session->unclaimed_pushed_streams_.find(
1235 GURL("http://www.example.org/a.dat"));
1236 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1238 if (session->flow_control_state_ ==
1239 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1240 // Unclaimed push body consumed bytes from the session window.
1241 EXPECT_EQ(
1242 SpdySession::GetDefaultInitialWindowSize(GetParam()) - kUploadDataSize,
1243 session->session_recv_window_size_);
1244 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
1247 // Shift time to expire the push stream. Read the second SYN_STREAM,
1248 // and verify a RST_STREAM was written.
1249 g_time_delta = base::TimeDelta::FromSeconds(301);
1250 data.RunFor(2);
1252 // Verify that the second pushed stream evicted the first pushed stream.
1253 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1254 iter = session->unclaimed_pushed_streams_.find(
1255 GURL("http://www.example.org/0.dat"));
1256 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1258 if (session->flow_control_state_ ==
1259 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1260 // Verify that the session window reclaimed the evicted stream body.
1261 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
1262 session->session_recv_window_size_);
1263 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
1266 // Read and process EOF.
1267 data.RunFor(1);
1268 base::MessageLoop::current()->RunUntilIdle();
1269 EXPECT_TRUE(session == NULL);
1272 TEST_P(SpdySessionTest, FailedPing) {
1273 session_deps_.host_resolver->set_synchronous_mode(true);
1275 MockConnect connect_data(SYNCHRONOUS, OK);
1276 MockRead reads[] = {
1277 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1279 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
1280 scoped_ptr<SpdyFrame> goaway(
1281 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping."));
1282 MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)};
1283 StaticSocketDataProvider data(
1284 reads, arraysize(reads), writes, arraysize(writes));
1285 data.set_connect_data(connect_data);
1286 session_deps_.socket_factory->AddSocketDataProvider(&data);
1288 CreateNetworkSession();
1290 base::WeakPtr<SpdySession> session =
1291 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1293 base::WeakPtr<SpdyStream> spdy_stream1 =
1294 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1295 session, test_url_, MEDIUM, BoundNetLog());
1296 ASSERT_TRUE(spdy_stream1.get() != NULL);
1297 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
1298 spdy_stream1->SetDelegate(&delegate);
1300 session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1301 session->set_hung_interval(base::TimeDelta::FromSeconds(0));
1303 // Send a PING frame.
1304 session->WritePingFrame(1, false);
1305 EXPECT_LT(0, session->pings_in_flight());
1306 EXPECT_GE(session->next_ping_id(), 1U);
1307 EXPECT_TRUE(session->check_ping_status_pending());
1309 // Assert session is not closed.
1310 EXPECT_TRUE(session->IsAvailable());
1311 EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams());
1312 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1314 // We set last time we have received any data in 1 sec less than now.
1315 // CheckPingStatus will trigger timeout because hung interval is zero.
1316 base::TimeTicks now = base::TimeTicks::Now();
1317 session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
1318 session->CheckPingStatus(now);
1319 base::MessageLoop::current()->RunUntilIdle();
1321 EXPECT_TRUE(session == NULL);
1322 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1323 EXPECT_EQ(NULL, spdy_stream1.get());
1326 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1327 // settings frame increasing the max concurrent streams by 1. Make
1328 // sure nothing blows up. This is a regression test for
1329 // http://crbug.com/57331 .
1330 TEST_P(SpdySessionTest, OnSettings) {
1331 session_deps_.host_resolver->set_synchronous_mode(true);
1333 const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1335 SettingsMap new_settings;
1336 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1337 new_settings[kSpdySettingsIds] =
1338 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1339 scoped_ptr<SpdyFrame> settings_frame(
1340 spdy_util_.ConstructSpdySettings(new_settings));
1341 MockRead reads[] = {
1342 CreateMockRead(*settings_frame, 0),
1343 MockRead(ASYNC, 0, 1),
1346 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1347 MockWrite writes[] = {
1348 CreateMockWrite(*settings_ack, 2),
1351 DeterministicSocketData data(reads, arraysize(reads),
1352 writes, arraysize(writes));
1353 MockConnect connect_data(SYNCHRONOUS, OK);
1354 data.set_connect_data(connect_data);
1355 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1357 CreateDeterministicNetworkSession();
1359 base::WeakPtr<SpdySession> session =
1360 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1362 // Create the maximum number of concurrent streams.
1363 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1364 base::WeakPtr<SpdyStream> spdy_stream =
1365 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1366 session, test_url_, MEDIUM, BoundNetLog());
1367 ASSERT_TRUE(spdy_stream != NULL);
1370 StreamReleaserCallback stream_releaser;
1371 SpdyStreamRequest request;
1372 ASSERT_EQ(ERR_IO_PENDING,
1373 request.StartRequest(
1374 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1375 BoundNetLog(),
1376 stream_releaser.MakeCallback(&request)));
1378 data.RunFor(1);
1380 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1382 data.RunFor(1);
1383 if (spdy_util_.spdy_version() >= SPDY4) {
1384 // Allow the SETTINGS+ACK to write, so the session finishes draining.
1385 data.RunFor(1);
1387 base::MessageLoop::current()->RunUntilIdle();
1388 EXPECT_TRUE(session == NULL);
1391 // Start with a persisted value for max concurrent streams. Receive a
1392 // settings frame increasing the max concurrent streams by 1 and which
1393 // also clears the persisted data. Verify that persisted data is
1394 // correct.
1395 TEST_P(SpdySessionTest, ClearSettings) {
1396 if (spdy_util_.spdy_version() >= SPDY4) {
1397 // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1398 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4.
1399 return;
1401 session_deps_.host_resolver->set_synchronous_mode(true);
1403 SettingsMap new_settings;
1404 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1405 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1406 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1407 scoped_ptr<SpdyFrame> settings_frame(
1408 spdy_util_.ConstructSpdySettings(new_settings));
1409 uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1410 test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1411 MockRead reads[] = {
1412 CreateMockRead(*settings_frame, 0),
1413 MockRead(ASYNC, 0, 1),
1416 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
1417 MockConnect connect_data(SYNCHRONOUS, OK);
1418 data.set_connect_data(connect_data);
1419 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1421 CreateDeterministicNetworkSession();
1423 // Initialize the SpdySetting with the default.
1424 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1425 test_host_port_pair_,
1426 SETTINGS_MAX_CONCURRENT_STREAMS,
1427 SETTINGS_FLAG_PLEASE_PERSIST,
1428 kInitialMaxConcurrentStreams);
1430 EXPECT_FALSE(
1431 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1432 test_host_port_pair_).empty());
1434 base::WeakPtr<SpdySession> session =
1435 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1437 // Create the maximum number of concurrent streams.
1438 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1439 base::WeakPtr<SpdyStream> spdy_stream =
1440 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1441 session, test_url_, MEDIUM, BoundNetLog());
1442 ASSERT_TRUE(spdy_stream != NULL);
1445 StreamReleaserCallback stream_releaser;
1447 SpdyStreamRequest request;
1448 ASSERT_EQ(ERR_IO_PENDING,
1449 request.StartRequest(
1450 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1451 BoundNetLog(),
1452 stream_releaser.MakeCallback(&request)));
1454 data.RunFor(1);
1456 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1458 // Make sure that persisted data is cleared.
1459 EXPECT_TRUE(
1460 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1461 test_host_port_pair_).empty());
1463 // Make sure session's max_concurrent_streams is correct.
1464 EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1465 session->max_concurrent_streams());
1467 data.RunFor(1);
1468 EXPECT_TRUE(session == NULL);
1471 // Start with max concurrent streams set to 1. Request two streams.
1472 // When the first completes, have the callback close its stream, which
1473 // should trigger the second stream creation. Then cancel that one
1474 // immediately. Don't crash. This is a regression test for
1475 // http://crbug.com/63532 .
1476 TEST_P(SpdySessionTest, CancelPendingCreateStream) {
1477 session_deps_.host_resolver->set_synchronous_mode(true);
1479 MockRead reads[] = {
1480 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1483 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1484 MockConnect connect_data(SYNCHRONOUS, OK);
1486 data.set_connect_data(connect_data);
1487 session_deps_.socket_factory->AddSocketDataProvider(&data);
1489 CreateNetworkSession();
1491 // Initialize the SpdySetting with 1 max concurrent streams.
1492 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1493 test_host_port_pair_,
1494 SETTINGS_MAX_CONCURRENT_STREAMS,
1495 SETTINGS_FLAG_PLEASE_PERSIST,
1498 base::WeakPtr<SpdySession> session =
1499 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1501 // Leave room for only one more stream to be created.
1502 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1503 base::WeakPtr<SpdyStream> spdy_stream =
1504 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1505 session, test_url_, MEDIUM, BoundNetLog());
1506 ASSERT_TRUE(spdy_stream != NULL);
1509 // Create 2 more streams. First will succeed. Second will be pending.
1510 base::WeakPtr<SpdyStream> spdy_stream1 =
1511 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1512 session, test_url_, MEDIUM, BoundNetLog());
1513 ASSERT_TRUE(spdy_stream1.get() != NULL);
1515 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1516 // a valgrind error if the callback is invoked when it's not supposed to be.
1517 scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
1519 SpdyStreamRequest request;
1520 ASSERT_EQ(ERR_IO_PENDING,
1521 request.StartRequest(
1522 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1523 BoundNetLog(),
1524 callback->callback()));
1526 // Release the first one, this will allow the second to be created.
1527 spdy_stream1->Cancel();
1528 EXPECT_EQ(NULL, spdy_stream1.get());
1530 request.CancelRequest();
1531 callback.reset();
1533 // Should not crash when running the pending callback.
1534 base::MessageLoop::current()->RunUntilIdle();
1537 TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
1538 session_deps_.host_resolver->set_synchronous_mode(true);
1540 MockRead reads[] = {
1541 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1544 SettingsMap settings;
1545 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1546 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
1547 MockConnect connect_data(SYNCHRONOUS, OK);
1548 scoped_ptr<SpdyFrame> settings_frame(
1549 spdy_util_.ConstructSpdySettings(settings));
1550 std::vector<MockWrite> writes;
1551 if ((GetParam() >= kProtoSPDY4MinimumVersion) &&
1552 (GetParam() <= kProtoSPDY4MaximumVersion)) {
1553 writes.push_back(
1554 MockWrite(ASYNC,
1555 kHttp2ConnectionHeaderPrefix,
1556 kHttp2ConnectionHeaderPrefixSize));
1558 writes.push_back(CreateMockWrite(*settings_frame));
1560 SettingsMap server_settings;
1561 const uint32 initial_max_concurrent_streams = 1;
1562 server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1563 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1564 initial_max_concurrent_streams);
1565 scoped_ptr<SpdyFrame> server_settings_frame(
1566 spdy_util_.ConstructSpdySettings(server_settings));
1567 if (GetParam() <= kProtoSPDY31) {
1568 writes.push_back(CreateMockWrite(*server_settings_frame));
1571 StaticSocketDataProvider data(reads, arraysize(reads),
1572 vector_as_array(&writes), writes.size());
1573 data.set_connect_data(connect_data);
1574 session_deps_.socket_factory->AddSocketDataProvider(&data);
1576 CreateNetworkSession();
1578 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1579 test_host_port_pair_,
1580 SETTINGS_MAX_CONCURRENT_STREAMS,
1581 SETTINGS_FLAG_PLEASE_PERSIST,
1582 initial_max_concurrent_streams);
1584 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1585 pool_peer.SetEnableSendingInitialData(true);
1587 base::WeakPtr<SpdySession> session =
1588 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1590 base::MessageLoop::current()->RunUntilIdle();
1591 EXPECT_TRUE(data.at_write_eof());
1594 TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
1595 CreateNetworkSession();
1597 base::WeakPtr<HttpServerProperties> test_http_server_properties =
1598 spdy_session_pool_->http_server_properties();
1599 SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
1600 test_http_server_properties->SetSpdySetting(
1601 test_host_port_pair_,
1602 SETTINGS_MAX_CONCURRENT_STREAMS,
1603 SETTINGS_FLAG_PLEASE_PERSIST,
1605 EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
1606 test_host_port_pair_).size());
1607 spdy_session_pool_->OnIPAddressChanged();
1608 EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
1609 test_host_port_pair_).size());
1612 TEST_P(SpdySessionTest, Initialize) {
1613 BoundTestNetLog log;
1614 session_deps_.net_log = log.bound().net_log();
1615 session_deps_.host_resolver->set_synchronous_mode(true);
1617 MockConnect connect_data(SYNCHRONOUS, OK);
1618 MockRead reads[] = {
1619 MockRead(ASYNC, 0, 0) // EOF
1622 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1623 data.set_connect_data(connect_data);
1624 session_deps_.socket_factory->AddSocketDataProvider(&data);
1626 CreateNetworkSession();
1628 base::WeakPtr<SpdySession> session =
1629 CreateInsecureSpdySession(http_session_, key_, log.bound());
1630 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1632 // Flush the read completion task.
1633 base::MessageLoop::current()->RunUntilIdle();
1635 net::TestNetLog::CapturedEntryList entries;
1636 log.GetEntries(&entries);
1637 EXPECT_LT(0u, entries.size());
1639 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1640 int pos = net::ExpectLogContainsSomewhere(
1641 entries, 0, net::NetLog::TYPE_HTTP2_SESSION_INITIALIZED,
1642 net::NetLog::PHASE_NONE);
1643 EXPECT_LT(0, pos);
1645 TestNetLog::CapturedEntry entry = entries[pos];
1646 NetLog::Source socket_source;
1647 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1648 &socket_source));
1649 EXPECT_TRUE(socket_source.IsValid());
1650 EXPECT_NE(log.bound().source().id, socket_source.id);
1653 TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
1654 session_deps_.host_resolver->set_synchronous_mode(true);
1656 MockConnect connect_data(SYNCHRONOUS, OK);
1657 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
1658 MockRead reads[] = {
1659 CreateMockRead(*goaway),
1660 MockRead(SYNCHRONOUS, 0, 0) // EOF
1663 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1664 data.set_connect_data(connect_data);
1665 session_deps_.socket_factory->AddSocketDataProvider(&data);
1667 CreateNetworkSession();
1669 BoundTestNetLog log;
1670 base::WeakPtr<SpdySession> session =
1671 CreateInsecureSpdySession(http_session_, key_, log.bound());
1672 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1674 // Flush the read completion task.
1675 base::MessageLoop::current()->RunUntilIdle();
1677 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1678 EXPECT_TRUE(session == NULL);
1680 // Check that the NetLog was filled reasonably.
1681 net::TestNetLog::CapturedEntryList entries;
1682 log.GetEntries(&entries);
1683 EXPECT_LT(0u, entries.size());
1685 // Check that we logged SPDY_SESSION_CLOSE correctly.
1686 int pos = net::ExpectLogContainsSomewhere(
1687 entries, 0, net::NetLog::TYPE_HTTP2_SESSION_CLOSE,
1688 net::NetLog::PHASE_NONE);
1690 if (pos < static_cast<int>(entries.size())) {
1691 TestNetLog::CapturedEntry entry = entries[pos];
1692 int error_code = 0;
1693 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1694 EXPECT_EQ(OK, error_code);
1695 } else {
1696 ADD_FAILURE();
1700 TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1701 session_deps_.host_resolver->set_synchronous_mode(true);
1703 MockConnect connect_data(SYNCHRONOUS, OK);
1704 MockRead reads[] = {
1705 MockRead(SYNCHRONOUS, 0, 0) // EOF
1708 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1709 data.set_connect_data(connect_data);
1710 session_deps_.socket_factory->AddSocketDataProvider(&data);
1712 CreateNetworkSession();
1714 BoundTestNetLog log;
1715 base::WeakPtr<SpdySession> session =
1716 CreateInsecureSpdySession(http_session_, key_, log.bound());
1717 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1719 // Flush the read completion task.
1720 base::MessageLoop::current()->RunUntilIdle();
1722 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1723 EXPECT_TRUE(session == NULL);
1725 // Check that the NetLog was filled reasonably.
1726 net::TestNetLog::CapturedEntryList entries;
1727 log.GetEntries(&entries);
1728 EXPECT_LT(0u, entries.size());
1730 // Check that we logged SPDY_SESSION_CLOSE correctly.
1731 int pos = net::ExpectLogContainsSomewhere(
1732 entries, 0, net::NetLog::TYPE_HTTP2_SESSION_CLOSE,
1733 net::NetLog::PHASE_NONE);
1735 if (pos < static_cast<int>(entries.size())) {
1736 TestNetLog::CapturedEntry entry = entries[pos];
1737 int error_code = 0;
1738 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1739 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1740 } else {
1741 ADD_FAILURE();
1745 TEST_P(SpdySessionTest, SynCompressionHistograms) {
1746 session_deps_.enable_compression = true;
1748 scoped_ptr<SpdyFrame> req(
1749 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, MEDIUM, true));
1750 MockWrite writes[] = {
1751 CreateMockWrite(*req, 0),
1753 MockRead reads[] = {
1754 MockRead(ASYNC, 0, 1) // EOF
1756 DeterministicSocketData data(reads, arraysize(reads),
1757 writes, arraysize(writes));
1758 MockConnect connect_data(SYNCHRONOUS, OK);
1759 data.set_connect_data(connect_data);
1760 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1762 CreateDeterministicNetworkSession();
1763 base::WeakPtr<SpdySession> session =
1764 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1766 GURL url(kDefaultURL);
1767 base::WeakPtr<SpdyStream> spdy_stream =
1768 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1769 session, url, MEDIUM, BoundNetLog());
1770 test::StreamDelegateDoNothing delegate(spdy_stream);
1771 spdy_stream->SetDelegate(&delegate);
1773 scoped_ptr<SpdyHeaderBlock> headers(
1774 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1775 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1776 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1778 // Write request headers & capture resulting histogram update.
1779 base::HistogramTester histogram_tester;
1781 data.RunFor(1);
1782 // Regression test of compression performance under the request fixture.
1783 switch (spdy_util_.spdy_version()) {
1784 case SPDY3:
1785 histogram_tester.ExpectBucketCount(
1786 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1787 break;
1788 case SPDY4:
1789 histogram_tester.ExpectBucketCount(
1790 "Net.SpdySynStreamCompressionPercentage", 81, 1);
1791 break;
1792 default:
1793 NOTREACHED();
1796 // Read and process EOF.
1797 data.RunFor(1);
1798 base::MessageLoop::current()->RunUntilIdle();
1799 EXPECT_TRUE(session == NULL);
1802 // Queue up a low-priority SYN_STREAM followed by a high-priority
1803 // one. The high priority one should still send first and receive
1804 // first.
1805 TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1806 // Construct the request.
1807 MockConnect connect_data(SYNCHRONOUS, OK);
1808 scoped_ptr<SpdyFrame> req_highest(
1809 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true));
1810 scoped_ptr<SpdyFrame> req_lowest(
1811 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1812 MockWrite writes[] = {
1813 CreateMockWrite(*req_highest, 0),
1814 CreateMockWrite(*req_lowest, 1),
1817 scoped_ptr<SpdyFrame> resp_highest(
1818 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1819 scoped_ptr<SpdyFrame> body_highest(
1820 spdy_util_.ConstructSpdyBodyFrame(1, true));
1821 scoped_ptr<SpdyFrame> resp_lowest(
1822 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1823 scoped_ptr<SpdyFrame> body_lowest(
1824 spdy_util_.ConstructSpdyBodyFrame(3, true));
1825 MockRead reads[] = {
1826 CreateMockRead(*resp_highest, 2),
1827 CreateMockRead(*body_highest, 3),
1828 CreateMockRead(*resp_lowest, 4),
1829 CreateMockRead(*body_lowest, 5),
1830 MockRead(ASYNC, 0, 6) // EOF
1833 session_deps_.host_resolver->set_synchronous_mode(true);
1835 DeterministicSocketData data(reads, arraysize(reads),
1836 writes, arraysize(writes));
1837 data.set_connect_data(connect_data);
1838 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1840 CreateDeterministicNetworkSession();
1842 base::WeakPtr<SpdySession> session =
1843 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1845 GURL url(kDefaultURL);
1847 base::WeakPtr<SpdyStream> spdy_stream_lowest =
1848 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1849 session, url, LOWEST, BoundNetLog());
1850 ASSERT_TRUE(spdy_stream_lowest);
1851 EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1852 test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1853 spdy_stream_lowest->SetDelegate(&delegate_lowest);
1855 base::WeakPtr<SpdyStream> spdy_stream_highest =
1856 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1857 session, url, HIGHEST, BoundNetLog());
1858 ASSERT_TRUE(spdy_stream_highest);
1859 EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1860 test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1861 spdy_stream_highest->SetDelegate(&delegate_highest);
1863 // Queue the lower priority one first.
1865 scoped_ptr<SpdyHeaderBlock> headers_lowest(
1866 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1867 spdy_stream_lowest->SendRequestHeaders(
1868 headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1869 EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1871 scoped_ptr<SpdyHeaderBlock> headers_highest(
1872 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1873 spdy_stream_highest->SendRequestHeaders(
1874 headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1875 EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1877 data.RunFor(7);
1879 EXPECT_FALSE(spdy_stream_lowest);
1880 EXPECT_FALSE(spdy_stream_highest);
1881 EXPECT_EQ(3u, delegate_lowest.stream_id());
1882 EXPECT_EQ(1u, delegate_highest.stream_id());
1885 TEST_P(SpdySessionTest, CancelStream) {
1886 MockConnect connect_data(SYNCHRONOUS, OK);
1887 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1888 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1889 scoped_ptr<SpdyFrame> req2(
1890 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1891 MockWrite writes[] = {
1892 CreateMockWrite(*req2, 0),
1895 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1896 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1897 MockRead reads[] = {
1898 CreateMockRead(*resp2, 1),
1899 CreateMockRead(*body2, 2),
1900 MockRead(ASYNC, 0, 3) // EOF
1903 session_deps_.host_resolver->set_synchronous_mode(true);
1905 DeterministicSocketData data(reads, arraysize(reads),
1906 writes, arraysize(writes));
1907 data.set_connect_data(connect_data);
1908 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1910 CreateDeterministicNetworkSession();
1912 base::WeakPtr<SpdySession> session =
1913 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1915 GURL url1(kDefaultURL);
1916 base::WeakPtr<SpdyStream> spdy_stream1 =
1917 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1918 session, url1, HIGHEST, BoundNetLog());
1919 ASSERT_TRUE(spdy_stream1.get() != NULL);
1920 EXPECT_EQ(0u, spdy_stream1->stream_id());
1921 test::StreamDelegateDoNothing delegate1(spdy_stream1);
1922 spdy_stream1->SetDelegate(&delegate1);
1924 GURL url2(kDefaultURL);
1925 base::WeakPtr<SpdyStream> spdy_stream2 =
1926 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1927 session, url2, LOWEST, BoundNetLog());
1928 ASSERT_TRUE(spdy_stream2.get() != NULL);
1929 EXPECT_EQ(0u, spdy_stream2->stream_id());
1930 test::StreamDelegateDoNothing delegate2(spdy_stream2);
1931 spdy_stream2->SetDelegate(&delegate2);
1933 scoped_ptr<SpdyHeaderBlock> headers(
1934 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1935 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1936 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1938 scoped_ptr<SpdyHeaderBlock> headers2(
1939 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1940 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1941 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1943 EXPECT_EQ(0u, spdy_stream1->stream_id());
1945 spdy_stream1->Cancel();
1946 EXPECT_EQ(NULL, spdy_stream1.get());
1948 EXPECT_EQ(0u, delegate1.stream_id());
1950 data.RunFor(1);
1952 EXPECT_EQ(0u, delegate1.stream_id());
1953 EXPECT_EQ(1u, delegate2.stream_id());
1955 spdy_stream2->Cancel();
1956 EXPECT_EQ(NULL, spdy_stream2.get());
1959 // Create two streams that are set to re-close themselves on close,
1960 // and then close the session. Nothing should blow up. Also a
1961 // regression test for http://crbug.com/139518 .
1962 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1963 session_deps_.host_resolver->set_synchronous_mode(true);
1965 MockConnect connect_data(SYNCHRONOUS, OK);
1967 // No actual data will be sent.
1968 MockWrite writes[] = {
1969 MockWrite(ASYNC, 0, 1) // EOF
1972 MockRead reads[] = {
1973 MockRead(ASYNC, 0, 0) // EOF
1975 DeterministicSocketData data(reads, arraysize(reads),
1976 writes, arraysize(writes));
1977 data.set_connect_data(connect_data);
1978 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1980 CreateDeterministicNetworkSession();
1982 base::WeakPtr<SpdySession> session =
1983 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1985 GURL url1(kDefaultURL);
1986 base::WeakPtr<SpdyStream> spdy_stream1 =
1987 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1988 session, url1, HIGHEST, BoundNetLog());
1989 ASSERT_TRUE(spdy_stream1.get() != NULL);
1990 EXPECT_EQ(0u, spdy_stream1->stream_id());
1992 GURL url2(kDefaultURL);
1993 base::WeakPtr<SpdyStream> spdy_stream2 =
1994 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1995 session, url2, LOWEST, BoundNetLog());
1996 ASSERT_TRUE(spdy_stream2.get() != NULL);
1997 EXPECT_EQ(0u, spdy_stream2->stream_id());
1999 test::ClosingDelegate delegate1(spdy_stream1);
2000 spdy_stream1->SetDelegate(&delegate1);
2002 test::ClosingDelegate delegate2(spdy_stream2);
2003 spdy_stream2->SetDelegate(&delegate2);
2005 scoped_ptr<SpdyHeaderBlock> headers(
2006 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2007 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2008 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2010 scoped_ptr<SpdyHeaderBlock> headers2(
2011 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2012 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2013 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2015 // Ensure that the streams have not yet been activated and assigned an id.
2016 EXPECT_EQ(0u, spdy_stream1->stream_id());
2017 EXPECT_EQ(0u, spdy_stream2->stream_id());
2019 // Ensure we don't crash while closing the session.
2020 session->CloseSessionOnError(ERR_ABORTED, std::string());
2022 EXPECT_EQ(NULL, spdy_stream1.get());
2023 EXPECT_EQ(NULL, spdy_stream2.get());
2025 EXPECT_TRUE(delegate1.StreamIsClosed());
2026 EXPECT_TRUE(delegate2.StreamIsClosed());
2028 base::MessageLoop::current()->RunUntilIdle();
2029 EXPECT_TRUE(session == NULL);
2032 // Create two streams that are set to close each other on close, and
2033 // then close the session. Nothing should blow up.
2034 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
2035 session_deps_.host_resolver->set_synchronous_mode(true);
2037 MockConnect connect_data(SYNCHRONOUS, OK);
2039 // No actual data will be sent.
2040 MockWrite writes[] = {
2041 MockWrite(ASYNC, 0, 1) // EOF
2044 MockRead reads[] = {
2045 MockRead(ASYNC, 0, 0) // EOF
2047 DeterministicSocketData data(reads, arraysize(reads),
2048 writes, arraysize(writes));
2049 data.set_connect_data(connect_data);
2050 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2052 CreateDeterministicNetworkSession();
2054 base::WeakPtr<SpdySession> session =
2055 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2057 GURL url1(kDefaultURL);
2058 base::WeakPtr<SpdyStream> spdy_stream1 =
2059 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2060 session, url1, HIGHEST, BoundNetLog());
2061 ASSERT_TRUE(spdy_stream1.get() != NULL);
2062 EXPECT_EQ(0u, spdy_stream1->stream_id());
2064 GURL url2(kDefaultURL);
2065 base::WeakPtr<SpdyStream> spdy_stream2 =
2066 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2067 session, url2, LOWEST, BoundNetLog());
2068 ASSERT_TRUE(spdy_stream2.get() != NULL);
2069 EXPECT_EQ(0u, spdy_stream2->stream_id());
2071 // Make |spdy_stream1| close |spdy_stream2|.
2072 test::ClosingDelegate delegate1(spdy_stream2);
2073 spdy_stream1->SetDelegate(&delegate1);
2075 // Make |spdy_stream2| close |spdy_stream1|.
2076 test::ClosingDelegate delegate2(spdy_stream1);
2077 spdy_stream2->SetDelegate(&delegate2);
2079 scoped_ptr<SpdyHeaderBlock> headers(
2080 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2081 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2082 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2084 scoped_ptr<SpdyHeaderBlock> headers2(
2085 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2086 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2087 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2089 // Ensure that the streams have not yet been activated and assigned an id.
2090 EXPECT_EQ(0u, spdy_stream1->stream_id());
2091 EXPECT_EQ(0u, spdy_stream2->stream_id());
2093 // Ensure we don't crash while closing the session.
2094 session->CloseSessionOnError(ERR_ABORTED, std::string());
2096 EXPECT_EQ(NULL, spdy_stream1.get());
2097 EXPECT_EQ(NULL, spdy_stream2.get());
2099 EXPECT_TRUE(delegate1.StreamIsClosed());
2100 EXPECT_TRUE(delegate2.StreamIsClosed());
2102 base::MessageLoop::current()->RunUntilIdle();
2103 EXPECT_TRUE(session == NULL);
2106 // Create two streams that are set to re-close themselves on close,
2107 // activate them, and then close the session. Nothing should blow up.
2108 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
2109 session_deps_.host_resolver->set_synchronous_mode(true);
2111 MockConnect connect_data(SYNCHRONOUS, OK);
2113 scoped_ptr<SpdyFrame> req1(
2114 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2115 scoped_ptr<SpdyFrame> req2(
2116 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2117 MockWrite writes[] = {
2118 CreateMockWrite(*req1, 0),
2119 CreateMockWrite(*req2, 1),
2122 MockRead reads[] = {
2123 MockRead(ASYNC, 0, 2) // EOF
2126 DeterministicSocketData data(reads, arraysize(reads),
2127 writes, arraysize(writes));
2128 data.set_connect_data(connect_data);
2129 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2131 CreateDeterministicNetworkSession();
2133 base::WeakPtr<SpdySession> session =
2134 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2136 GURL url1(kDefaultURL);
2137 base::WeakPtr<SpdyStream> spdy_stream1 =
2138 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2139 session, url1, MEDIUM, BoundNetLog());
2140 ASSERT_TRUE(spdy_stream1.get() != NULL);
2141 EXPECT_EQ(0u, spdy_stream1->stream_id());
2143 GURL url2(kDefaultURL);
2144 base::WeakPtr<SpdyStream> spdy_stream2 =
2145 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2146 session, url2, MEDIUM, BoundNetLog());
2147 ASSERT_TRUE(spdy_stream2.get() != NULL);
2148 EXPECT_EQ(0u, spdy_stream2->stream_id());
2150 test::ClosingDelegate delegate1(spdy_stream1);
2151 spdy_stream1->SetDelegate(&delegate1);
2153 test::ClosingDelegate delegate2(spdy_stream2);
2154 spdy_stream2->SetDelegate(&delegate2);
2156 scoped_ptr<SpdyHeaderBlock> headers(
2157 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2158 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2159 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2161 scoped_ptr<SpdyHeaderBlock> headers2(
2162 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2163 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2164 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2166 // Ensure that the streams have not yet been activated and assigned an id.
2167 EXPECT_EQ(0u, spdy_stream1->stream_id());
2168 EXPECT_EQ(0u, spdy_stream2->stream_id());
2170 data.RunFor(2);
2172 EXPECT_EQ(1u, spdy_stream1->stream_id());
2173 EXPECT_EQ(3u, spdy_stream2->stream_id());
2175 // Ensure we don't crash while closing the session.
2176 session->CloseSessionOnError(ERR_ABORTED, std::string());
2178 EXPECT_EQ(NULL, spdy_stream1.get());
2179 EXPECT_EQ(NULL, spdy_stream2.get());
2181 EXPECT_TRUE(delegate1.StreamIsClosed());
2182 EXPECT_TRUE(delegate2.StreamIsClosed());
2184 base::MessageLoop::current()->RunUntilIdle();
2185 EXPECT_TRUE(session == NULL);
2188 // Create two streams that are set to close each other on close,
2189 // activate them, and then close the session. Nothing should blow up.
2190 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2191 session_deps_.host_resolver->set_synchronous_mode(true);
2193 MockConnect connect_data(SYNCHRONOUS, OK);
2195 scoped_ptr<SpdyFrame> req1(
2196 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2197 scoped_ptr<SpdyFrame> req2(
2198 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2199 MockWrite writes[] = {
2200 CreateMockWrite(*req1, 0),
2201 CreateMockWrite(*req2, 1),
2204 MockRead reads[] = {
2205 MockRead(ASYNC, 0, 2) // EOF
2208 DeterministicSocketData data(reads, arraysize(reads),
2209 writes, arraysize(writes));
2210 data.set_connect_data(connect_data);
2211 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2213 CreateDeterministicNetworkSession();
2215 base::WeakPtr<SpdySession> session =
2216 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2218 GURL url1(kDefaultURL);
2219 base::WeakPtr<SpdyStream> spdy_stream1 =
2220 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2221 session, url1, MEDIUM, BoundNetLog());
2222 ASSERT_TRUE(spdy_stream1.get() != NULL);
2223 EXPECT_EQ(0u, spdy_stream1->stream_id());
2225 GURL url2(kDefaultURL);
2226 base::WeakPtr<SpdyStream> spdy_stream2 =
2227 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2228 session, url2, MEDIUM, BoundNetLog());
2229 ASSERT_TRUE(spdy_stream2.get() != NULL);
2230 EXPECT_EQ(0u, spdy_stream2->stream_id());
2232 // Make |spdy_stream1| close |spdy_stream2|.
2233 test::ClosingDelegate delegate1(spdy_stream2);
2234 spdy_stream1->SetDelegate(&delegate1);
2236 // Make |spdy_stream2| close |spdy_stream1|.
2237 test::ClosingDelegate delegate2(spdy_stream1);
2238 spdy_stream2->SetDelegate(&delegate2);
2240 scoped_ptr<SpdyHeaderBlock> headers(
2241 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2242 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2243 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2245 scoped_ptr<SpdyHeaderBlock> headers2(
2246 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2247 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2248 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2250 // Ensure that the streams have not yet been activated and assigned an id.
2251 EXPECT_EQ(0u, spdy_stream1->stream_id());
2252 EXPECT_EQ(0u, spdy_stream2->stream_id());
2254 data.RunFor(2);
2256 EXPECT_EQ(1u, spdy_stream1->stream_id());
2257 EXPECT_EQ(3u, spdy_stream2->stream_id());
2259 // Ensure we don't crash while closing the session.
2260 session->CloseSessionOnError(ERR_ABORTED, std::string());
2262 EXPECT_EQ(NULL, spdy_stream1.get());
2263 EXPECT_EQ(NULL, spdy_stream2.get());
2265 EXPECT_TRUE(delegate1.StreamIsClosed());
2266 EXPECT_TRUE(delegate2.StreamIsClosed());
2268 base::MessageLoop::current()->RunUntilIdle();
2269 EXPECT_TRUE(session == NULL);
2272 // Delegate that closes a given session when the stream is closed.
2273 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2274 public:
2275 SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2276 const base::WeakPtr<SpdySession>& session_to_close)
2277 : StreamDelegateDoNothing(stream),
2278 session_to_close_(session_to_close) {}
2280 ~SessionClosingDelegate() override {}
2282 void OnClose(int status) override {
2283 session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2286 private:
2287 base::WeakPtr<SpdySession> session_to_close_;
2290 // Close an activated stream that closes its session. Nothing should
2291 // blow up. This is a regression test for http://crbug.com/263691 .
2292 TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2293 session_deps_.host_resolver->set_synchronous_mode(true);
2295 MockConnect connect_data(SYNCHRONOUS, OK);
2297 scoped_ptr<SpdyFrame> req(
2298 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2299 scoped_ptr<SpdyFrame> rst(
2300 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2301 scoped_ptr<SpdyFrame> goaway(
2302 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2303 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2304 // despite being queued second.
2305 MockWrite writes[] = {
2306 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 1),
2307 CreateMockWrite(*rst, 2),
2310 MockRead reads[] = {
2311 MockRead(ASYNC, 0, 3) // EOF
2313 DeterministicSocketData data(reads, arraysize(reads),
2314 writes, arraysize(writes));
2315 data.set_connect_data(connect_data);
2316 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2318 CreateDeterministicNetworkSession();
2320 base::WeakPtr<SpdySession> session =
2321 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2323 GURL url(kDefaultURL);
2324 base::WeakPtr<SpdyStream> spdy_stream =
2325 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2326 session, url, MEDIUM, BoundNetLog());
2327 ASSERT_TRUE(spdy_stream.get() != NULL);
2328 EXPECT_EQ(0u, spdy_stream->stream_id());
2330 SessionClosingDelegate delegate(spdy_stream, session);
2331 spdy_stream->SetDelegate(&delegate);
2333 scoped_ptr<SpdyHeaderBlock> headers(
2334 spdy_util_.ConstructGetHeaderBlock(url.spec()));
2335 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2336 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2338 EXPECT_EQ(0u, spdy_stream->stream_id());
2340 data.RunFor(1);
2342 EXPECT_EQ(1u, spdy_stream->stream_id());
2344 // Ensure we don't crash while closing the stream (which closes the
2345 // session).
2346 spdy_stream->Cancel();
2348 EXPECT_EQ(NULL, spdy_stream.get());
2349 EXPECT_TRUE(delegate.StreamIsClosed());
2351 data.RunFor(2); // Write the RST_STREAM & GOAWAY.
2352 base::MessageLoop::current()->RunUntilIdle();
2353 EXPECT_TRUE(session == NULL);
2356 TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2357 session_deps_.host_resolver->set_synchronous_mode(true);
2359 MockConnect connect_data(SYNCHRONOUS, OK);
2361 // No actual data will be sent.
2362 MockWrite writes[] = {
2363 MockWrite(ASYNC, 0, 1) // EOF
2366 MockRead reads[] = {
2367 MockRead(ASYNC, 0, 0) // EOF
2369 DeterministicSocketData data(reads, arraysize(reads),
2370 writes, arraysize(writes));
2371 data.set_connect_data(connect_data);
2372 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2374 // Load a cert that is valid for:
2375 // www.example.org
2376 // mail.example.org
2377 // www.example.com
2378 base::FilePath certs_dir = GetTestCertsDirectory();
2379 scoped_refptr<X509Certificate> test_cert(
2380 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2381 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2383 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2384 ssl.cert = test_cert;
2385 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2387 CreateDeterministicNetworkSession();
2389 base::WeakPtr<SpdySession> session =
2390 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2392 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2393 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2394 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
2395 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2398 TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2399 session_deps_.host_resolver->set_synchronous_mode(true);
2401 MockConnect connect_data(SYNCHRONOUS, OK);
2403 // No actual data will be sent.
2404 MockWrite writes[] = {
2405 MockWrite(ASYNC, 0, 1) // EOF
2408 MockRead reads[] = {
2409 MockRead(ASYNC, 0, 0) // EOF
2411 DeterministicSocketData data(reads, arraysize(reads),
2412 writes, arraysize(writes));
2413 data.set_connect_data(connect_data);
2414 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2416 // Load a cert that is valid for:
2417 // www.example.org
2418 // mail.example.org
2419 // www.example.com
2420 base::FilePath certs_dir = GetTestCertsDirectory();
2421 scoped_refptr<X509Certificate> test_cert(
2422 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2423 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2425 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2426 ssl.channel_id_sent = true;
2427 ssl.cert = test_cert;
2428 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2430 CreateDeterministicNetworkSession();
2432 base::WeakPtr<SpdySession> session =
2433 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2435 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2436 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2437 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2438 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2441 TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2442 // TODO(rtenneti): Define a helper class/methods and move the common code in
2443 // this file.
2444 MockConnect connect_data(SYNCHRONOUS, OK);
2446 SettingsMap new_settings;
2447 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2448 const uint32 max_concurrent_streams = 1;
2449 new_settings[kSpdySettingsIds1] =
2450 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2452 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
2453 scoped_ptr<SpdyFrame> req1(
2454 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2455 scoped_ptr<SpdyFrame> req2(
2456 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
2457 scoped_ptr<SpdyFrame> req3(
2458 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
2459 MockWrite writes[] = {
2460 CreateMockWrite(*settings_ack, 1),
2461 CreateMockWrite(*req1, 2),
2462 CreateMockWrite(*req2, 5),
2463 CreateMockWrite(*req3, 8),
2466 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2467 // streams to 1.
2468 scoped_ptr<SpdyFrame> settings_frame(
2469 spdy_util_.ConstructSpdySettings(new_settings));
2471 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2472 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2474 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2475 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2477 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
2478 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2480 MockRead reads[] = {
2481 CreateMockRead(*settings_frame),
2482 CreateMockRead(*resp1, 3),
2483 CreateMockRead(*body1, 4),
2484 CreateMockRead(*resp2, 6),
2485 CreateMockRead(*body2, 7),
2486 CreateMockRead(*resp3, 9),
2487 CreateMockRead(*body3, 10),
2488 MockRead(ASYNC, 0, 11) // EOF
2491 DeterministicSocketData data(reads, arraysize(reads),
2492 writes, arraysize(writes));
2493 data.set_connect_data(connect_data);
2494 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2496 CreateDeterministicNetworkSession();
2498 base::WeakPtr<SpdySession> session =
2499 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2501 // Read the settings frame.
2502 data.RunFor(1);
2504 GURL url1(kDefaultURL);
2505 base::WeakPtr<SpdyStream> spdy_stream1 =
2506 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2507 session, url1, LOWEST, BoundNetLog());
2508 ASSERT_TRUE(spdy_stream1.get() != NULL);
2509 EXPECT_EQ(0u, spdy_stream1->stream_id());
2510 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2511 spdy_stream1->SetDelegate(&delegate1);
2513 TestCompletionCallback callback2;
2514 GURL url2(kDefaultURL);
2515 SpdyStreamRequest request2;
2516 ASSERT_EQ(ERR_IO_PENDING,
2517 request2.StartRequest(
2518 SPDY_REQUEST_RESPONSE_STREAM,
2519 session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2521 TestCompletionCallback callback3;
2522 GURL url3(kDefaultURL);
2523 SpdyStreamRequest request3;
2524 ASSERT_EQ(ERR_IO_PENDING,
2525 request3.StartRequest(
2526 SPDY_REQUEST_RESPONSE_STREAM,
2527 session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2529 EXPECT_EQ(0u, session->num_active_streams());
2530 EXPECT_EQ(1u, session->num_created_streams());
2531 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2533 scoped_ptr<SpdyHeaderBlock> headers(
2534 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2535 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2536 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2538 // Run until 1st stream is activated and then closed.
2539 EXPECT_EQ(0u, delegate1.stream_id());
2540 data.RunFor(4);
2541 EXPECT_EQ(NULL, spdy_stream1.get());
2542 EXPECT_EQ(1u, delegate1.stream_id());
2544 EXPECT_EQ(0u, session->num_active_streams());
2545 EXPECT_EQ(0u, session->num_created_streams());
2546 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2548 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2549 // create the 2nd stream.
2550 base::MessageLoop::current()->RunUntilIdle();
2552 EXPECT_EQ(0u, session->num_active_streams());
2553 EXPECT_EQ(1u, session->num_created_streams());
2554 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2556 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2557 test::StreamDelegateDoNothing delegate2(stream2);
2558 stream2->SetDelegate(&delegate2);
2559 scoped_ptr<SpdyHeaderBlock> headers2(
2560 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2561 stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2562 EXPECT_TRUE(stream2->HasUrlFromHeaders());
2564 // Run until 2nd stream is activated and then closed.
2565 EXPECT_EQ(0u, delegate2.stream_id());
2566 data.RunFor(3);
2567 EXPECT_EQ(NULL, stream2.get());
2568 EXPECT_EQ(3u, delegate2.stream_id());
2570 EXPECT_EQ(0u, session->num_active_streams());
2571 EXPECT_EQ(0u, session->num_created_streams());
2572 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2574 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2575 // create the 3rd stream.
2576 base::MessageLoop::current()->RunUntilIdle();
2578 EXPECT_EQ(0u, session->num_active_streams());
2579 EXPECT_EQ(1u, session->num_created_streams());
2580 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2582 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2583 test::StreamDelegateDoNothing delegate3(stream3);
2584 stream3->SetDelegate(&delegate3);
2585 scoped_ptr<SpdyHeaderBlock> headers3(
2586 spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2587 stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2588 EXPECT_TRUE(stream3->HasUrlFromHeaders());
2590 // Run until 2nd stream is activated and then closed.
2591 EXPECT_EQ(0u, delegate3.stream_id());
2592 data.RunFor(3);
2593 EXPECT_EQ(NULL, stream3.get());
2594 EXPECT_EQ(5u, delegate3.stream_id());
2596 EXPECT_EQ(0u, session->num_active_streams());
2597 EXPECT_EQ(0u, session->num_created_streams());
2598 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2600 data.RunFor(1);
2603 TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2604 session_deps_.host_resolver->set_synchronous_mode(true);
2606 MockRead reads[] = {
2607 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2610 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2611 MockConnect connect_data(SYNCHRONOUS, OK);
2613 data.set_connect_data(connect_data);
2614 session_deps_.socket_factory->AddSocketDataProvider(&data);
2616 CreateNetworkSession();
2618 base::WeakPtr<SpdySession> session =
2619 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2621 // Leave room for only one more stream to be created.
2622 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2623 base::WeakPtr<SpdyStream> spdy_stream =
2624 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2625 session, test_url_, MEDIUM, BoundNetLog());
2626 ASSERT_TRUE(spdy_stream != NULL);
2629 GURL url1(kDefaultURL);
2630 base::WeakPtr<SpdyStream> spdy_stream1 =
2631 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2632 session, url1, LOWEST, BoundNetLog());
2633 ASSERT_TRUE(spdy_stream1.get() != NULL);
2634 EXPECT_EQ(0u, spdy_stream1->stream_id());
2636 TestCompletionCallback callback2;
2637 GURL url2(kDefaultURL);
2638 SpdyStreamRequest request2;
2639 ASSERT_EQ(ERR_IO_PENDING,
2640 request2.StartRequest(
2641 SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2642 callback2.callback()));
2644 TestCompletionCallback callback3;
2645 GURL url3(kDefaultURL);
2646 SpdyStreamRequest request3;
2647 ASSERT_EQ(ERR_IO_PENDING,
2648 request3.StartRequest(
2649 SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2650 callback3.callback()));
2652 EXPECT_EQ(0u, session->num_active_streams());
2653 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2654 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2656 // Cancel the first stream; this will allow the second stream to be created.
2657 EXPECT_TRUE(spdy_stream1.get() != NULL);
2658 spdy_stream1->Cancel();
2659 EXPECT_EQ(NULL, spdy_stream1.get());
2661 EXPECT_EQ(OK, callback2.WaitForResult());
2662 EXPECT_EQ(0u, session->num_active_streams());
2663 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2664 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2666 // Cancel the second stream; this will allow the third stream to be created.
2667 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2668 spdy_stream2->Cancel();
2669 EXPECT_EQ(NULL, spdy_stream2.get());
2671 EXPECT_EQ(OK, callback3.WaitForResult());
2672 EXPECT_EQ(0u, session->num_active_streams());
2673 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2674 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2676 // Cancel the third stream.
2677 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2678 spdy_stream3->Cancel();
2679 EXPECT_EQ(NULL, spdy_stream3.get());
2680 EXPECT_EQ(0u, session->num_active_streams());
2681 EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
2682 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2685 // Test that SpdySession::DoReadLoop reads data from the socket
2686 // without yielding. This test makes 32k - 1 bytes of data available
2687 // on the socket for reading. It then verifies that it has read all
2688 // the available data without yielding.
2689 TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2690 MockConnect connect_data(SYNCHRONOUS, OK);
2691 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2693 scoped_ptr<SpdyFrame> req1(
2694 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2695 MockWrite writes[] = {
2696 CreateMockWrite(*req1, 0),
2699 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2700 // (-spdy_data_frame_size).
2701 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2702 const int kPayloadSize =
2703 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2704 TestDataStream test_stream;
2705 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2706 char* payload_data = payload->data();
2707 test_stream.GetBytes(payload_data, kPayloadSize);
2709 scoped_ptr<SpdyFrame> partial_data_frame(
2710 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2711 scoped_ptr<SpdyFrame> finish_data_frame(
2712 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2714 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2716 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2717 // bytes.
2718 MockRead reads[] = {
2719 CreateMockRead(*resp1, 1),
2720 CreateMockRead(*partial_data_frame, 2),
2721 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2722 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2723 CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2724 MockRead(ASYNC, 0, 6) // EOF
2727 // Create SpdySession and SpdyStream and send the request.
2728 DeterministicSocketData data(reads, arraysize(reads),
2729 writes, arraysize(writes));
2730 data.set_connect_data(connect_data);
2731 session_deps_.host_resolver->set_synchronous_mode(true);
2732 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2734 CreateDeterministicNetworkSession();
2736 base::WeakPtr<SpdySession> session =
2737 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2739 GURL url1(kDefaultURL);
2740 base::WeakPtr<SpdyStream> spdy_stream1 =
2741 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2742 session, url1, MEDIUM, BoundNetLog());
2743 ASSERT_TRUE(spdy_stream1.get() != NULL);
2744 EXPECT_EQ(0u, spdy_stream1->stream_id());
2745 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2746 spdy_stream1->SetDelegate(&delegate1);
2748 scoped_ptr<SpdyHeaderBlock> headers1(
2749 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2750 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2751 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2753 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2754 // post a task.
2755 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2757 // Run until 1st read.
2758 EXPECT_EQ(0u, delegate1.stream_id());
2759 data.RunFor(2);
2760 EXPECT_EQ(1u, delegate1.stream_id());
2761 EXPECT_EQ(0u, observer.executed_count());
2763 // Read all the data and verify SpdySession::DoReadLoop has not
2764 // posted a task.
2765 data.RunFor(4);
2766 EXPECT_EQ(NULL, spdy_stream1.get());
2768 // Verify task observer's executed_count is zero, which indicates DoRead read
2769 // all the available data.
2770 EXPECT_EQ(0u, observer.executed_count());
2771 EXPECT_TRUE(data.at_write_eof());
2772 EXPECT_TRUE(data.at_read_eof());
2775 // Test that SpdySession::DoReadLoop yields while reading the
2776 // data. This test makes 32k + 1 bytes of data available on the socket
2777 // for reading. It then verifies that DoRead has yielded even though
2778 // there is data available for it to read (i.e, socket()->Read didn't
2779 // return ERR_IO_PENDING during socket reads).
2780 TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2781 MockConnect connect_data(SYNCHRONOUS, OK);
2782 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2784 scoped_ptr<SpdyFrame> req1(
2785 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2786 MockWrite writes[] = {
2787 CreateMockWrite(*req1, 0),
2790 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2791 // (-spdy_data_frame_size).
2792 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2793 const int kPayloadSize =
2794 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2795 TestDataStream test_stream;
2796 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2797 char* payload_data = payload->data();
2798 test_stream.GetBytes(payload_data, kPayloadSize);
2800 scoped_ptr<SpdyFrame> partial_data_frame(
2801 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2802 scoped_ptr<SpdyFrame> finish_data_frame(
2803 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2805 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2807 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2808 MockRead reads[] = {
2809 CreateMockRead(*resp1, 1),
2810 CreateMockRead(*partial_data_frame, 2),
2811 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2812 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2813 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2814 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2815 MockRead(ASYNC, 0, 7) // EOF
2818 // Create SpdySession and SpdyStream and send the request.
2819 DeterministicSocketData data(reads, arraysize(reads),
2820 writes, arraysize(writes));
2821 data.set_connect_data(connect_data);
2822 session_deps_.host_resolver->set_synchronous_mode(true);
2823 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2825 CreateDeterministicNetworkSession();
2827 base::WeakPtr<SpdySession> session =
2828 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2830 GURL url1(kDefaultURL);
2831 base::WeakPtr<SpdyStream> spdy_stream1 =
2832 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2833 session, url1, MEDIUM, BoundNetLog());
2834 ASSERT_TRUE(spdy_stream1.get() != NULL);
2835 EXPECT_EQ(0u, spdy_stream1->stream_id());
2836 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2837 spdy_stream1->SetDelegate(&delegate1);
2839 scoped_ptr<SpdyHeaderBlock> headers1(
2840 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2841 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2842 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2844 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2845 // task.
2846 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2848 // Run until 1st read.
2849 EXPECT_EQ(0u, delegate1.stream_id());
2850 data.RunFor(2);
2851 EXPECT_EQ(1u, delegate1.stream_id());
2852 EXPECT_EQ(0u, observer.executed_count());
2854 // Read all the data and verify SpdySession::DoReadLoop has posted a
2855 // task.
2856 data.RunFor(6);
2857 EXPECT_EQ(NULL, spdy_stream1.get());
2859 // Verify task observer's executed_count is 1, which indicates DoRead has
2860 // posted only one task and thus yielded though there is data available for it
2861 // to read.
2862 EXPECT_EQ(1u, observer.executed_count());
2863 EXPECT_TRUE(data.at_write_eof());
2864 EXPECT_TRUE(data.at_read_eof());
2867 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2868 // + async, by doing the following MockReads.
2870 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2871 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2873 // The above reads 26K synchronously. Since that is less that 32K, we
2874 // will attempt to read again. However, that DoRead() will return
2875 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2876 // yield. When we come back, DoRead() will read the results from the
2877 // async read, and rest of the data synchronously.
2878 TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2879 MockConnect connect_data(SYNCHRONOUS, OK);
2880 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2882 scoped_ptr<SpdyFrame> req1(
2883 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2884 MockWrite writes[] = {
2885 CreateMockWrite(*req1, 0),
2888 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2889 // (-spdy_data_frame_size).
2890 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2891 TestDataStream test_stream;
2892 const int kEightKPayloadSize =
2893 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2894 scoped_refptr<net::IOBuffer> eightk_payload(
2895 new net::IOBuffer(kEightKPayloadSize));
2896 char* eightk_payload_data = eightk_payload->data();
2897 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2899 // Build buffer of 2k size.
2900 TestDataStream test_stream2;
2901 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2902 scoped_refptr<net::IOBuffer> twok_payload(
2903 new net::IOBuffer(kTwoKPayloadSize));
2904 char* twok_payload_data = twok_payload->data();
2905 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2907 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2908 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2909 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2910 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2911 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2912 1, "h", 1, DATA_FLAG_FIN));
2914 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2916 MockRead reads[] = {
2917 CreateMockRead(*resp1, 1),
2918 CreateMockRead(*eightk_data_frame, 2),
2919 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
2920 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2921 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
2922 CreateMockRead(*eightk_data_frame, 6, ASYNC),
2923 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
2924 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2925 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2926 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
2927 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
2928 MockRead(ASYNC, 0, 12) // EOF
2931 // Create SpdySession and SpdyStream and send the request.
2932 DeterministicSocketData data(reads, arraysize(reads),
2933 writes, arraysize(writes));
2934 data.set_connect_data(connect_data);
2935 session_deps_.host_resolver->set_synchronous_mode(true);
2936 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2938 CreateDeterministicNetworkSession();
2940 base::WeakPtr<SpdySession> session =
2941 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2943 GURL url1(kDefaultURL);
2944 base::WeakPtr<SpdyStream> spdy_stream1 =
2945 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2946 session, url1, MEDIUM, BoundNetLog());
2947 ASSERT_TRUE(spdy_stream1.get() != NULL);
2948 EXPECT_EQ(0u, spdy_stream1->stream_id());
2949 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2950 spdy_stream1->SetDelegate(&delegate1);
2952 scoped_ptr<SpdyHeaderBlock> headers1(
2953 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2954 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2955 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2957 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2958 // posting of tasks.
2959 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2961 // Run until 1st read.
2962 EXPECT_EQ(0u, delegate1.stream_id());
2963 data.RunFor(2);
2964 EXPECT_EQ(1u, delegate1.stream_id());
2965 EXPECT_EQ(0u, observer.executed_count());
2967 // Read all the data and verify SpdySession::DoReadLoop has posted a
2968 // task.
2969 data.RunFor(12);
2970 EXPECT_EQ(NULL, spdy_stream1.get());
2972 // Verify task observer's executed_count is 1, which indicates DoRead has
2973 // posted only one task and thus yielded though there is data available for
2974 // it to read.
2975 EXPECT_EQ(1u, observer.executed_count());
2976 EXPECT_TRUE(data.at_write_eof());
2977 EXPECT_TRUE(data.at_read_eof());
2980 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2981 // nothing blows up.
2982 TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
2983 MockConnect connect_data(SYNCHRONOUS, OK);
2984 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2986 scoped_ptr<SpdyFrame> req1(
2987 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2988 MockWrite writes[] = {
2989 CreateMockWrite(*req1, 0),
2992 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2993 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2994 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
2996 MockRead reads[] = {
2997 CreateMockRead(*resp1, 1),
2998 CreateMockRead(*body1, 2),
2999 CreateMockRead(*goaway, 3),
3002 // Create SpdySession and SpdyStream and send the request.
3003 DeterministicSocketData data(reads, arraysize(reads),
3004 writes, arraysize(writes));
3005 data.set_connect_data(connect_data);
3006 session_deps_.host_resolver->set_synchronous_mode(true);
3007 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3009 CreateDeterministicNetworkSession();
3011 base::WeakPtr<SpdySession> session =
3012 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3014 GURL url1(kDefaultURL);
3015 base::WeakPtr<SpdyStream> spdy_stream1 =
3016 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3017 session, url1, MEDIUM, BoundNetLog());
3018 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3019 spdy_stream1->SetDelegate(&delegate1);
3020 ASSERT_TRUE(spdy_stream1.get() != NULL);
3021 EXPECT_EQ(0u, spdy_stream1->stream_id());
3023 scoped_ptr<SpdyHeaderBlock> headers1(
3024 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3025 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
3026 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3028 // Run until 1st read.
3029 EXPECT_EQ(0u, spdy_stream1->stream_id());
3030 data.RunFor(1);
3031 EXPECT_EQ(1u, spdy_stream1->stream_id());
3033 // Run until GoAway.
3034 data.RunFor(3);
3035 EXPECT_EQ(NULL, spdy_stream1.get());
3036 EXPECT_TRUE(data.at_write_eof());
3037 EXPECT_TRUE(data.at_read_eof());
3038 EXPECT_TRUE(session == NULL);
3041 // Within this framework, a SpdySession should be initialized with
3042 // flow control disabled for protocol version 2, with flow control
3043 // enabled only for streams for protocol version 3, and with flow
3044 // control enabled for streams and sessions for higher versions.
3045 TEST_P(SpdySessionTest, ProtocolNegotiation) {
3046 session_deps_.host_resolver->set_synchronous_mode(true);
3048 MockConnect connect_data(SYNCHRONOUS, OK);
3049 MockRead reads[] = {
3050 MockRead(SYNCHRONOUS, 0, 0) // EOF
3052 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3053 data.set_connect_data(connect_data);
3054 session_deps_.socket_factory->AddSocketDataProvider(&data);
3056 CreateNetworkSession();
3057 base::WeakPtr<SpdySession> session =
3058 CreateFakeSpdySession(spdy_session_pool_, key_);
3060 EXPECT_EQ(spdy_util_.spdy_version(),
3061 session->buffered_spdy_framer_->protocol_version());
3062 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3063 session->flow_control_state());
3064 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3065 session->session_send_window_size_);
3066 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3067 session->session_recv_window_size_);
3068 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3071 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3072 // pointers to the idle session are currently held.
3073 TEST_P(SpdySessionTest, CloseOneIdleConnection) {
3074 ClientSocketPoolManager::set_max_sockets_per_group(
3075 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3076 ClientSocketPoolManager::set_max_sockets_per_pool(
3077 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3079 MockConnect connect_data(SYNCHRONOUS, OK);
3080 MockRead reads[] = {
3081 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3083 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3084 data.set_connect_data(connect_data);
3085 session_deps_.socket_factory->AddSocketDataProvider(&data);
3086 session_deps_.socket_factory->AddSocketDataProvider(&data);
3088 CreateNetworkSession();
3090 TransportClientSocketPool* pool =
3091 http_session_->GetTransportSocketPool(
3092 HttpNetworkSession::NORMAL_SOCKET_POOL);
3094 // Create an idle SPDY session.
3095 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3096 PRIVACY_MODE_DISABLED);
3097 base::WeakPtr<SpdySession> session1 =
3098 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3099 EXPECT_FALSE(pool->IsStalled());
3101 // Trying to create a new connection should cause the pool to be stalled, and
3102 // post a task asynchronously to try and close the session.
3103 TestCompletionCallback callback2;
3104 HostPortPair host_port2("2.com", 80);
3105 scoped_refptr<TransportSocketParams> params2(
3106 new TransportSocketParams(
3107 host_port2, false, false, OnHostResolutionCallback(),
3108 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3109 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3110 EXPECT_EQ(ERR_IO_PENDING,
3111 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3112 callback2.callback(), pool, BoundNetLog()));
3113 EXPECT_TRUE(pool->IsStalled());
3115 // The socket pool should close the connection asynchronously and establish a
3116 // new connection.
3117 EXPECT_EQ(OK, callback2.WaitForResult());
3118 EXPECT_FALSE(pool->IsStalled());
3119 EXPECT_TRUE(session1 == NULL);
3122 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3123 // pointers to the idle session are currently held, in the case the SPDY session
3124 // has an alias.
3125 TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
3126 ClientSocketPoolManager::set_max_sockets_per_group(
3127 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3128 ClientSocketPoolManager::set_max_sockets_per_pool(
3129 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3131 MockConnect connect_data(SYNCHRONOUS, OK);
3132 MockRead reads[] = {
3133 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3135 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3136 data.set_connect_data(connect_data);
3137 session_deps_.socket_factory->AddSocketDataProvider(&data);
3138 session_deps_.socket_factory->AddSocketDataProvider(&data);
3140 session_deps_.host_resolver->set_synchronous_mode(true);
3141 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3142 "1.com", "192.168.0.2", std::string());
3143 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3144 "2.com", "192.168.0.2", std::string());
3145 // Not strictly needed.
3146 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3147 "3.com", "192.168.0.3", std::string());
3149 CreateNetworkSession();
3151 TransportClientSocketPool* pool =
3152 http_session_->GetTransportSocketPool(
3153 HttpNetworkSession::NORMAL_SOCKET_POOL);
3155 // Create an idle SPDY session.
3156 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3157 PRIVACY_MODE_DISABLED);
3158 base::WeakPtr<SpdySession> session1 =
3159 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3160 EXPECT_FALSE(pool->IsStalled());
3162 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3163 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3164 PRIVACY_MODE_DISABLED);
3165 HostResolver::RequestInfo info(key2.host_port_pair());
3166 AddressList addresses;
3167 // Pre-populate the DNS cache, since a synchronous resolution is required in
3168 // order to create the alias.
3169 session_deps_.host_resolver->Resolve(info,
3170 DEFAULT_PRIORITY,
3171 &addresses,
3172 CompletionCallback(),
3173 NULL,
3174 BoundNetLog());
3175 // Get a session for |key2|, which should return the session created earlier.
3176 base::WeakPtr<SpdySession> session2 =
3177 spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3178 ASSERT_EQ(session1.get(), session2.get());
3179 EXPECT_FALSE(pool->IsStalled());
3181 // Trying to create a new connection should cause the pool to be stalled, and
3182 // post a task asynchronously to try and close the session.
3183 TestCompletionCallback callback3;
3184 HostPortPair host_port3("3.com", 80);
3185 scoped_refptr<TransportSocketParams> params3(
3186 new TransportSocketParams(
3187 host_port3, false, false, OnHostResolutionCallback(),
3188 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3189 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3190 EXPECT_EQ(ERR_IO_PENDING,
3191 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3192 callback3.callback(), pool, BoundNetLog()));
3193 EXPECT_TRUE(pool->IsStalled());
3195 // The socket pool should close the connection asynchronously and establish a
3196 // new connection.
3197 EXPECT_EQ(OK, callback3.WaitForResult());
3198 EXPECT_FALSE(pool->IsStalled());
3199 EXPECT_TRUE(session1 == NULL);
3200 EXPECT_TRUE(session2 == NULL);
3203 // Tests that when a SPDY session becomes idle, it closes itself if there is
3204 // a lower layer pool stalled on the per-pool socket limit.
3205 TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3206 ClientSocketPoolManager::set_max_sockets_per_group(
3207 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3208 ClientSocketPoolManager::set_max_sockets_per_pool(
3209 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3211 MockConnect connect_data(SYNCHRONOUS, OK);
3212 MockRead reads[] = {
3213 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3215 scoped_ptr<SpdyFrame> req1(
3216 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3217 scoped_ptr<SpdyFrame> cancel1(
3218 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3219 MockWrite writes[] = {
3220 CreateMockWrite(*req1, 1),
3221 CreateMockWrite(*cancel1, 1),
3223 StaticSocketDataProvider data(reads, arraysize(reads),
3224 writes, arraysize(writes));
3225 data.set_connect_data(connect_data);
3226 session_deps_.socket_factory->AddSocketDataProvider(&data);
3228 MockRead http_reads[] = {
3229 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3231 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
3232 NULL, 0);
3233 http_data.set_connect_data(connect_data);
3234 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3237 CreateNetworkSession();
3239 TransportClientSocketPool* pool =
3240 http_session_->GetTransportSocketPool(
3241 HttpNetworkSession::NORMAL_SOCKET_POOL);
3243 // Create a SPDY session.
3244 GURL url1(kDefaultURL);
3245 SpdySessionKey key1(HostPortPair(url1.host(), 80),
3246 ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3247 base::WeakPtr<SpdySession> session1 =
3248 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3249 EXPECT_FALSE(pool->IsStalled());
3251 // Create a stream using the session, and send a request.
3253 TestCompletionCallback callback1;
3254 base::WeakPtr<SpdyStream> spdy_stream1 =
3255 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3256 session1, url1, DEFAULT_PRIORITY,
3257 BoundNetLog());
3258 ASSERT_TRUE(spdy_stream1.get());
3259 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3260 spdy_stream1->SetDelegate(&delegate1);
3262 scoped_ptr<SpdyHeaderBlock> headers1(
3263 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3264 EXPECT_EQ(ERR_IO_PENDING,
3265 spdy_stream1->SendRequestHeaders(
3266 headers1.Pass(), NO_MORE_DATA_TO_SEND));
3267 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3269 base::MessageLoop::current()->RunUntilIdle();
3271 // Trying to create a new connection should cause the pool to be stalled, and
3272 // post a task asynchronously to try and close the session.
3273 TestCompletionCallback callback2;
3274 HostPortPair host_port2("2.com", 80);
3275 scoped_refptr<TransportSocketParams> params2(
3276 new TransportSocketParams(
3277 host_port2, false, false, OnHostResolutionCallback(),
3278 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3279 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3280 EXPECT_EQ(ERR_IO_PENDING,
3281 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3282 callback2.callback(), pool, BoundNetLog()));
3283 EXPECT_TRUE(pool->IsStalled());
3285 // Running the message loop should cause the socket pool to ask the SPDY
3286 // session to close an idle socket, but since the socket is in use, nothing
3287 // happens.
3288 base::RunLoop().RunUntilIdle();
3289 EXPECT_TRUE(pool->IsStalled());
3290 EXPECT_FALSE(callback2.have_result());
3292 // Cancelling the request should result in the session's socket being
3293 // closed, since the pool is stalled.
3294 ASSERT_TRUE(spdy_stream1.get());
3295 spdy_stream1->Cancel();
3296 base::RunLoop().RunUntilIdle();
3297 ASSERT_FALSE(pool->IsStalled());
3298 EXPECT_EQ(OK, callback2.WaitForResult());
3301 // Verify that SpdySessionKey and therefore SpdySession is different when
3302 // privacy mode is enabled or disabled.
3303 TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3304 CreateDeterministicNetworkSession();
3306 HostPortPair host_port_pair("www.example.org", 443);
3307 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3308 PRIVACY_MODE_ENABLED);
3309 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3310 PRIVACY_MODE_DISABLED);
3312 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3313 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3315 // Add SpdySession with PrivacyMode Enabled to the pool.
3316 base::WeakPtr<SpdySession> session_privacy_enabled =
3317 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3319 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3320 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3322 // Add SpdySession with PrivacyMode Disabled to the pool.
3323 base::WeakPtr<SpdySession> session_privacy_disabled =
3324 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3326 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3327 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3329 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3330 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3331 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3333 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3334 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3335 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3338 // Delegate that creates another stream when its stream is closed.
3339 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3340 public:
3341 StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3342 const base::WeakPtr<SpdySession>& session)
3343 : StreamDelegateDoNothing(stream),
3344 session_(session) {}
3346 ~StreamCreatingDelegate() override {}
3348 void OnClose(int status) override {
3349 GURL url(kDefaultURL);
3350 ignore_result(
3351 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3352 session_, url, MEDIUM, BoundNetLog()));
3355 private:
3356 const base::WeakPtr<SpdySession> session_;
3359 // Create another stream in response to a stream being reset. Nothing
3360 // should blow up. This is a regression test for
3361 // http://crbug.com/263690 .
3362 TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3363 session_deps_.host_resolver->set_synchronous_mode(true);
3365 MockConnect connect_data(SYNCHRONOUS, OK);
3367 scoped_ptr<SpdyFrame> req(
3368 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3369 MockWrite writes[] = {
3370 CreateMockWrite(*req, 0),
3373 scoped_ptr<SpdyFrame> rst(
3374 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3375 MockRead reads[] = {
3376 CreateMockRead(*rst, 1),
3377 MockRead(ASYNC, 0, 2) // EOF
3379 DeterministicSocketData data(reads, arraysize(reads),
3380 writes, arraysize(writes));
3381 data.set_connect_data(connect_data);
3382 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3384 CreateDeterministicNetworkSession();
3386 base::WeakPtr<SpdySession> session =
3387 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3389 GURL url(kDefaultURL);
3390 base::WeakPtr<SpdyStream> spdy_stream =
3391 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3392 session, url, MEDIUM, BoundNetLog());
3393 ASSERT_TRUE(spdy_stream.get() != NULL);
3394 EXPECT_EQ(0u, spdy_stream->stream_id());
3396 StreamCreatingDelegate delegate(spdy_stream, session);
3397 spdy_stream->SetDelegate(&delegate);
3399 scoped_ptr<SpdyHeaderBlock> headers(
3400 spdy_util_.ConstructGetHeaderBlock(url.spec()));
3401 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3402 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3404 EXPECT_EQ(0u, spdy_stream->stream_id());
3406 data.RunFor(1);
3408 EXPECT_EQ(1u, spdy_stream->stream_id());
3410 // Cause the stream to be reset, which should cause another stream
3411 // to be created.
3412 data.RunFor(1);
3414 EXPECT_EQ(NULL, spdy_stream.get());
3415 EXPECT_TRUE(delegate.StreamIsClosed());
3416 EXPECT_EQ(0u, session->num_active_streams());
3417 EXPECT_EQ(1u, session->num_created_streams());
3420 // The tests below are only for SPDY/3 and above.
3422 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3423 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3424 // gets sent.
3425 SettingsMap new_settings;
3426 int32 window_size = 1;
3427 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3428 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3430 // Set up the socket so we read a SETTINGS frame that sets
3431 // INITIAL_WINDOW_SIZE.
3432 MockConnect connect_data(SYNCHRONOUS, OK);
3433 scoped_ptr<SpdyFrame> settings_frame(
3434 spdy_util_.ConstructSpdySettings(new_settings));
3435 MockRead reads[] = {
3436 CreateMockRead(*settings_frame, 0),
3437 MockRead(ASYNC, 0, 1) // EOF
3440 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3441 MockWrite writes[] = {
3442 CreateMockWrite(*settings_ack, 2),
3445 session_deps_.host_resolver->set_synchronous_mode(true);
3447 DeterministicSocketData data(reads, arraysize(reads),
3448 writes, arraysize(writes));
3449 data.set_connect_data(connect_data);
3450 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3452 CreateDeterministicNetworkSession();
3454 base::WeakPtr<SpdySession> session =
3455 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3456 base::WeakPtr<SpdyStream> spdy_stream1 =
3457 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3458 session, test_url_, MEDIUM, BoundNetLog());
3459 ASSERT_TRUE(spdy_stream1.get() != NULL);
3460 TestCompletionCallback callback1;
3461 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3463 data.RunFor(1); // Process the SETTINGS frame, but not the EOF
3464 base::MessageLoop::current()->RunUntilIdle();
3465 EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3466 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3468 // Release the first one, this will allow the second to be created.
3469 spdy_stream1->Cancel();
3470 EXPECT_EQ(NULL, spdy_stream1.get());
3472 base::WeakPtr<SpdyStream> spdy_stream2 =
3473 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3474 session, test_url_, MEDIUM, BoundNetLog());
3475 ASSERT_TRUE(spdy_stream2.get() != NULL);
3476 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3477 spdy_stream2->Cancel();
3478 EXPECT_EQ(NULL, spdy_stream2.get());
3481 // The tests below are only for SPDY/3.1 and above.
3483 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3484 // adjust the session receive window size for SPDY 3.1 and higher. In
3485 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3486 // sending a WINDOW_UPDATE frame for a large enough delta.
3487 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3488 if (GetParam() < kProtoSPDY31)
3489 return;
3491 session_deps_.host_resolver->set_synchronous_mode(true);
3493 const int32 initial_window_size =
3494 SpdySession::GetDefaultInitialWindowSize(GetParam());
3495 const int32 delta_window_size = 100;
3497 MockConnect connect_data(SYNCHRONOUS, OK);
3498 MockRead reads[] = {
3499 MockRead(ASYNC, 0, 1) // EOF
3501 scoped_ptr<SpdyFrame> window_update(spdy_util_.ConstructSpdyWindowUpdate(
3502 kSessionFlowControlStreamId, initial_window_size + delta_window_size));
3503 MockWrite writes[] = {
3504 CreateMockWrite(*window_update, 0),
3506 DeterministicSocketData data(reads, arraysize(reads),
3507 writes, arraysize(writes));
3508 data.set_connect_data(connect_data);
3509 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3511 CreateDeterministicNetworkSession();
3512 base::WeakPtr<SpdySession> session =
3513 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3514 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3515 session->flow_control_state());
3517 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3518 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3520 session->IncreaseRecvWindowSize(delta_window_size);
3521 EXPECT_EQ(initial_window_size + delta_window_size,
3522 session->session_recv_window_size_);
3523 EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3525 // Should trigger sending a WINDOW_UPDATE frame.
3526 session->IncreaseRecvWindowSize(initial_window_size);
3527 EXPECT_EQ(initial_window_size + delta_window_size + initial_window_size,
3528 session->session_recv_window_size_);
3529 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3531 data.RunFor(1);
3533 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3534 session->in_io_loop_ = true;
3535 session->DecreaseRecvWindowSize(initial_window_size + delta_window_size +
3536 initial_window_size);
3537 session->in_io_loop_ = false;
3538 EXPECT_EQ(0, session->session_recv_window_size_);
3539 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3542 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3543 // adjust the session send window size when the "enable_spdy_31" flag
3544 // is set.
3545 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3546 if (GetParam() < kProtoSPDY31)
3547 return;
3549 session_deps_.host_resolver->set_synchronous_mode(true);
3551 MockConnect connect_data(SYNCHRONOUS, OK);
3552 MockRead reads[] = {
3553 MockRead(SYNCHRONOUS, 0, 0) // EOF
3555 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3556 data.set_connect_data(connect_data);
3557 session_deps_.socket_factory->AddSocketDataProvider(&data);
3559 CreateNetworkSession();
3560 base::WeakPtr<SpdySession> session =
3561 CreateFakeSpdySession(spdy_session_pool_, key_);
3562 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3563 session->flow_control_state());
3565 const int32 initial_window_size =
3566 SpdySession::GetDefaultInitialWindowSize(GetParam());
3567 const int32 delta_window_size = 100;
3569 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3571 session->IncreaseSendWindowSize(delta_window_size);
3572 EXPECT_EQ(initial_window_size + delta_window_size,
3573 session->session_send_window_size_);
3575 session->DecreaseSendWindowSize(delta_window_size);
3576 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3579 // Incoming data for an inactive stream should not cause the session
3580 // receive window size to decrease, but it should cause the unacked
3581 // bytes to increase.
3582 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3583 if (GetParam() < kProtoSPDY31)
3584 return;
3586 session_deps_.host_resolver->set_synchronous_mode(true);
3588 MockConnect connect_data(SYNCHRONOUS, OK);
3589 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3590 MockRead reads[] = {
3591 CreateMockRead(*resp, 0),
3592 MockRead(ASYNC, 0, 1) // EOF
3594 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3595 data.set_connect_data(connect_data);
3596 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3598 CreateDeterministicNetworkSession();
3599 base::WeakPtr<SpdySession> session =
3600 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3601 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3602 session->flow_control_state());
3604 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3605 session->session_recv_window_size_);
3606 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3608 data.RunFor(1);
3610 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3611 session->session_recv_window_size_);
3612 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3614 data.RunFor(1);
3617 // The frame header is not included in flow control, but frame payload
3618 // (including optional pad length and padding) is.
3619 TEST_P(SpdySessionTest, SessionFlowControlPadding) {
3620 // Padding only exists in HTTP/2.
3621 if (GetParam() < kProtoSPDY4MinimumVersion)
3622 return;
3624 session_deps_.host_resolver->set_synchronous_mode(true);
3626 const int padding_length = 42;
3627 MockConnect connect_data(SYNCHRONOUS, OK);
3628 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(
3629 1, kUploadData, kUploadDataSize, false, padding_length));
3630 MockRead reads[] = {
3631 CreateMockRead(*resp, 0), MockRead(ASYNC, 0, 1) // EOF
3633 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3634 data.set_connect_data(connect_data);
3635 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3637 CreateDeterministicNetworkSession();
3638 base::WeakPtr<SpdySession> session =
3639 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3640 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3641 session->flow_control_state());
3643 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3644 session->session_recv_window_size_);
3645 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3647 data.RunFor(1);
3649 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3650 session->session_recv_window_size_);
3651 EXPECT_EQ(kUploadDataSize + padding_length,
3652 session->session_unacked_recv_window_bytes_);
3654 data.RunFor(1);
3657 // A delegate that drops any received data.
3658 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3659 public:
3660 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3661 base::StringPiece data)
3662 : StreamDelegateSendImmediate(stream, data) {}
3664 ~DropReceivedDataDelegate() override {}
3666 // Drop any received data.
3667 void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override {}
3670 // Send data back and forth but use a delegate that drops its received
3671 // data. The receive window should still increase to its original
3672 // value, i.e. we shouldn't "leak" receive window bytes.
3673 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3674 if (GetParam() < kProtoSPDY31)
3675 return;
3677 const char kStreamUrl[] = "http://www.example.org/";
3679 const int32 msg_data_size = 100;
3680 const std::string msg_data(msg_data_size, 'a');
3682 MockConnect connect_data(SYNCHRONOUS, OK);
3684 scoped_ptr<SpdyFrame> req(
3685 spdy_util_.ConstructSpdyPost(
3686 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3687 scoped_ptr<SpdyFrame> msg(
3688 spdy_util_.ConstructSpdyBodyFrame(
3689 1, msg_data.data(), msg_data_size, false));
3690 MockWrite writes[] = {
3691 CreateMockWrite(*req, 0),
3692 CreateMockWrite(*msg, 2),
3695 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3696 scoped_ptr<SpdyFrame> echo(
3697 spdy_util_.ConstructSpdyBodyFrame(
3698 1, msg_data.data(), msg_data_size, false));
3699 scoped_ptr<SpdyFrame> window_update(
3700 spdy_util_.ConstructSpdyWindowUpdate(
3701 kSessionFlowControlStreamId, msg_data_size));
3702 MockRead reads[] = {
3703 CreateMockRead(*resp, 1),
3704 CreateMockRead(*echo, 3),
3705 MockRead(ASYNC, 0, 4) // EOF
3708 // Create SpdySession and SpdyStream and send the request.
3709 DeterministicSocketData data(reads, arraysize(reads),
3710 writes, arraysize(writes));
3711 data.set_connect_data(connect_data);
3712 session_deps_.host_resolver->set_synchronous_mode(true);
3713 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3715 CreateDeterministicNetworkSession();
3717 base::WeakPtr<SpdySession> session =
3718 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3720 GURL url(kStreamUrl);
3721 base::WeakPtr<SpdyStream> stream =
3722 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3723 session, url, MEDIUM, BoundNetLog());
3724 ASSERT_TRUE(stream.get() != NULL);
3725 EXPECT_EQ(0u, stream->stream_id());
3727 DropReceivedDataDelegate delegate(stream, msg_data);
3728 stream->SetDelegate(&delegate);
3730 scoped_ptr<SpdyHeaderBlock> headers(
3731 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3732 EXPECT_EQ(ERR_IO_PENDING,
3733 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3734 EXPECT_TRUE(stream->HasUrlFromHeaders());
3736 const int32 initial_window_size =
3737 SpdySession::GetDefaultInitialWindowSize(GetParam());
3738 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3739 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3741 data.RunFor(4);
3743 EXPECT_TRUE(data.at_write_eof());
3744 EXPECT_TRUE(data.at_read_eof());
3746 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3747 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3749 stream->Close();
3750 EXPECT_EQ(NULL, stream.get());
3752 EXPECT_EQ(OK, delegate.WaitForClose());
3754 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3755 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3758 // Send data back and forth but close the stream before its data frame
3759 // can be written to the socket. The send window should then increase
3760 // to its original value, i.e. we shouldn't "leak" send window bytes.
3761 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3762 if (GetParam() < kProtoSPDY31)
3763 return;
3765 const char kStreamUrl[] = "http://www.example.org/";
3767 const int32 msg_data_size = 100;
3768 const std::string msg_data(msg_data_size, 'a');
3770 MockConnect connect_data(SYNCHRONOUS, OK);
3772 scoped_ptr<SpdyFrame> req(
3773 spdy_util_.ConstructSpdyPost(
3774 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3775 MockWrite writes[] = {
3776 CreateMockWrite(*req, 0),
3779 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3780 MockRead reads[] = {
3781 CreateMockRead(*resp, 1),
3782 MockRead(ASYNC, 0, 2) // EOF
3785 // Create SpdySession and SpdyStream and send the request.
3786 DeterministicSocketData data(reads, arraysize(reads),
3787 writes, arraysize(writes));
3788 data.set_connect_data(connect_data);
3789 session_deps_.host_resolver->set_synchronous_mode(true);
3790 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3792 CreateDeterministicNetworkSession();
3794 base::WeakPtr<SpdySession> session =
3795 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3797 GURL url(kStreamUrl);
3798 base::WeakPtr<SpdyStream> stream =
3799 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3800 session, url, MEDIUM, BoundNetLog());
3801 ASSERT_TRUE(stream.get() != NULL);
3802 EXPECT_EQ(0u, stream->stream_id());
3804 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3805 stream->SetDelegate(&delegate);
3807 scoped_ptr<SpdyHeaderBlock> headers(
3808 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3809 EXPECT_EQ(ERR_IO_PENDING,
3810 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3811 EXPECT_TRUE(stream->HasUrlFromHeaders());
3813 const int32 initial_window_size =
3814 SpdySession::GetDefaultInitialWindowSize(GetParam());
3815 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3817 data.RunFor(1);
3819 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3821 data.RunFor(1);
3823 EXPECT_TRUE(data.at_write_eof());
3824 EXPECT_TRUE(data.at_read_eof());
3826 EXPECT_EQ(initial_window_size - msg_data_size,
3827 session->session_send_window_size_);
3829 // Closing the stream should increase the session's send window.
3830 stream->Close();
3831 EXPECT_EQ(NULL, stream.get());
3833 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3835 EXPECT_EQ(OK, delegate.WaitForClose());
3838 // Send data back and forth; the send and receive windows should
3839 // change appropriately.
3840 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
3841 if (GetParam() < kProtoSPDY31)
3842 return;
3844 const char kStreamUrl[] = "http://www.example.org/";
3846 const int32 msg_data_size = 100;
3847 const std::string msg_data(msg_data_size, 'a');
3849 MockConnect connect_data(SYNCHRONOUS, OK);
3851 scoped_ptr<SpdyFrame> req(
3852 spdy_util_.ConstructSpdyPost(
3853 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3854 scoped_ptr<SpdyFrame> msg(
3855 spdy_util_.ConstructSpdyBodyFrame(
3856 1, msg_data.data(), msg_data_size, false));
3857 MockWrite writes[] = {
3858 CreateMockWrite(*req, 0),
3859 CreateMockWrite(*msg, 2),
3862 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3863 scoped_ptr<SpdyFrame> echo(
3864 spdy_util_.ConstructSpdyBodyFrame(
3865 1, msg_data.data(), msg_data_size, false));
3866 scoped_ptr<SpdyFrame> window_update(
3867 spdy_util_.ConstructSpdyWindowUpdate(
3868 kSessionFlowControlStreamId, msg_data_size));
3869 MockRead reads[] = {
3870 CreateMockRead(*resp, 1),
3871 CreateMockRead(*echo, 3),
3872 CreateMockRead(*window_update, 4),
3873 MockRead(ASYNC, 0, 5) // EOF
3876 // Create SpdySession and SpdyStream and send the request.
3877 DeterministicSocketData data(reads, arraysize(reads),
3878 writes, arraysize(writes));
3879 data.set_connect_data(connect_data);
3880 session_deps_.host_resolver->set_synchronous_mode(true);
3881 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3883 CreateDeterministicNetworkSession();
3885 base::WeakPtr<SpdySession> session =
3886 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3888 GURL url(kStreamUrl);
3889 base::WeakPtr<SpdyStream> stream =
3890 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3891 session, url, MEDIUM, BoundNetLog());
3892 ASSERT_TRUE(stream.get() != NULL);
3893 EXPECT_EQ(0u, stream->stream_id());
3895 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3896 stream->SetDelegate(&delegate);
3898 scoped_ptr<SpdyHeaderBlock> headers(
3899 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3900 EXPECT_EQ(ERR_IO_PENDING,
3901 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3902 EXPECT_TRUE(stream->HasUrlFromHeaders());
3904 const int32 initial_window_size =
3905 SpdySession::GetDefaultInitialWindowSize(GetParam());
3906 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3907 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3908 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3910 data.RunFor(1);
3912 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3913 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3914 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3916 data.RunFor(1);
3918 EXPECT_EQ(initial_window_size - msg_data_size,
3919 session->session_send_window_size_);
3920 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3921 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3923 data.RunFor(1);
3925 EXPECT_EQ(initial_window_size - msg_data_size,
3926 session->session_send_window_size_);
3927 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3928 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3930 data.RunFor(1);
3932 EXPECT_EQ(initial_window_size - msg_data_size,
3933 session->session_send_window_size_);
3934 EXPECT_EQ(initial_window_size - msg_data_size,
3935 session->session_recv_window_size_);
3936 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3938 data.RunFor(1);
3940 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3941 EXPECT_EQ(initial_window_size - msg_data_size,
3942 session->session_recv_window_size_);
3943 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3945 EXPECT_TRUE(data.at_write_eof());
3946 EXPECT_TRUE(data.at_read_eof());
3948 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
3950 // Draining the delegate's read queue should increase the session's
3951 // receive window.
3952 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3953 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3954 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3956 stream->Close();
3957 EXPECT_EQ(NULL, stream.get());
3959 EXPECT_EQ(OK, delegate.WaitForClose());
3961 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3962 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3963 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3966 // Given a stall function and an unstall function, runs a test to make
3967 // sure that a stream resumes after unstall.
3968 void SpdySessionTest::RunResumeAfterUnstallTest(
3969 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
3970 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
3971 unstall_function) {
3972 const char kStreamUrl[] = "http://www.example.org/";
3973 GURL url(kStreamUrl);
3975 session_deps_.host_resolver->set_synchronous_mode(true);
3977 scoped_ptr<SpdyFrame> req(
3978 spdy_util_.ConstructSpdyPost(
3979 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3980 scoped_ptr<SpdyFrame> body(
3981 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3982 MockWrite writes[] = {
3983 CreateMockWrite(*req, 0),
3984 CreateMockWrite(*body, 1),
3987 scoped_ptr<SpdyFrame> resp(
3988 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3989 scoped_ptr<SpdyFrame> echo(
3990 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
3991 MockRead reads[] = {
3992 CreateMockRead(*resp, 2),
3993 MockRead(ASYNC, 0, 0, 3), // EOF
3996 DeterministicSocketData data(reads, arraysize(reads),
3997 writes, arraysize(writes));
3998 MockConnect connect_data(SYNCHRONOUS, OK);
3999 data.set_connect_data(connect_data);
4001 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4003 CreateDeterministicNetworkSession();
4004 base::WeakPtr<SpdySession> session =
4005 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4006 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4007 session->flow_control_state());
4009 base::WeakPtr<SpdyStream> stream =
4010 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4011 session, url, LOWEST, BoundNetLog());
4012 ASSERT_TRUE(stream.get() != NULL);
4014 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
4015 stream->SetDelegate(&delegate);
4017 EXPECT_FALSE(stream->HasUrlFromHeaders());
4018 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4020 scoped_ptr<SpdyHeaderBlock> headers(
4021 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4022 EXPECT_EQ(ERR_IO_PENDING,
4023 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4024 EXPECT_TRUE(stream->HasUrlFromHeaders());
4025 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
4027 stall_function.Run(session.get(), stream.get());
4029 data.RunFor(1);
4031 EXPECT_TRUE(stream->send_stalled_by_flow_control());
4033 unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
4035 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4037 data.RunFor(3);
4039 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
4041 EXPECT_TRUE(delegate.send_headers_completed());
4042 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
4043 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
4044 EXPECT_TRUE(data.at_write_eof());
4047 // Run the resume-after-unstall test with all possible stall and
4048 // unstall sequences.
4050 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
4051 if (GetParam() < kProtoSPDY31)
4052 return;
4054 RunResumeAfterUnstallTest(
4055 base::Bind(&SpdySessionTest::StallSessionOnly,
4056 base::Unretained(this)),
4057 base::Bind(&SpdySessionTest::UnstallSessionOnly,
4058 base::Unretained(this)));
4061 // Equivalent to
4062 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4063 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
4064 if (GetParam() < kProtoSPDY31)
4065 return;
4067 RunResumeAfterUnstallTest(
4068 base::Bind(&SpdySessionTest::StallStreamOnly,
4069 base::Unretained(this)),
4070 base::Bind(&SpdySessionTest::UnstallStreamOnly,
4071 base::Unretained(this)));
4074 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4075 if (GetParam() < kProtoSPDY31)
4076 return;
4078 RunResumeAfterUnstallTest(
4079 base::Bind(&SpdySessionTest::StallSessionStream,
4080 base::Unretained(this)),
4081 base::Bind(&SpdySessionTest::UnstallSessionStream,
4082 base::Unretained(this)));
4085 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4086 if (GetParam() < kProtoSPDY31)
4087 return;
4089 RunResumeAfterUnstallTest(
4090 base::Bind(&SpdySessionTest::StallStreamSession,
4091 base::Unretained(this)),
4092 base::Bind(&SpdySessionTest::UnstallSessionStream,
4093 base::Unretained(this)));
4096 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4097 if (GetParam() < kProtoSPDY31)
4098 return;
4100 RunResumeAfterUnstallTest(
4101 base::Bind(&SpdySessionTest::StallStreamSession,
4102 base::Unretained(this)),
4103 base::Bind(&SpdySessionTest::UnstallStreamSession,
4104 base::Unretained(this)));
4107 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4108 if (GetParam() < kProtoSPDY31)
4109 return;
4111 RunResumeAfterUnstallTest(
4112 base::Bind(&SpdySessionTest::StallSessionStream,
4113 base::Unretained(this)),
4114 base::Bind(&SpdySessionTest::UnstallStreamSession,
4115 base::Unretained(this)));
4118 // Cause a stall by reducing the flow control send window to 0. The
4119 // streams should resume in priority order when that window is then
4120 // increased.
4121 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4122 if (GetParam() < kProtoSPDY31)
4123 return;
4125 const char kStreamUrl[] = "http://www.example.org/";
4126 GURL url(kStreamUrl);
4128 session_deps_.host_resolver->set_synchronous_mode(true);
4130 scoped_ptr<SpdyFrame> req1(
4131 spdy_util_.ConstructSpdyPost(
4132 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4133 scoped_ptr<SpdyFrame> req2(
4134 spdy_util_.ConstructSpdyPost(
4135 kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
4136 scoped_ptr<SpdyFrame> body1(
4137 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4138 scoped_ptr<SpdyFrame> body2(
4139 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4140 MockWrite writes[] = {
4141 CreateMockWrite(*req1, 0),
4142 CreateMockWrite(*req2, 1),
4143 CreateMockWrite(*body2, 2),
4144 CreateMockWrite(*body1, 3),
4147 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4148 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4149 MockRead reads[] = {
4150 CreateMockRead(*resp1, 4),
4151 CreateMockRead(*resp2, 5),
4152 MockRead(ASYNC, 0, 0, 6), // EOF
4155 DeterministicSocketData data(reads, arraysize(reads),
4156 writes, arraysize(writes));
4157 MockConnect connect_data(SYNCHRONOUS, OK);
4158 data.set_connect_data(connect_data);
4160 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4162 CreateDeterministicNetworkSession();
4163 base::WeakPtr<SpdySession> session =
4164 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4165 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4166 session->flow_control_state());
4168 base::WeakPtr<SpdyStream> stream1 =
4169 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4170 session, url, LOWEST, BoundNetLog());
4171 ASSERT_TRUE(stream1.get() != NULL);
4173 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4174 stream1->SetDelegate(&delegate1);
4176 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4178 base::WeakPtr<SpdyStream> stream2 =
4179 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4180 session, url, MEDIUM, BoundNetLog());
4181 ASSERT_TRUE(stream2.get() != NULL);
4183 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4184 stream2->SetDelegate(&delegate2);
4186 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4188 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4189 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4191 StallSessionSend(session.get());
4193 scoped_ptr<SpdyHeaderBlock> headers1(
4194 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4195 EXPECT_EQ(ERR_IO_PENDING,
4196 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4197 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4198 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4200 data.RunFor(1);
4201 EXPECT_EQ(1u, stream1->stream_id());
4202 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4204 scoped_ptr<SpdyHeaderBlock> headers2(
4205 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4206 EXPECT_EQ(ERR_IO_PENDING,
4207 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4208 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4209 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4211 data.RunFor(1);
4212 EXPECT_EQ(3u, stream2->stream_id());
4213 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4215 // This should unstall only stream2.
4216 UnstallSessionSend(session.get(), kBodyDataSize);
4218 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4219 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4221 data.RunFor(1);
4223 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4224 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4226 // This should then unstall stream1.
4227 UnstallSessionSend(session.get(), kBodyDataSize);
4229 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4230 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4232 data.RunFor(4);
4234 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4235 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4237 EXPECT_TRUE(delegate1.send_headers_completed());
4238 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4239 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4241 EXPECT_TRUE(delegate2.send_headers_completed());
4242 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4243 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4245 EXPECT_TRUE(data.at_write_eof());
4248 // Delegate that closes a given stream after sending its body.
4249 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4250 public:
4251 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4252 base::StringPiece data)
4253 : StreamDelegateWithBody(stream, data) {}
4255 ~StreamClosingDelegate() override {}
4257 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4258 stream_to_close_ = stream_to_close;
4261 void OnDataSent() override {
4262 test::StreamDelegateWithBody::OnDataSent();
4263 if (stream_to_close_.get()) {
4264 stream_to_close_->Close();
4265 EXPECT_EQ(NULL, stream_to_close_.get());
4269 private:
4270 base::WeakPtr<SpdyStream> stream_to_close_;
4273 // Cause a stall by reducing the flow control send window to
4274 // 0. Unstalling the session should properly handle deleted streams.
4275 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4276 if (GetParam() < kProtoSPDY31)
4277 return;
4279 const char kStreamUrl[] = "http://www.example.org/";
4280 GURL url(kStreamUrl);
4282 session_deps_.host_resolver->set_synchronous_mode(true);
4284 scoped_ptr<SpdyFrame> req1(
4285 spdy_util_.ConstructSpdyPost(
4286 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4287 scoped_ptr<SpdyFrame> req2(
4288 spdy_util_.ConstructSpdyPost(
4289 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4290 scoped_ptr<SpdyFrame> req3(
4291 spdy_util_.ConstructSpdyPost(
4292 kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
4293 scoped_ptr<SpdyFrame> body2(
4294 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4295 MockWrite writes[] = {
4296 CreateMockWrite(*req1, 0),
4297 CreateMockWrite(*req2, 1),
4298 CreateMockWrite(*req3, 2),
4299 CreateMockWrite(*body2, 3),
4302 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4303 MockRead reads[] = {
4304 CreateMockRead(*resp2, 4),
4305 MockRead(ASYNC, 0, 0, 5), // EOF
4308 DeterministicSocketData data(reads, arraysize(reads),
4309 writes, arraysize(writes));
4310 MockConnect connect_data(SYNCHRONOUS, OK);
4311 data.set_connect_data(connect_data);
4313 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4315 CreateDeterministicNetworkSession();
4316 base::WeakPtr<SpdySession> session =
4317 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4318 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4319 session->flow_control_state());
4321 base::WeakPtr<SpdyStream> stream1 =
4322 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4323 session, url, LOWEST, BoundNetLog());
4324 ASSERT_TRUE(stream1.get() != NULL);
4326 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4327 stream1->SetDelegate(&delegate1);
4329 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4331 base::WeakPtr<SpdyStream> stream2 =
4332 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4333 session, url, LOWEST, BoundNetLog());
4334 ASSERT_TRUE(stream2.get() != NULL);
4336 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4337 stream2->SetDelegate(&delegate2);
4339 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4341 base::WeakPtr<SpdyStream> stream3 =
4342 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4343 session, url, LOWEST, BoundNetLog());
4344 ASSERT_TRUE(stream3.get() != NULL);
4346 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4347 stream3->SetDelegate(&delegate3);
4349 EXPECT_FALSE(stream3->HasUrlFromHeaders());
4351 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4352 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4353 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4355 StallSessionSend(session.get());
4357 scoped_ptr<SpdyHeaderBlock> headers1(
4358 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4359 EXPECT_EQ(ERR_IO_PENDING,
4360 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4361 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4362 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4364 data.RunFor(1);
4365 EXPECT_EQ(1u, stream1->stream_id());
4366 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4368 scoped_ptr<SpdyHeaderBlock> headers2(
4369 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4370 EXPECT_EQ(ERR_IO_PENDING,
4371 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4372 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4373 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4375 data.RunFor(1);
4376 EXPECT_EQ(3u, stream2->stream_id());
4377 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4379 scoped_ptr<SpdyHeaderBlock> headers3(
4380 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4381 EXPECT_EQ(ERR_IO_PENDING,
4382 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4383 EXPECT_TRUE(stream3->HasUrlFromHeaders());
4384 EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4386 data.RunFor(1);
4387 EXPECT_EQ(5u, stream3->stream_id());
4388 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4390 SpdyStreamId stream_id1 = stream1->stream_id();
4391 SpdyStreamId stream_id2 = stream2->stream_id();
4392 SpdyStreamId stream_id3 = stream3->stream_id();
4394 // Close stream1 preemptively.
4395 session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4396 EXPECT_EQ(NULL, stream1.get());
4398 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4399 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4400 EXPECT_TRUE(session->IsStreamActive(stream_id3));
4402 // Unstall stream2, which should then close stream3.
4403 delegate2.set_stream_to_close(stream3);
4404 UnstallSessionSend(session.get(), kBodyDataSize);
4406 data.RunFor(1);
4407 EXPECT_EQ(NULL, stream3.get());
4409 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4410 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4411 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4412 EXPECT_FALSE(session->IsStreamActive(stream_id3));
4414 data.RunFor(2);
4415 EXPECT_EQ(NULL, stream2.get());
4417 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4418 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4419 EXPECT_EQ(OK, delegate3.WaitForClose());
4421 EXPECT_TRUE(delegate1.send_headers_completed());
4422 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4424 EXPECT_TRUE(delegate2.send_headers_completed());
4425 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4426 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4428 EXPECT_TRUE(delegate3.send_headers_completed());
4429 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4431 EXPECT_TRUE(data.at_write_eof());
4434 // Cause a stall by reducing the flow control send window to
4435 // 0. Unstalling the session should properly handle the session itself
4436 // being closed.
4437 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4438 if (GetParam() < kProtoSPDY31)
4439 return;
4441 const char kStreamUrl[] = "http://www.example.org/";
4442 GURL url(kStreamUrl);
4444 session_deps_.host_resolver->set_synchronous_mode(true);
4446 scoped_ptr<SpdyFrame> req1(
4447 spdy_util_.ConstructSpdyPost(
4448 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4449 scoped_ptr<SpdyFrame> req2(
4450 spdy_util_.ConstructSpdyPost(
4451 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4452 scoped_ptr<SpdyFrame> body1(
4453 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4454 MockWrite writes[] = {
4455 CreateMockWrite(*req1, 0),
4456 CreateMockWrite(*req2, 1),
4459 MockRead reads[] = {
4460 MockRead(ASYNC, 0, 0, 2), // EOF
4463 DeterministicSocketData data(reads, arraysize(reads),
4464 writes, arraysize(writes));
4465 MockConnect connect_data(SYNCHRONOUS, OK);
4466 data.set_connect_data(connect_data);
4468 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4470 CreateDeterministicNetworkSession();
4471 base::WeakPtr<SpdySession> session =
4472 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4473 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4474 session->flow_control_state());
4476 base::WeakPtr<SpdyStream> stream1 =
4477 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4478 session, url, LOWEST, BoundNetLog());
4479 ASSERT_TRUE(stream1.get() != NULL);
4481 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4482 stream1->SetDelegate(&delegate1);
4484 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4486 base::WeakPtr<SpdyStream> stream2 =
4487 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4488 session, url, LOWEST, BoundNetLog());
4489 ASSERT_TRUE(stream2.get() != NULL);
4491 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4492 stream2->SetDelegate(&delegate2);
4494 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4496 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4497 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4499 StallSessionSend(session.get());
4501 scoped_ptr<SpdyHeaderBlock> headers1(
4502 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4503 EXPECT_EQ(ERR_IO_PENDING,
4504 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4505 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4506 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4508 data.RunFor(1);
4509 EXPECT_EQ(1u, stream1->stream_id());
4510 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4512 scoped_ptr<SpdyHeaderBlock> headers2(
4513 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4514 EXPECT_EQ(ERR_IO_PENDING,
4515 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4516 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4517 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4519 data.RunFor(1);
4520 EXPECT_EQ(3u, stream2->stream_id());
4521 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4523 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4525 // Unstall stream1.
4526 UnstallSessionSend(session.get(), kBodyDataSize);
4528 // Close the session (since we can't do it from within the delegate
4529 // method, since it's in the stream's loop).
4530 session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4531 base::RunLoop().RunUntilIdle();
4532 EXPECT_TRUE(session == NULL);
4534 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4536 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4537 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4539 EXPECT_TRUE(delegate1.send_headers_completed());
4540 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4542 EXPECT_TRUE(delegate2.send_headers_completed());
4543 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4545 EXPECT_TRUE(data.at_write_eof());
4548 TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4549 if (GetParam() < kProtoSPDY31)
4550 return;
4552 MockConnect connect_data(SYNCHRONOUS, OK);
4554 scoped_ptr<SpdyFrame> req(
4555 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4556 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4558 GOAWAY_FLOW_CONTROL_ERROR,
4559 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4560 "the receive window size of 1"));
4561 MockWrite writes[] = {
4562 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
4565 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4566 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4567 MockRead reads[] = {
4568 CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
4571 DeterministicSocketData data(
4572 reads, arraysize(reads), writes, arraysize(writes));
4573 data.set_connect_data(connect_data);
4574 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4576 CreateDeterministicNetworkSession();
4578 base::WeakPtr<SpdySession> session =
4579 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4581 GURL url(kDefaultURL);
4582 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4583 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
4584 ASSERT_TRUE(spdy_stream.get() != NULL);
4585 test::StreamDelegateDoNothing delegate(spdy_stream);
4586 spdy_stream->SetDelegate(&delegate);
4588 scoped_ptr<SpdyHeaderBlock> headers(
4589 spdy_util_.ConstructGetHeaderBlock(url.spec()));
4590 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4592 data.RunFor(1); // Write request.
4594 // Put session on the edge of overflowing it's recv window.
4595 session->session_recv_window_size_ = 1;
4597 // Read response headers & body. Body overflows the session window, and a
4598 // goaway is written.
4599 data.RunFor(3);
4600 base::MessageLoop::current()->RunUntilIdle();
4602 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4603 EXPECT_TRUE(session == NULL);
4606 TEST_P(SpdySessionTest, SplitHeaders) {
4607 GURL kStreamUrl("http://www.example.org/foo.dat");
4608 SpdyHeaderBlock headers;
4609 spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4610 headers["alpha"] = "beta";
4612 SpdyHeaderBlock request_headers;
4613 SpdyHeaderBlock response_headers;
4615 SplitPushedHeadersToRequestAndResponse(
4616 headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4618 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4619 std::string alpha_val =
4620 (it == response_headers.end()) ? std::string() : it->second;
4621 EXPECT_EQ("beta", alpha_val);
4623 GURL request_url =
4624 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4625 EXPECT_EQ(kStreamUrl, request_url);
4628 // Regression. Sorta. Push streams and client streams were sharing a single
4629 // limit for a long time.
4630 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4631 SettingsMap new_settings;
4632 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4633 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4634 scoped_ptr<SpdyFrame> settings_frame(
4635 spdy_util_.ConstructSpdySettings(new_settings));
4636 scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4637 NULL, 0, 2, 1, "http://www.example.org/a.dat"));
4638 MockRead reads[] = {
4639 CreateMockRead(*settings_frame), CreateMockRead(*pushed, 3),
4640 MockRead(ASYNC, 0, 4),
4643 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4644 scoped_ptr<SpdyFrame> req(
4645 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4646 MockWrite writes[] = {
4647 CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4650 DeterministicSocketData data(
4651 reads, arraysize(reads), writes, arraysize(writes));
4652 MockConnect connect_data(SYNCHRONOUS, OK);
4653 data.set_connect_data(connect_data);
4654 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4656 CreateDeterministicNetworkSession();
4658 base::WeakPtr<SpdySession> session =
4659 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4661 // Read the settings frame.
4662 data.RunFor(1);
4664 GURL url1(kDefaultURL);
4665 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4666 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4667 ASSERT_TRUE(spdy_stream1.get() != NULL);
4668 EXPECT_EQ(0u, spdy_stream1->stream_id());
4669 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4670 spdy_stream1->SetDelegate(&delegate1);
4672 EXPECT_EQ(0u, session->num_active_streams());
4673 EXPECT_EQ(1u, session->num_created_streams());
4674 EXPECT_EQ(0u, session->num_pushed_streams());
4675 EXPECT_EQ(0u, session->num_active_pushed_streams());
4677 scoped_ptr<SpdyHeaderBlock> headers(
4678 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4679 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4680 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4682 // Run until 1st stream is activated.
4683 EXPECT_EQ(0u, delegate1.stream_id());
4684 data.RunFor(2);
4685 EXPECT_EQ(1u, delegate1.stream_id());
4686 EXPECT_EQ(1u, session->num_active_streams());
4687 EXPECT_EQ(0u, session->num_created_streams());
4688 EXPECT_EQ(0u, session->num_pushed_streams());
4689 EXPECT_EQ(0u, session->num_active_pushed_streams());
4691 // Run until pushed stream is created.
4692 data.RunFor(1);
4693 EXPECT_EQ(2u, session->num_active_streams());
4694 EXPECT_EQ(0u, session->num_created_streams());
4695 EXPECT_EQ(1u, session->num_pushed_streams());
4696 EXPECT_EQ(1u, session->num_active_pushed_streams());
4698 // Second stream should not be stalled, although we have 2 active streams, but
4699 // one of them is push stream and should not be taken into account when we
4700 // create streams on the client.
4701 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4702 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4703 EXPECT_TRUE(spdy_stream2.get() != NULL);
4704 EXPECT_EQ(2u, session->num_active_streams());
4705 EXPECT_EQ(1u, session->num_created_streams());
4706 EXPECT_EQ(1u, session->num_pushed_streams());
4707 EXPECT_EQ(1u, session->num_active_pushed_streams());
4709 // Read EOF.
4710 data.RunFor(1);
4713 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4714 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4715 NULL, 0, 2, 1, "http://www.example.org/a.dat"));
4716 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4717 NULL, 0, 4, 1, "http://www.example.org/b.dat"));
4718 MockRead reads[] = {
4719 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4720 MockRead(ASYNC, 0, 4),
4723 scoped_ptr<SpdyFrame> req(
4724 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4725 scoped_ptr<SpdyFrame> rst(
4726 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4727 MockWrite writes[] = {
4728 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4731 DeterministicSocketData data(
4732 reads, arraysize(reads), writes, arraysize(writes));
4733 MockConnect connect_data(SYNCHRONOUS, OK);
4734 data.set_connect_data(connect_data);
4735 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4737 CreateDeterministicNetworkSession();
4739 base::WeakPtr<SpdySession> session =
4740 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4741 session->set_max_concurrent_pushed_streams(1);
4743 GURL url1(kDefaultURL);
4744 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4745 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4746 ASSERT_TRUE(spdy_stream1.get() != NULL);
4747 EXPECT_EQ(0u, spdy_stream1->stream_id());
4748 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4749 spdy_stream1->SetDelegate(&delegate1);
4751 EXPECT_EQ(0u, session->num_active_streams());
4752 EXPECT_EQ(1u, session->num_created_streams());
4753 EXPECT_EQ(0u, session->num_pushed_streams());
4754 EXPECT_EQ(0u, session->num_active_pushed_streams());
4756 scoped_ptr<SpdyHeaderBlock> headers(
4757 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4758 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4759 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4761 // Run until 1st stream is activated.
4762 EXPECT_EQ(0u, delegate1.stream_id());
4763 data.RunFor(1);
4764 EXPECT_EQ(1u, delegate1.stream_id());
4765 EXPECT_EQ(1u, session->num_active_streams());
4766 EXPECT_EQ(0u, session->num_created_streams());
4767 EXPECT_EQ(0u, session->num_pushed_streams());
4768 EXPECT_EQ(0u, session->num_active_pushed_streams());
4770 // Run until pushed stream is created.
4771 data.RunFor(1);
4772 EXPECT_EQ(2u, session->num_active_streams());
4773 EXPECT_EQ(0u, session->num_created_streams());
4774 EXPECT_EQ(1u, session->num_pushed_streams());
4775 EXPECT_EQ(1u, session->num_active_pushed_streams());
4777 // Reset incoming pushed stream.
4778 data.RunFor(2);
4779 EXPECT_EQ(2u, session->num_active_streams());
4780 EXPECT_EQ(0u, session->num_created_streams());
4781 EXPECT_EQ(1u, session->num_pushed_streams());
4782 EXPECT_EQ(1u, session->num_active_pushed_streams());
4784 // Read EOF.
4785 data.RunFor(1);
4788 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4789 // Streams in reserved remote state exist only in SPDY4.
4790 if (spdy_util_.spdy_version() < SPDY4)
4791 return;
4793 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4794 NULL, 0, 2, 1, "http://www.example.org/a.dat"));
4795 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4796 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/b.dat",
4797 push_headers.get());
4798 scoped_ptr<SpdyFrame> push_b(
4799 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4800 scoped_ptr<SpdyFrame> headers_b(
4801 spdy_util_.ConstructSpdyPushHeaders(4, NULL, 0));
4802 MockRead reads[] = {
4803 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4804 CreateMockRead(*headers_b, 3), MockRead(ASYNC, 0, 5),
4807 scoped_ptr<SpdyFrame> req(
4808 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4809 scoped_ptr<SpdyFrame> rst(
4810 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4811 MockWrite writes[] = {
4812 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
4815 DeterministicSocketData data(
4816 reads, arraysize(reads), writes, arraysize(writes));
4817 MockConnect connect_data(SYNCHRONOUS, OK);
4818 data.set_connect_data(connect_data);
4819 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4821 CreateDeterministicNetworkSession();
4823 base::WeakPtr<SpdySession> session =
4824 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4825 session->set_max_concurrent_pushed_streams(1);
4827 GURL url1(kDefaultURL);
4828 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4829 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4830 ASSERT_TRUE(spdy_stream1.get() != NULL);
4831 EXPECT_EQ(0u, spdy_stream1->stream_id());
4832 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4833 spdy_stream1->SetDelegate(&delegate1);
4835 EXPECT_EQ(0u, session->num_active_streams());
4836 EXPECT_EQ(1u, session->num_created_streams());
4837 EXPECT_EQ(0u, session->num_pushed_streams());
4838 EXPECT_EQ(0u, session->num_active_pushed_streams());
4840 scoped_ptr<SpdyHeaderBlock> headers(
4841 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4842 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4843 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4845 // Run until 1st stream is activated.
4846 EXPECT_EQ(0u, delegate1.stream_id());
4847 data.RunFor(1);
4848 EXPECT_EQ(1u, delegate1.stream_id());
4849 EXPECT_EQ(1u, session->num_active_streams());
4850 EXPECT_EQ(0u, session->num_created_streams());
4851 EXPECT_EQ(0u, session->num_pushed_streams());
4852 EXPECT_EQ(0u, session->num_active_pushed_streams());
4854 // Run until pushed stream is created.
4855 data.RunFor(1);
4856 EXPECT_EQ(2u, session->num_active_streams());
4857 EXPECT_EQ(0u, session->num_created_streams());
4858 EXPECT_EQ(1u, session->num_pushed_streams());
4859 EXPECT_EQ(1u, session->num_active_pushed_streams());
4861 // Accept promised stream. It should not count towards pushed stream limit.
4862 data.RunFor(1);
4863 EXPECT_EQ(3u, session->num_active_streams());
4864 EXPECT_EQ(0u, session->num_created_streams());
4865 EXPECT_EQ(2u, session->num_pushed_streams());
4866 EXPECT_EQ(1u, session->num_active_pushed_streams());
4868 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4869 // while we accept only one.
4870 data.RunFor(2);
4871 EXPECT_EQ(2u, session->num_active_streams());
4872 EXPECT_EQ(0u, session->num_created_streams());
4873 EXPECT_EQ(1u, session->num_pushed_streams());
4874 EXPECT_EQ(1u, session->num_active_pushed_streams());
4876 // Read EOF.
4877 data.RunFor(1);
4880 TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
4881 // Streams in reserved remote state exist only in SPDY4.
4882 if (spdy_util_.spdy_version() < SPDY4)
4883 return;
4885 const char kPushedUrl[] = "http://www.example.org/a.dat";
4886 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4887 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
4888 scoped_ptr<SpdyFrame> push_promise(
4889 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
4890 scoped_ptr<SpdyFrame> headers_frame(
4891 spdy_util_.ConstructSpdyPushHeaders(2, NULL, 0));
4892 MockRead reads[] = {
4893 CreateMockRead(*push_promise, 1), CreateMockRead(*headers_frame, 2),
4894 MockRead(ASYNC, 0, 4),
4897 scoped_ptr<SpdyFrame> req(
4898 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4899 scoped_ptr<SpdyFrame> rst(
4900 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
4901 MockWrite writes[] = {
4902 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4905 DeterministicSocketData data(
4906 reads, arraysize(reads), writes, arraysize(writes));
4907 MockConnect connect_data(SYNCHRONOUS, OK);
4908 data.set_connect_data(connect_data);
4909 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4911 CreateDeterministicNetworkSession();
4913 base::WeakPtr<SpdySession> session =
4914 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4916 GURL url1(kDefaultURL);
4917 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4918 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4919 ASSERT_TRUE(spdy_stream1.get() != NULL);
4920 EXPECT_EQ(0u, spdy_stream1->stream_id());
4921 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4922 spdy_stream1->SetDelegate(&delegate1);
4924 EXPECT_EQ(0u, session->num_active_streams());
4925 EXPECT_EQ(1u, session->num_created_streams());
4926 EXPECT_EQ(0u, session->num_pushed_streams());
4927 EXPECT_EQ(0u, session->num_active_pushed_streams());
4929 scoped_ptr<SpdyHeaderBlock> headers(
4930 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4931 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4932 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4934 // Run until 1st stream is activated.
4935 EXPECT_EQ(0u, delegate1.stream_id());
4936 data.RunFor(1);
4937 EXPECT_EQ(1u, delegate1.stream_id());
4938 EXPECT_EQ(1u, session->num_active_streams());
4939 EXPECT_EQ(0u, session->num_created_streams());
4940 EXPECT_EQ(0u, session->num_pushed_streams());
4941 EXPECT_EQ(0u, session->num_active_pushed_streams());
4943 // Run until pushed stream is created.
4944 data.RunFor(1);
4945 EXPECT_EQ(2u, session->num_active_streams());
4946 EXPECT_EQ(0u, session->num_created_streams());
4947 EXPECT_EQ(1u, session->num_pushed_streams());
4948 EXPECT_EQ(0u, session->num_active_pushed_streams());
4950 base::WeakPtr<SpdyStream> pushed_stream;
4951 int rv =
4952 session->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
4953 ASSERT_EQ(OK, rv);
4954 ASSERT_TRUE(pushed_stream.get() != NULL);
4955 test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
4956 pushed_stream->SetDelegate(&delegate2);
4958 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4959 // that all our counters are in consistent state.
4960 data.RunFor(1);
4961 EXPECT_EQ(1u, session->num_active_streams());
4962 EXPECT_EQ(0u, session->num_created_streams());
4963 EXPECT_EQ(0u, session->num_pushed_streams());
4964 EXPECT_EQ(0u, session->num_active_pushed_streams());
4966 // Read EOF.
4967 data.RunFor(2);
4970 TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
4971 session_deps_.host_resolver->set_synchronous_mode(true);
4973 MockRead reads[] = {
4974 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
4977 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
4979 MockConnect connect_data(SYNCHRONOUS, OK);
4980 data.set_connect_data(connect_data);
4981 session_deps_.socket_factory->AddSocketDataProvider(&data);
4983 CreateNetworkSession();
4984 base::WeakPtr<SpdySession> session =
4985 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4987 session->stream_hi_water_mark_ = 5;
4988 // Low client (odd) ids are fine.
4989 EXPECT_TRUE(session->OnUnknownFrame(3, 0));
4990 // Client id exceeding watermark.
4991 EXPECT_FALSE(session->OnUnknownFrame(9, 0));
4993 session->last_accepted_push_stream_id_ = 6;
4994 // Low server (even) ids are fine.
4995 EXPECT_TRUE(session->OnUnknownFrame(2, 0));
4996 // Server id exceeding last accepted id.
4997 EXPECT_FALSE(session->OnUnknownFrame(8, 0));
5000 TEST(MapFramerErrorToProtocolError, MapsValues) {
5001 CHECK_EQ(
5002 SPDY_ERROR_INVALID_CONTROL_FRAME,
5003 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
5004 CHECK_EQ(
5005 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
5006 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
5007 CHECK_EQ(
5008 SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
5009 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
5010 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
5011 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
5014 TEST(MapFramerErrorToNetError, MapsValue) {
5015 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
5016 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
5017 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5018 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
5019 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5020 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
5021 CHECK_EQ(
5022 ERR_SPDY_FRAME_SIZE_ERROR,
5023 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
5026 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
5027 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
5028 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
5029 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
5030 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
5031 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
5032 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
5033 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY,
5034 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY));
5035 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED,
5036 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED));
5039 TEST(MapNetErrorToGoAwayStatus, MapsValue) {
5040 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
5041 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
5042 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
5043 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
5044 CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
5045 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
5046 CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
5047 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
5048 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
5049 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
5050 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
5053 TEST(CanPoolTest, CanPool) {
5054 // Load a cert that is valid for:
5055 // www.example.org
5056 // mail.example.org
5057 // www.example.com
5059 TransportSecurityState tss;
5060 SSLInfo ssl_info;
5061 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5062 "spdy_pooling.pem");
5064 EXPECT_TRUE(SpdySession::CanPool(
5065 &tss, ssl_info, "www.example.org", "www.example.org"));
5066 EXPECT_TRUE(SpdySession::CanPool(
5067 &tss, ssl_info, "www.example.org", "mail.example.org"));
5068 EXPECT_TRUE(SpdySession::CanPool(
5069 &tss, ssl_info, "www.example.org", "mail.example.com"));
5070 EXPECT_FALSE(SpdySession::CanPool(
5071 &tss, ssl_info, "www.example.org", "mail.google.com"));
5074 TEST(CanPoolTest, CanNotPoolWithCertErrors) {
5075 // Load a cert that is valid for:
5076 // www.example.org
5077 // mail.example.org
5078 // www.example.com
5080 TransportSecurityState tss;
5081 SSLInfo ssl_info;
5082 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5083 "spdy_pooling.pem");
5084 ssl_info.cert_status = CERT_STATUS_REVOKED;
5086 EXPECT_FALSE(SpdySession::CanPool(
5087 &tss, ssl_info, "www.example.org", "mail.example.org"));
5090 TEST(CanPoolTest, CanNotPoolWithClientCerts) {
5091 // Load a cert that is valid for:
5092 // www.example.org
5093 // mail.example.org
5094 // www.example.com
5096 TransportSecurityState tss;
5097 SSLInfo ssl_info;
5098 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5099 "spdy_pooling.pem");
5100 ssl_info.client_cert_sent = true;
5102 EXPECT_FALSE(SpdySession::CanPool(
5103 &tss, ssl_info, "www.example.org", "mail.example.org"));
5106 TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
5107 // Load a cert that is valid for:
5108 // www.example.org
5109 // mail.example.org
5110 // www.example.com
5112 TransportSecurityState tss;
5113 SSLInfo ssl_info;
5114 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5115 "spdy_pooling.pem");
5116 ssl_info.channel_id_sent = true;
5118 EXPECT_TRUE(SpdySession::CanPool(
5119 &tss, ssl_info, "www.example.org", "mail.example.org"));
5120 EXPECT_FALSE(SpdySession::CanPool(
5121 &tss, ssl_info, "www.example.org", "www.example.com"));
5124 TEST(CanPoolTest, CanNotPoolWithBadPins) {
5125 uint8 primary_pin = 1;
5126 uint8 backup_pin = 2;
5127 uint8 bad_pin = 3;
5128 TransportSecurityState tss;
5129 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5131 SSLInfo ssl_info;
5132 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5133 "spdy_pooling.pem");
5134 ssl_info.is_issued_by_known_root = true;
5135 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
5137 EXPECT_FALSE(SpdySession::CanPool(
5138 &tss, ssl_info, "www.example.org", "mail.example.org"));
5141 TEST(CanPoolTest, CanPoolWithAcceptablePins) {
5142 uint8 primary_pin = 1;
5143 uint8 backup_pin = 2;
5144 TransportSecurityState tss;
5145 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5147 SSLInfo ssl_info;
5148 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5149 "spdy_pooling.pem");
5150 ssl_info.is_issued_by_known_root = true;
5151 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
5153 EXPECT_TRUE(SpdySession::CanPool(
5154 &tss, ssl_info, "www.example.org", "mail.example.org"));
5157 } // namespace net