Move InMemoryURLIndex into chrome/browser/autocomplete
[chromium-blink-merge.git] / net / spdy / spdy_session_unittest.cc
blobf8dbdeaeab4e878a732a1b02d9e09ad964f6d0d5
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/net_log_unittest.h"
16 #include "net/base/request_priority.h"
17 #include "net/base/test_data_directory.h"
18 #include "net/base/test_data_stream.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(
182 NextProto,
183 SpdySessionTest,
184 testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
186 // Try to create a SPDY session that will fail during
187 // initialization. Nothing should blow up.
188 TEST_P(SpdySessionTest, InitialReadError) {
189 CreateDeterministicNetworkSession();
191 base::WeakPtr<SpdySession> session = TryCreateFakeSpdySessionExpectingFailure(
192 spdy_session_pool_, key_, ERR_CONNECTION_CLOSED);
193 EXPECT_TRUE(session);
194 // Flush the read.
195 base::RunLoop().RunUntilIdle();
196 EXPECT_FALSE(session);
199 namespace {
201 // A helper class that vends a callback that, when fired, destroys a
202 // given SpdyStreamRequest.
203 class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
204 public:
205 StreamRequestDestroyingCallback() {}
207 ~StreamRequestDestroyingCallback() override {}
209 void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) {
210 request_ = request.Pass();
213 CompletionCallback MakeCallback() {
214 return base::Bind(&StreamRequestDestroyingCallback::OnComplete,
215 base::Unretained(this));
218 private:
219 void OnComplete(int result) {
220 request_.reset();
221 SetResult(result);
224 scoped_ptr<SpdyStreamRequest> request_;
227 } // namespace
229 // Request kInitialMaxConcurrentStreams streams. Request two more
230 // streams, but have the callback for one destroy the second stream
231 // request. Close the session. Nothing should blow up. This is a
232 // regression test for http://crbug.com/250841 .
233 TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
234 session_deps_.host_resolver->set_synchronous_mode(true);
236 MockRead reads[] = {MockRead(ASYNC, 0, 0), };
238 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
239 MockConnect connect_data(SYNCHRONOUS, OK);
240 data.set_connect_data(connect_data);
241 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
243 CreateDeterministicNetworkSession();
245 base::WeakPtr<SpdySession> session =
246 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
248 // Create the maximum number of concurrent streams.
249 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
250 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
251 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog());
252 ASSERT_TRUE(spdy_stream != NULL);
255 SpdyStreamRequest request1;
256 scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest);
258 StreamRequestDestroyingCallback callback1;
259 ASSERT_EQ(ERR_IO_PENDING,
260 request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM,
261 session,
262 test_url_,
263 MEDIUM,
264 BoundNetLog(),
265 callback1.MakeCallback()));
267 // |callback2| is never called.
268 TestCompletionCallback callback2;
269 ASSERT_EQ(ERR_IO_PENDING,
270 request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM,
271 session,
272 test_url_,
273 MEDIUM,
274 BoundNetLog(),
275 callback2.callback()));
277 callback1.SetRequestToDestroy(request2.Pass());
279 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
281 EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
284 // A session receiving a GOAWAY frame with no active streams should close.
285 TEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
286 session_deps_.host_resolver->set_synchronous_mode(true);
288 MockConnect connect_data(SYNCHRONOUS, OK);
289 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
290 MockRead reads[] = {
291 CreateMockRead(*goaway, 0),
293 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
294 data.set_connect_data(connect_data);
295 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
297 CreateDeterministicNetworkSession();
299 base::WeakPtr<SpdySession> session =
300 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
302 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
304 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
306 // Read and process the GOAWAY frame.
307 data.RunFor(1);
308 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
309 base::RunLoop().RunUntilIdle();
310 EXPECT_TRUE(session == NULL);
313 // A session receiving a GOAWAY frame immediately with no active
314 // streams should then close.
315 TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
316 session_deps_.host_resolver->set_synchronous_mode(true);
318 MockConnect connect_data(SYNCHRONOUS, OK);
319 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
320 MockRead reads[] = {
321 CreateMockRead(*goaway, 0, SYNCHRONOUS),
323 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
324 data.set_connect_data(connect_data);
325 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
327 CreateDeterministicNetworkSession();
329 data.StopAfter(1);
331 base::WeakPtr<SpdySession> session =
332 TryCreateInsecureSpdySessionExpectingFailure(
333 http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
334 base::RunLoop().RunUntilIdle();
336 EXPECT_FALSE(session);
337 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
340 // A session receiving a GOAWAY frame with active streams should close
341 // when the last active stream is closed.
342 TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
343 session_deps_.host_resolver->set_synchronous_mode(true);
345 MockConnect connect_data(SYNCHRONOUS, OK);
346 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
347 MockRead reads[] = {
348 CreateMockRead(*goaway, 2),
349 MockRead(ASYNC, 0, 3) // EOF
351 scoped_ptr<SpdyFrame> req1(
352 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
353 scoped_ptr<SpdyFrame> req2(
354 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
355 MockWrite writes[] = {
356 CreateMockWrite(*req1, 0),
357 CreateMockWrite(*req2, 1),
359 DeterministicSocketData data(reads, arraysize(reads),
360 writes, arraysize(writes));
361 data.set_connect_data(connect_data);
362 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
364 CreateDeterministicNetworkSession();
366 base::WeakPtr<SpdySession> session =
367 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
369 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
371 GURL url(kDefaultURL);
372 base::WeakPtr<SpdyStream> spdy_stream1 =
373 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
374 session, url, MEDIUM, BoundNetLog());
375 test::StreamDelegateDoNothing delegate1(spdy_stream1);
376 spdy_stream1->SetDelegate(&delegate1);
378 base::WeakPtr<SpdyStream> spdy_stream2 =
379 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
380 session, url, MEDIUM, BoundNetLog());
381 test::StreamDelegateDoNothing delegate2(spdy_stream2);
382 spdy_stream2->SetDelegate(&delegate2);
384 scoped_ptr<SpdyHeaderBlock> headers(
385 spdy_util_.ConstructGetHeaderBlock(url.spec()));
386 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
388 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
389 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
390 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
391 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
393 data.RunFor(2);
395 EXPECT_EQ(1u, spdy_stream1->stream_id());
396 EXPECT_EQ(3u, spdy_stream2->stream_id());
398 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
400 // Read and process the GOAWAY frame.
401 data.RunFor(1);
403 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
405 EXPECT_FALSE(session->IsStreamActive(3));
406 EXPECT_EQ(NULL, spdy_stream2.get());
407 EXPECT_TRUE(session->IsStreamActive(1));
409 EXPECT_TRUE(session->IsGoingAway());
411 // Should close the session.
412 spdy_stream1->Close();
413 EXPECT_EQ(NULL, spdy_stream1.get());
415 base::MessageLoop::current()->RunUntilIdle();
416 EXPECT_TRUE(session == NULL);
419 // Have a session receive two GOAWAY frames, with the last one causing
420 // the last active stream to be closed. The session should then be
421 // closed after the second GOAWAY frame.
422 TEST_P(SpdySessionTest, GoAwayTwice) {
423 session_deps_.host_resolver->set_synchronous_mode(true);
425 MockConnect connect_data(SYNCHRONOUS, OK);
426 scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
427 scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
428 MockRead reads[] = {
429 CreateMockRead(*goaway1, 2),
430 CreateMockRead(*goaway2, 3),
431 MockRead(ASYNC, 0, 4) // EOF
433 scoped_ptr<SpdyFrame> req1(
434 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
435 scoped_ptr<SpdyFrame> req2(
436 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
437 MockWrite writes[] = {
438 CreateMockWrite(*req1, 0),
439 CreateMockWrite(*req2, 1),
441 DeterministicSocketData data(reads, arraysize(reads),
442 writes, arraysize(writes));
443 data.set_connect_data(connect_data);
444 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
446 CreateDeterministicNetworkSession();
448 base::WeakPtr<SpdySession> session =
449 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
451 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
453 GURL url(kDefaultURL);
454 base::WeakPtr<SpdyStream> spdy_stream1 =
455 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
456 session, url, MEDIUM, BoundNetLog());
457 test::StreamDelegateDoNothing delegate1(spdy_stream1);
458 spdy_stream1->SetDelegate(&delegate1);
460 base::WeakPtr<SpdyStream> spdy_stream2 =
461 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
462 session, url, MEDIUM, BoundNetLog());
463 test::StreamDelegateDoNothing delegate2(spdy_stream2);
464 spdy_stream2->SetDelegate(&delegate2);
466 scoped_ptr<SpdyHeaderBlock> headers(
467 spdy_util_.ConstructGetHeaderBlock(url.spec()));
468 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
470 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
471 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
472 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
473 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
475 data.RunFor(2);
477 EXPECT_EQ(1u, spdy_stream1->stream_id());
478 EXPECT_EQ(3u, spdy_stream2->stream_id());
480 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
482 // Read and process the first GOAWAY frame.
483 data.RunFor(1);
485 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
487 EXPECT_FALSE(session->IsStreamActive(3));
488 EXPECT_EQ(NULL, spdy_stream2.get());
489 EXPECT_TRUE(session->IsStreamActive(1));
490 EXPECT_TRUE(session->IsGoingAway());
492 // Read and process the second GOAWAY frame, which should close the
493 // session.
494 data.RunFor(1);
495 base::MessageLoop::current()->RunUntilIdle();
496 EXPECT_TRUE(session == NULL);
499 // Have a session with active streams receive a GOAWAY frame and then
500 // close it. It should handle the close properly (i.e., not try to
501 // make itself unavailable in its pool twice).
502 TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
503 session_deps_.host_resolver->set_synchronous_mode(true);
505 MockConnect connect_data(SYNCHRONOUS, OK);
506 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
507 MockRead reads[] = {
508 CreateMockRead(*goaway, 2),
509 MockRead(ASYNC, 0, 3) // EOF
511 scoped_ptr<SpdyFrame> req1(
512 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
513 scoped_ptr<SpdyFrame> req2(
514 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
515 MockWrite writes[] = {
516 CreateMockWrite(*req1, 0),
517 CreateMockWrite(*req2, 1),
519 DeterministicSocketData data(reads, arraysize(reads),
520 writes, arraysize(writes));
521 data.set_connect_data(connect_data);
522 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
524 CreateDeterministicNetworkSession();
526 base::WeakPtr<SpdySession> session =
527 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
529 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
531 GURL url(kDefaultURL);
532 base::WeakPtr<SpdyStream> spdy_stream1 =
533 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
534 session, url, MEDIUM, BoundNetLog());
535 test::StreamDelegateDoNothing delegate1(spdy_stream1);
536 spdy_stream1->SetDelegate(&delegate1);
538 base::WeakPtr<SpdyStream> spdy_stream2 =
539 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
540 session, url, MEDIUM, BoundNetLog());
541 test::StreamDelegateDoNothing delegate2(spdy_stream2);
542 spdy_stream2->SetDelegate(&delegate2);
544 scoped_ptr<SpdyHeaderBlock> headers(
545 spdy_util_.ConstructGetHeaderBlock(url.spec()));
546 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
548 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
549 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
550 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
551 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
553 data.RunFor(2);
555 EXPECT_EQ(1u, spdy_stream1->stream_id());
556 EXPECT_EQ(3u, spdy_stream2->stream_id());
558 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
560 // Read and process the GOAWAY frame.
561 data.RunFor(1);
563 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
565 EXPECT_FALSE(session->IsStreamActive(3));
566 EXPECT_EQ(NULL, spdy_stream2.get());
567 EXPECT_TRUE(session->IsStreamActive(1));
568 EXPECT_TRUE(session->IsGoingAway());
570 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
571 EXPECT_EQ(NULL, spdy_stream1.get());
573 base::MessageLoop::current()->RunUntilIdle();
574 EXPECT_TRUE(session == NULL);
577 // Process a joint read buffer which causes the session to begin draining, and
578 // then processes a GOAWAY. The session should gracefully drain. Regression test
579 // for crbug.com/379469
580 TEST_P(SpdySessionTest, GoAwayWhileDraining) {
581 session_deps_.host_resolver->set_synchronous_mode(true);
583 scoped_ptr<SpdyFrame> req(
584 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
585 MockWrite writes[] = {
586 CreateMockWrite(*req, 0),
589 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
590 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
591 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
592 size_t joint_size = goaway->size() * 2 + body->size();
594 // Compose interleaved |goaway| and |body| frames into a single read.
595 scoped_ptr<char[]> buffer(new char[joint_size]);
597 size_t out = 0;
598 memcpy(&buffer[out], goaway->data(), goaway->size());
599 out += goaway->size();
600 memcpy(&buffer[out], body->data(), body->size());
601 out += body->size();
602 memcpy(&buffer[out], goaway->data(), goaway->size());
603 out += goaway->size();
604 ASSERT_EQ(out, joint_size);
606 SpdyFrame joint_frames(buffer.get(), joint_size, false);
608 MockRead reads[] = {
609 CreateMockRead(*resp, 1), CreateMockRead(joint_frames, 2),
610 MockRead(ASYNC, 0, 3) // EOF
613 MockConnect connect_data(SYNCHRONOUS, OK);
614 DeterministicSocketData data(
615 reads, arraysize(reads), writes, arraysize(writes));
616 data.set_connect_data(connect_data);
617 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
619 CreateDeterministicNetworkSession();
620 base::WeakPtr<SpdySession> session =
621 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
623 GURL url(kDefaultURL);
624 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
625 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
626 test::StreamDelegateDoNothing delegate(spdy_stream);
627 spdy_stream->SetDelegate(&delegate);
629 scoped_ptr<SpdyHeaderBlock> headers(
630 spdy_util_.ConstructGetHeaderBlock(url.spec()));
631 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
632 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
634 data.RunFor(3);
635 base::MessageLoop::current()->RunUntilIdle();
637 // Stream and session closed gracefully.
638 EXPECT_TRUE(delegate.StreamIsClosed());
639 EXPECT_EQ(OK, delegate.WaitForClose());
640 EXPECT_EQ(kUploadData, delegate.TakeReceivedData());
641 EXPECT_TRUE(session == NULL);
644 // Try to create a stream after receiving a GOAWAY frame. It should
645 // fail.
646 TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
647 session_deps_.host_resolver->set_synchronous_mode(true);
649 MockConnect connect_data(SYNCHRONOUS, OK);
650 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
651 MockRead reads[] = {
652 CreateMockRead(*goaway, 1),
653 MockRead(ASYNC, 0, 2) // EOF
655 scoped_ptr<SpdyFrame> req(
656 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
657 MockWrite writes[] = {
658 CreateMockWrite(*req, 0),
660 DeterministicSocketData data(reads, arraysize(reads),
661 writes, arraysize(writes));
662 data.set_connect_data(connect_data);
663 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
665 CreateDeterministicNetworkSession();
667 base::WeakPtr<SpdySession> session =
668 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
670 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
672 GURL url(kDefaultURL);
673 base::WeakPtr<SpdyStream> spdy_stream =
674 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
675 session, url, MEDIUM, BoundNetLog());
676 test::StreamDelegateDoNothing delegate(spdy_stream);
677 spdy_stream->SetDelegate(&delegate);
679 scoped_ptr<SpdyHeaderBlock> headers(
680 spdy_util_.ConstructGetHeaderBlock(url.spec()));
681 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
682 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
684 data.RunFor(1);
686 EXPECT_EQ(1u, spdy_stream->stream_id());
688 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
690 // Read and process the GOAWAY frame.
691 data.RunFor(1);
693 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
694 EXPECT_TRUE(session->IsStreamActive(1));
696 SpdyStreamRequest stream_request;
697 int rv = stream_request.StartRequest(
698 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog(),
699 CompletionCallback());
700 EXPECT_EQ(ERR_FAILED, rv);
702 // Read and process EOF.
703 data.RunFor(1);
705 EXPECT_TRUE(session == NULL);
708 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
709 // the stream being refused.
710 TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
711 session_deps_.host_resolver->set_synchronous_mode(true);
713 MockConnect connect_data(SYNCHRONOUS, OK);
714 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
715 scoped_ptr<SpdyFrame>
716 push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kDefaultURL));
717 MockRead reads[] = {
718 CreateMockRead(*goaway, 1),
719 CreateMockRead(*push, 2),
720 MockRead(ASYNC, 0, 4) // EOF
722 scoped_ptr<SpdyFrame> req(
723 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
724 scoped_ptr<SpdyFrame> rst(
725 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
726 MockWrite writes[] = {
727 CreateMockWrite(*req, 0),
728 CreateMockWrite(*rst, 3)
730 DeterministicSocketData data(reads, arraysize(reads),
731 writes, arraysize(writes));
732 data.set_connect_data(connect_data);
733 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
735 CreateDeterministicNetworkSession();
737 base::WeakPtr<SpdySession> session =
738 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
740 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
742 GURL url(kDefaultURL);
743 base::WeakPtr<SpdyStream> spdy_stream =
744 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
745 session, url, MEDIUM, BoundNetLog());
746 test::StreamDelegateDoNothing delegate(spdy_stream);
747 spdy_stream->SetDelegate(&delegate);
749 scoped_ptr<SpdyHeaderBlock> headers(
750 spdy_util_.ConstructGetHeaderBlock(url.spec()));
751 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
752 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
754 data.RunFor(1);
756 EXPECT_EQ(1u, spdy_stream->stream_id());
758 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
760 // Read and process the GOAWAY frame.
761 data.RunFor(1);
763 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
764 EXPECT_TRUE(session->IsStreamActive(1));
766 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
767 // and EOF.
768 data.RunFor(3);
769 base::MessageLoop::current()->RunUntilIdle();
770 EXPECT_TRUE(session == NULL);
773 // A session observing a network change with active streams should close
774 // when the last active stream is closed.
775 TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
776 session_deps_.host_resolver->set_synchronous_mode(true);
778 MockConnect connect_data(SYNCHRONOUS, OK);
779 MockRead reads[] = {
780 MockRead(ASYNC, 0, 1) // EOF
782 scoped_ptr<SpdyFrame> req1(
783 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
784 MockWrite writes[] = {
785 CreateMockWrite(*req1, 0),
787 DeterministicSocketData data(reads, arraysize(reads),
788 writes, arraysize(writes));
789 data.set_connect_data(connect_data);
790 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
792 CreateDeterministicNetworkSession();
794 base::WeakPtr<SpdySession> session =
795 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
797 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
799 base::WeakPtr<SpdyStream> spdy_stream =
800 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session,
801 GURL(kDefaultURL), MEDIUM, BoundNetLog());
802 test::StreamDelegateDoNothing delegate(spdy_stream);
803 spdy_stream->SetDelegate(&delegate);
805 scoped_ptr<SpdyHeaderBlock> headers(
806 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
808 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
809 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
811 data.RunFor(1);
813 EXPECT_EQ(1u, spdy_stream->stream_id());
815 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
817 spdy_session_pool_->OnIPAddressChanged();
819 // The SpdySessionPool behavior differs based on how the OSs reacts to
820 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
821 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
822 // For OSs where the TCP connections will close upon relevant network
823 // changes, SpdySessionPool doesn't need to force them to close, so in these
824 // cases verify the session has become unavailable but remains open and the
825 // pre-existing stream is still active.
826 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
828 EXPECT_TRUE(session->IsGoingAway());
830 EXPECT_TRUE(session->IsStreamActive(1));
832 // Should close the session.
833 spdy_stream->Close();
834 #endif
835 EXPECT_EQ(NULL, spdy_stream.get());
837 base::MessageLoop::current()->RunUntilIdle();
838 EXPECT_TRUE(session == NULL);
841 TEST_P(SpdySessionTest, ClientPing) {
842 session_deps_.enable_ping = true;
843 session_deps_.host_resolver->set_synchronous_mode(true);
845 MockConnect connect_data(SYNCHRONOUS, OK);
846 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
847 MockRead reads[] = {
848 CreateMockRead(*read_ping, 1),
849 MockRead(ASYNC, 0, 0, 2) // EOF
851 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
852 MockWrite writes[] = {
853 CreateMockWrite(*write_ping, 0),
855 DeterministicSocketData data(
856 reads, arraysize(reads), writes, arraysize(writes));
857 data.set_connect_data(connect_data);
858 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
860 CreateDeterministicNetworkSession();
862 base::WeakPtr<SpdySession> session =
863 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
865 base::WeakPtr<SpdyStream> spdy_stream1 =
866 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
867 session, test_url_, MEDIUM, BoundNetLog());
868 ASSERT_TRUE(spdy_stream1.get() != NULL);
869 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
870 spdy_stream1->SetDelegate(&delegate);
872 base::TimeTicks before_ping_time = base::TimeTicks::Now();
874 session->set_connection_at_risk_of_loss_time(
875 base::TimeDelta::FromSeconds(-1));
876 session->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
878 session->SendPrefacePingIfNoneInFlight();
880 data.RunFor(2);
882 session->CheckPingStatus(before_ping_time);
884 EXPECT_EQ(0, session->pings_in_flight());
885 EXPECT_GE(session->next_ping_id(), 1U);
886 EXPECT_FALSE(session->check_ping_status_pending());
887 EXPECT_GE(session->last_activity_time(), before_ping_time);
889 data.RunFor(1);
891 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
893 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
894 EXPECT_TRUE(session == NULL);
897 TEST_P(SpdySessionTest, ServerPing) {
898 session_deps_.host_resolver->set_synchronous_mode(true);
900 MockConnect connect_data(SYNCHRONOUS, OK);
901 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
902 MockRead reads[] = {
903 CreateMockRead(*read_ping),
904 MockRead(SYNCHRONOUS, 0, 0) // EOF
906 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
907 MockWrite writes[] = {
908 CreateMockWrite(*write_ping),
910 StaticSocketDataProvider data(
911 reads, arraysize(reads), writes, arraysize(writes));
912 data.set_connect_data(connect_data);
913 session_deps_.socket_factory->AddSocketDataProvider(&data);
915 CreateNetworkSession();
917 base::WeakPtr<SpdySession> session =
918 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
920 base::WeakPtr<SpdyStream> spdy_stream1 =
921 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
922 session, test_url_, MEDIUM, BoundNetLog());
923 ASSERT_TRUE(spdy_stream1.get() != NULL);
924 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
925 spdy_stream1->SetDelegate(&delegate);
927 // Flush the read completion task.
928 base::MessageLoop::current()->RunUntilIdle();
930 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
932 EXPECT_TRUE(session == NULL);
933 EXPECT_EQ(NULL, spdy_stream1.get());
936 // Cause a ping to be sent out while producing a write. The write loop
937 // should handle this properly, i.e. another DoWriteLoop task should
938 // not be posted. This is a regression test for
939 // http://crbug.com/261043 .
940 TEST_P(SpdySessionTest, PingAndWriteLoop) {
941 session_deps_.enable_ping = true;
942 session_deps_.time_func = TheNearFuture;
944 MockConnect connect_data(SYNCHRONOUS, OK);
945 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
946 scoped_ptr<SpdyFrame> req(
947 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
948 MockWrite writes[] = {
949 CreateMockWrite(*req, 0),
950 CreateMockWrite(*write_ping, 1),
953 MockRead reads[] = {
954 MockRead(ASYNC, 0, 2) // EOF
957 session_deps_.host_resolver->set_synchronous_mode(true);
959 DeterministicSocketData data(reads, arraysize(reads),
960 writes, arraysize(writes));
961 data.set_connect_data(connect_data);
962 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
964 CreateDeterministicNetworkSession();
966 base::WeakPtr<SpdySession> session =
967 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
969 GURL url(kDefaultURL);
970 base::WeakPtr<SpdyStream> spdy_stream =
971 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
972 session, url, LOWEST, BoundNetLog());
973 test::StreamDelegateDoNothing delegate(spdy_stream);
974 spdy_stream->SetDelegate(&delegate);
976 scoped_ptr<SpdyHeaderBlock> headers(
977 spdy_util_.ConstructGetHeaderBlock(url.spec()));
978 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
980 // Shift time so that a ping will be sent out.
981 g_time_delta = base::TimeDelta::FromSeconds(11);
983 data.RunFor(2);
985 session->CloseSessionOnError(ERR_ABORTED, "Aborting");
988 TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
989 const SpdyStreamId kLastStreamId = 0x7fffffff;
990 session_deps_.host_resolver->set_synchronous_mode(true);
992 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
993 // fixed to allow for two stream ID assignments, and three concurrent
994 // streams. Four streams are started, and two are activated. Verify the
995 // session goes away, and that the created (but not activated) and
996 // stalled streams are aborted. Also verify the activated streams complete,
997 // at which point the session closes.
999 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
1000 NULL, 0, false, kLastStreamId - 2, MEDIUM, true));
1001 scoped_ptr<SpdyFrame> req2(
1002 spdy_util_.ConstructSpdyGet(NULL, 0, false, kLastStreamId, MEDIUM, true));
1004 MockWrite writes[] = {
1005 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
1008 scoped_ptr<SpdyFrame> resp1(
1009 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId - 2));
1010 scoped_ptr<SpdyFrame> resp2(
1011 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId));
1013 scoped_ptr<SpdyFrame> body1(
1014 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
1015 scoped_ptr<SpdyFrame> body2(
1016 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
1018 MockRead reads[] = {
1019 CreateMockRead(*resp1, 2), CreateMockRead(*resp2, 3),
1020 CreateMockRead(*body1, 4), CreateMockRead(*body2, 5),
1021 MockRead(ASYNC, 0, 6) // EOF
1024 DeterministicSocketData data(
1025 reads, arraysize(reads), writes, arraysize(writes));
1027 MockConnect connect_data(SYNCHRONOUS, OK);
1028 data.set_connect_data(connect_data);
1029 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1031 CreateDeterministicNetworkSession();
1032 base::WeakPtr<SpdySession> session =
1033 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1035 // Fix stream_hi_water_mark_ to allow for two stream activations.
1036 session->stream_hi_water_mark_ = kLastStreamId - 2;
1037 // Fix max_concurrent_streams to allow for three stream creations.
1038 session->max_concurrent_streams_ = 3;
1040 // Create three streams synchronously, and begin a fourth (which is stalled).
1041 GURL url(kDefaultURL);
1042 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1043 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1044 test::StreamDelegateDoNothing delegate1(stream1);
1045 stream1->SetDelegate(&delegate1);
1047 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
1048 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1049 test::StreamDelegateDoNothing delegate2(stream2);
1050 stream2->SetDelegate(&delegate2);
1052 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1053 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1054 test::StreamDelegateDoNothing delegate3(stream3);
1055 stream3->SetDelegate(&delegate3);
1057 SpdyStreamRequest request4;
1058 TestCompletionCallback callback4;
1059 EXPECT_EQ(ERR_IO_PENDING,
1060 request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1061 session,
1062 url,
1063 MEDIUM,
1064 BoundNetLog(),
1065 callback4.callback()));
1067 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1068 EXPECT_EQ(0u, session->num_active_streams());
1069 EXPECT_EQ(3u, session->num_created_streams());
1070 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1072 // Activate stream 1. One ID remains available.
1073 stream1->SendRequestHeaders(
1074 scoped_ptr<SpdyHeaderBlock>(
1075 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1076 NO_MORE_DATA_TO_SEND);
1077 data.RunFor(1);
1079 EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1080 EXPECT_EQ(1u, session->num_active_streams());
1081 EXPECT_EQ(2u, session->num_created_streams());
1082 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1084 // Activate stream 2. ID space is exhausted.
1085 stream2->SendRequestHeaders(
1086 scoped_ptr<SpdyHeaderBlock>(
1087 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1088 NO_MORE_DATA_TO_SEND);
1089 data.RunFor(1);
1091 // Active streams remain active.
1092 EXPECT_EQ(kLastStreamId, stream2->stream_id());
1093 EXPECT_EQ(2u, session->num_active_streams());
1095 // Session is going away. Created and stalled streams were aborted.
1096 EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session->availability_state_);
1097 EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose());
1098 EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult());
1099 EXPECT_EQ(0u, session->num_created_streams());
1100 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1102 // Read responses on remaining active streams.
1103 data.RunFor(4);
1104 EXPECT_EQ(OK, delegate1.WaitForClose());
1105 EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1106 EXPECT_EQ(OK, delegate2.WaitForClose());
1107 EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1109 // Session was destroyed.
1110 base::MessageLoop::current()->RunUntilIdle();
1111 EXPECT_FALSE(session.get());
1114 // Verifies that an unstalled pending stream creation racing with a new stream
1115 // creation doesn't violate the maximum stream concurrency. Regression test for
1116 // crbug.com/373858.
1117 TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) {
1118 session_deps_.host_resolver->set_synchronous_mode(true);
1120 MockRead reads[] = {
1121 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1124 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1126 MockConnect connect_data(SYNCHRONOUS, OK);
1127 data.set_connect_data(connect_data);
1128 session_deps_.socket_factory->AddSocketDataProvider(&data);
1130 CreateNetworkSession();
1131 base::WeakPtr<SpdySession> session =
1132 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1134 // Fix max_concurrent_streams to allow for one open stream.
1135 session->max_concurrent_streams_ = 1;
1137 // Create two streams: one synchronously, and one which stalls.
1138 GURL url(kDefaultURL);
1139 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1140 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1142 SpdyStreamRequest request2;
1143 TestCompletionCallback callback2;
1144 EXPECT_EQ(ERR_IO_PENDING,
1145 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1146 session,
1147 url,
1148 MEDIUM,
1149 BoundNetLog(),
1150 callback2.callback()));
1152 EXPECT_EQ(1u, session->num_created_streams());
1153 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1155 // Cancel the first stream. A callback to unstall the second stream was
1156 // posted. Don't run it yet.
1157 stream1->Cancel();
1159 EXPECT_EQ(0u, session->num_created_streams());
1160 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1162 // Create a third stream prior to the second stream's callback.
1163 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1164 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1166 EXPECT_EQ(1u, session->num_created_streams());
1167 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1169 // NOW run the message loop. The unstalled stream will re-stall itself.
1170 base::MessageLoop::current()->RunUntilIdle();
1171 EXPECT_EQ(1u, session->num_created_streams());
1172 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1174 // Cancel the third stream and run the message loop. Verify that the second
1175 // stream creation now completes.
1176 stream3->Cancel();
1177 base::MessageLoop::current()->RunUntilIdle();
1179 EXPECT_EQ(1u, session->num_created_streams());
1180 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1181 EXPECT_EQ(OK, callback2.WaitForResult());
1184 TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
1185 session_deps_.host_resolver->set_synchronous_mode(true);
1186 session_deps_.time_func = TheNearFuture;
1188 scoped_ptr<SpdyFrame> req(
1189 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1190 scoped_ptr<SpdyFrame> rst(
1191 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
1193 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
1194 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
1195 scoped_ptr<SpdyFrame> push_a_body(
1196 spdy_util_.ConstructSpdyBodyFrame(2, false));
1197 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1198 // iterators inside. See http://crbug.com/443490
1199 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
1200 NULL, 0, 4, 1, "http://www.google.com/0.dat"));
1201 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)};
1202 MockRead reads[] = {
1203 CreateMockRead(*push_a, 1), CreateMockRead(*push_a_body, 2),
1204 CreateMockRead(*push_b, 3), MockRead(ASYNC, 0, 5), // EOF
1206 DeterministicSocketData data(
1207 reads, arraysize(reads), writes, arraysize(writes));
1209 MockConnect connect_data(SYNCHRONOUS, OK);
1210 data.set_connect_data(connect_data);
1211 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1213 CreateDeterministicNetworkSession();
1214 base::WeakPtr<SpdySession> session =
1215 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1217 // Process the principal request, and the first push stream request & body.
1218 GURL url(kDefaultURL);
1219 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1220 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1221 test::StreamDelegateDoNothing delegate(spdy_stream);
1222 spdy_stream->SetDelegate(&delegate);
1224 scoped_ptr<SpdyHeaderBlock> headers(
1225 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1226 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1228 data.RunFor(3);
1230 // Verify that there is one unclaimed push stream.
1231 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1232 SpdySession::PushedStreamMap::iterator iter =
1233 session->unclaimed_pushed_streams_.find(
1234 GURL("http://www.google.com/a.dat"));
1235 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1237 if (session->flow_control_state_ ==
1238 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1239 // Unclaimed push body consumed bytes from the session window.
1240 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()) - kUploadDataSize,
1241 session->session_recv_window_size_);
1242 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
1245 // Shift time to expire the push stream. Read the second SYN_STREAM,
1246 // and verify a RST_STREAM was written.
1247 g_time_delta = base::TimeDelta::FromSeconds(301);
1248 data.RunFor(2);
1250 // Verify that the second pushed stream evicted the first pushed stream.
1251 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1252 iter = session->unclaimed_pushed_streams_.find(
1253 GURL("http://www.google.com/0.dat"));
1254 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1256 if (session->flow_control_state_ ==
1257 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1258 // Verify that the session window reclaimed the evicted stream body.
1259 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
1260 session->session_recv_window_size_);
1261 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
1264 // Read and process EOF.
1265 data.RunFor(1);
1266 base::MessageLoop::current()->RunUntilIdle();
1267 EXPECT_TRUE(session == NULL);
1270 TEST_P(SpdySessionTest, FailedPing) {
1271 session_deps_.host_resolver->set_synchronous_mode(true);
1273 MockConnect connect_data(SYNCHRONOUS, OK);
1274 MockRead reads[] = {
1275 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1277 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
1278 scoped_ptr<SpdyFrame> goaway(
1279 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping."));
1280 MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)};
1281 StaticSocketDataProvider data(
1282 reads, arraysize(reads), writes, arraysize(writes));
1283 data.set_connect_data(connect_data);
1284 session_deps_.socket_factory->AddSocketDataProvider(&data);
1286 CreateNetworkSession();
1288 base::WeakPtr<SpdySession> session =
1289 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1291 base::WeakPtr<SpdyStream> spdy_stream1 =
1292 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1293 session, test_url_, MEDIUM, BoundNetLog());
1294 ASSERT_TRUE(spdy_stream1.get() != NULL);
1295 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
1296 spdy_stream1->SetDelegate(&delegate);
1298 session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1299 session->set_hung_interval(base::TimeDelta::FromSeconds(0));
1301 // Send a PING frame.
1302 session->WritePingFrame(1, false);
1303 EXPECT_LT(0, session->pings_in_flight());
1304 EXPECT_GE(session->next_ping_id(), 1U);
1305 EXPECT_TRUE(session->check_ping_status_pending());
1307 // Assert session is not closed.
1308 EXPECT_TRUE(session->IsAvailable());
1309 EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams());
1310 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1312 // We set last time we have received any data in 1 sec less than now.
1313 // CheckPingStatus will trigger timeout because hung interval is zero.
1314 base::TimeTicks now = base::TimeTicks::Now();
1315 session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
1316 session->CheckPingStatus(now);
1317 base::MessageLoop::current()->RunUntilIdle();
1319 EXPECT_TRUE(session == NULL);
1320 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1321 EXPECT_EQ(NULL, spdy_stream1.get());
1324 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1325 // settings frame increasing the max concurrent streams by 1. Make
1326 // sure nothing blows up. This is a regression test for
1327 // http://crbug.com/57331 .
1328 TEST_P(SpdySessionTest, OnSettings) {
1329 session_deps_.host_resolver->set_synchronous_mode(true);
1331 const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1333 SettingsMap new_settings;
1334 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1335 new_settings[kSpdySettingsIds] =
1336 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1337 scoped_ptr<SpdyFrame> settings_frame(
1338 spdy_util_.ConstructSpdySettings(new_settings));
1339 MockRead reads[] = {
1340 CreateMockRead(*settings_frame, 0),
1341 MockRead(ASYNC, 0, 1),
1344 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1345 MockWrite writes[] = {
1346 CreateMockWrite(*settings_ack, 2),
1349 DeterministicSocketData data(reads, arraysize(reads),
1350 writes, arraysize(writes));
1351 MockConnect connect_data(SYNCHRONOUS, OK);
1352 data.set_connect_data(connect_data);
1353 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1355 CreateDeterministicNetworkSession();
1357 base::WeakPtr<SpdySession> session =
1358 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1360 // Create the maximum number of concurrent streams.
1361 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1362 base::WeakPtr<SpdyStream> spdy_stream =
1363 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1364 session, test_url_, MEDIUM, BoundNetLog());
1365 ASSERT_TRUE(spdy_stream != NULL);
1368 StreamReleaserCallback stream_releaser;
1369 SpdyStreamRequest request;
1370 ASSERT_EQ(ERR_IO_PENDING,
1371 request.StartRequest(
1372 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1373 BoundNetLog(),
1374 stream_releaser.MakeCallback(&request)));
1376 data.RunFor(1);
1378 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1380 data.RunFor(1);
1381 if (spdy_util_.spdy_version() >= SPDY4) {
1382 // Allow the SETTINGS+ACK to write, so the session finishes draining.
1383 data.RunFor(1);
1385 base::MessageLoop::current()->RunUntilIdle();
1386 EXPECT_TRUE(session == NULL);
1389 // Start with a persisted value for max concurrent streams. Receive a
1390 // settings frame increasing the max concurrent streams by 1 and which
1391 // also clears the persisted data. Verify that persisted data is
1392 // correct.
1393 TEST_P(SpdySessionTest, ClearSettings) {
1394 if (spdy_util_.spdy_version() >= SPDY4) {
1395 // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1396 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4.
1397 return;
1399 session_deps_.host_resolver->set_synchronous_mode(true);
1401 SettingsMap new_settings;
1402 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1403 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1404 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1405 scoped_ptr<SpdyFrame> settings_frame(
1406 spdy_util_.ConstructSpdySettings(new_settings));
1407 uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1408 test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1409 MockRead reads[] = {
1410 CreateMockRead(*settings_frame, 0),
1411 MockRead(ASYNC, 0, 1),
1414 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
1415 MockConnect connect_data(SYNCHRONOUS, OK);
1416 data.set_connect_data(connect_data);
1417 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1419 CreateDeterministicNetworkSession();
1421 // Initialize the SpdySetting with the default.
1422 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1423 test_host_port_pair_,
1424 SETTINGS_MAX_CONCURRENT_STREAMS,
1425 SETTINGS_FLAG_PLEASE_PERSIST,
1426 kInitialMaxConcurrentStreams);
1428 EXPECT_FALSE(
1429 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1430 test_host_port_pair_).empty());
1432 base::WeakPtr<SpdySession> session =
1433 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1435 // Create the maximum number of concurrent streams.
1436 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1437 base::WeakPtr<SpdyStream> spdy_stream =
1438 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1439 session, test_url_, MEDIUM, BoundNetLog());
1440 ASSERT_TRUE(spdy_stream != NULL);
1443 StreamReleaserCallback stream_releaser;
1445 SpdyStreamRequest request;
1446 ASSERT_EQ(ERR_IO_PENDING,
1447 request.StartRequest(
1448 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1449 BoundNetLog(),
1450 stream_releaser.MakeCallback(&request)));
1452 data.RunFor(1);
1454 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1456 // Make sure that persisted data is cleared.
1457 EXPECT_TRUE(
1458 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1459 test_host_port_pair_).empty());
1461 // Make sure session's max_concurrent_streams is correct.
1462 EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1463 session->max_concurrent_streams());
1465 data.RunFor(1);
1466 EXPECT_TRUE(session == NULL);
1469 // Start with max concurrent streams set to 1. Request two streams.
1470 // When the first completes, have the callback close its stream, which
1471 // should trigger the second stream creation. Then cancel that one
1472 // immediately. Don't crash. This is a regression test for
1473 // http://crbug.com/63532 .
1474 TEST_P(SpdySessionTest, CancelPendingCreateStream) {
1475 session_deps_.host_resolver->set_synchronous_mode(true);
1477 MockRead reads[] = {
1478 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1481 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1482 MockConnect connect_data(SYNCHRONOUS, OK);
1484 data.set_connect_data(connect_data);
1485 session_deps_.socket_factory->AddSocketDataProvider(&data);
1487 CreateNetworkSession();
1489 // Initialize the SpdySetting with 1 max concurrent streams.
1490 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1491 test_host_port_pair_,
1492 SETTINGS_MAX_CONCURRENT_STREAMS,
1493 SETTINGS_FLAG_PLEASE_PERSIST,
1496 base::WeakPtr<SpdySession> session =
1497 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1499 // Leave room for only one more stream to be created.
1500 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1501 base::WeakPtr<SpdyStream> spdy_stream =
1502 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1503 session, test_url_, MEDIUM, BoundNetLog());
1504 ASSERT_TRUE(spdy_stream != NULL);
1507 // Create 2 more streams. First will succeed. Second will be pending.
1508 base::WeakPtr<SpdyStream> spdy_stream1 =
1509 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1510 session, test_url_, MEDIUM, BoundNetLog());
1511 ASSERT_TRUE(spdy_stream1.get() != NULL);
1513 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1514 // a valgrind error if the callback is invoked when it's not supposed to be.
1515 scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
1517 SpdyStreamRequest request;
1518 ASSERT_EQ(ERR_IO_PENDING,
1519 request.StartRequest(
1520 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1521 BoundNetLog(),
1522 callback->callback()));
1524 // Release the first one, this will allow the second to be created.
1525 spdy_stream1->Cancel();
1526 EXPECT_EQ(NULL, spdy_stream1.get());
1528 request.CancelRequest();
1529 callback.reset();
1531 // Should not crash when running the pending callback.
1532 base::MessageLoop::current()->RunUntilIdle();
1535 TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
1536 session_deps_.host_resolver->set_synchronous_mode(true);
1538 MockRead reads[] = {
1539 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1542 SettingsMap settings;
1543 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
1544 const SpdySettingsIds kSpdySettingsIds2 = SETTINGS_INITIAL_WINDOW_SIZE;
1545 const uint32 kInitialRecvWindowSize = 10 * 1024 * 1024;
1546 settings[kSpdySettingsIds1] =
1547 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
1548 if (spdy_util_.spdy_version() >= SPDY3) {
1549 settings[kSpdySettingsIds2] =
1550 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialRecvWindowSize);
1552 MockConnect connect_data(SYNCHRONOUS, OK);
1553 scoped_ptr<SpdyFrame> settings_frame(
1554 spdy_util_.ConstructSpdySettings(settings));
1555 scoped_ptr<SpdyFrame> initial_window_update(
1556 spdy_util_.ConstructSpdyWindowUpdate(
1557 kSessionFlowControlStreamId,
1558 kDefaultInitialRecvWindowSize -
1559 SpdySession::GetInitialWindowSize(GetParam())));
1560 std::vector<MockWrite> writes;
1561 if ((GetParam() >= kProtoSPDY4MinimumVersion) &&
1562 (GetParam() <= kProtoSPDY4MaximumVersion)) {
1563 writes.push_back(
1564 MockWrite(ASYNC,
1565 kHttp2ConnectionHeaderPrefix,
1566 kHttp2ConnectionHeaderPrefixSize));
1568 writes.push_back(CreateMockWrite(*settings_frame));
1569 if (GetParam() >= kProtoSPDY31) {
1570 writes.push_back(CreateMockWrite(*initial_window_update));
1573 SettingsMap server_settings;
1574 const uint32 initial_max_concurrent_streams = 1;
1575 server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1576 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1577 initial_max_concurrent_streams);
1578 scoped_ptr<SpdyFrame> server_settings_frame(
1579 spdy_util_.ConstructSpdySettings(server_settings));
1580 if (GetParam() <= kProtoSPDY31) {
1581 writes.push_back(CreateMockWrite(*server_settings_frame));
1584 session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize;
1586 StaticSocketDataProvider data(reads, arraysize(reads),
1587 vector_as_array(&writes), writes.size());
1588 data.set_connect_data(connect_data);
1589 session_deps_.socket_factory->AddSocketDataProvider(&data);
1591 CreateNetworkSession();
1593 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1594 test_host_port_pair_,
1595 SETTINGS_MAX_CONCURRENT_STREAMS,
1596 SETTINGS_FLAG_PLEASE_PERSIST,
1597 initial_max_concurrent_streams);
1599 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1600 pool_peer.SetEnableSendingInitialData(true);
1602 base::WeakPtr<SpdySession> session =
1603 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1605 base::MessageLoop::current()->RunUntilIdle();
1606 EXPECT_TRUE(data.at_write_eof());
1609 TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
1610 CreateNetworkSession();
1612 base::WeakPtr<HttpServerProperties> test_http_server_properties =
1613 spdy_session_pool_->http_server_properties();
1614 SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
1615 test_http_server_properties->SetSpdySetting(
1616 test_host_port_pair_,
1617 SETTINGS_MAX_CONCURRENT_STREAMS,
1618 SETTINGS_FLAG_PLEASE_PERSIST,
1620 EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
1621 test_host_port_pair_).size());
1622 spdy_session_pool_->OnIPAddressChanged();
1623 EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
1624 test_host_port_pair_).size());
1627 TEST_P(SpdySessionTest, Initialize) {
1628 CapturingBoundNetLog log;
1629 session_deps_.net_log = log.bound().net_log();
1630 session_deps_.host_resolver->set_synchronous_mode(true);
1632 MockConnect connect_data(SYNCHRONOUS, OK);
1633 MockRead reads[] = {
1634 MockRead(ASYNC, 0, 0) // EOF
1637 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1638 data.set_connect_data(connect_data);
1639 session_deps_.socket_factory->AddSocketDataProvider(&data);
1641 CreateNetworkSession();
1643 base::WeakPtr<SpdySession> session =
1644 CreateInsecureSpdySession(http_session_, key_, log.bound());
1645 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1647 // Flush the read completion task.
1648 base::MessageLoop::current()->RunUntilIdle();
1650 net::CapturingNetLog::CapturedEntryList entries;
1651 log.GetEntries(&entries);
1652 EXPECT_LT(0u, entries.size());
1654 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1655 int pos = net::ExpectLogContainsSomewhere(
1656 entries, 0, net::NetLog::TYPE_HTTP2_SESSION_INITIALIZED,
1657 net::NetLog::PHASE_NONE);
1658 EXPECT_LT(0, pos);
1660 CapturingNetLog::CapturedEntry entry = entries[pos];
1661 NetLog::Source socket_source;
1662 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1663 &socket_source));
1664 EXPECT_TRUE(socket_source.IsValid());
1665 EXPECT_NE(log.bound().source().id, socket_source.id);
1668 TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
1669 session_deps_.host_resolver->set_synchronous_mode(true);
1671 MockConnect connect_data(SYNCHRONOUS, OK);
1672 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
1673 MockRead reads[] = {
1674 CreateMockRead(*goaway),
1675 MockRead(SYNCHRONOUS, 0, 0) // EOF
1678 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1679 data.set_connect_data(connect_data);
1680 session_deps_.socket_factory->AddSocketDataProvider(&data);
1682 CreateNetworkSession();
1684 CapturingBoundNetLog log;
1685 base::WeakPtr<SpdySession> session =
1686 CreateInsecureSpdySession(http_session_, key_, log.bound());
1687 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1689 // Flush the read completion task.
1690 base::MessageLoop::current()->RunUntilIdle();
1692 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1693 EXPECT_TRUE(session == NULL);
1695 // Check that the NetLog was filled reasonably.
1696 net::CapturingNetLog::CapturedEntryList entries;
1697 log.GetEntries(&entries);
1698 EXPECT_LT(0u, entries.size());
1700 // Check that we logged SPDY_SESSION_CLOSE correctly.
1701 int pos = net::ExpectLogContainsSomewhere(
1702 entries, 0, net::NetLog::TYPE_HTTP2_SESSION_CLOSE,
1703 net::NetLog::PHASE_NONE);
1705 if (pos < static_cast<int>(entries.size())) {
1706 CapturingNetLog::CapturedEntry entry = entries[pos];
1707 int error_code = 0;
1708 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1709 EXPECT_EQ(OK, error_code);
1710 } else {
1711 ADD_FAILURE();
1715 TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1716 session_deps_.host_resolver->set_synchronous_mode(true);
1718 MockConnect connect_data(SYNCHRONOUS, OK);
1719 MockRead reads[] = {
1720 MockRead(SYNCHRONOUS, 0, 0) // EOF
1723 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1724 data.set_connect_data(connect_data);
1725 session_deps_.socket_factory->AddSocketDataProvider(&data);
1727 CreateNetworkSession();
1729 CapturingBoundNetLog log;
1730 base::WeakPtr<SpdySession> session =
1731 CreateInsecureSpdySession(http_session_, key_, log.bound());
1732 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1734 // Flush the read completion task.
1735 base::MessageLoop::current()->RunUntilIdle();
1737 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1738 EXPECT_TRUE(session == NULL);
1740 // Check that the NetLog was filled reasonably.
1741 net::CapturingNetLog::CapturedEntryList entries;
1742 log.GetEntries(&entries);
1743 EXPECT_LT(0u, entries.size());
1745 // Check that we logged SPDY_SESSION_CLOSE correctly.
1746 int pos = net::ExpectLogContainsSomewhere(
1747 entries, 0, net::NetLog::TYPE_HTTP2_SESSION_CLOSE,
1748 net::NetLog::PHASE_NONE);
1750 if (pos < static_cast<int>(entries.size())) {
1751 CapturingNetLog::CapturedEntry entry = entries[pos];
1752 int error_code = 0;
1753 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1754 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1755 } else {
1756 ADD_FAILURE();
1760 TEST_P(SpdySessionTest, SynCompressionHistograms) {
1761 session_deps_.enable_compression = true;
1763 scoped_ptr<SpdyFrame> req(
1764 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, MEDIUM, true));
1765 MockWrite writes[] = {
1766 CreateMockWrite(*req, 0),
1768 MockRead reads[] = {
1769 MockRead(ASYNC, 0, 1) // EOF
1771 DeterministicSocketData data(reads, arraysize(reads),
1772 writes, arraysize(writes));
1773 MockConnect connect_data(SYNCHRONOUS, OK);
1774 data.set_connect_data(connect_data);
1775 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1777 CreateDeterministicNetworkSession();
1778 base::WeakPtr<SpdySession> session =
1779 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1781 GURL url(kDefaultURL);
1782 base::WeakPtr<SpdyStream> spdy_stream =
1783 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1784 session, url, MEDIUM, BoundNetLog());
1785 test::StreamDelegateDoNothing delegate(spdy_stream);
1786 spdy_stream->SetDelegate(&delegate);
1788 scoped_ptr<SpdyHeaderBlock> headers(
1789 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1790 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1791 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1793 // Write request headers & capture resulting histogram update.
1794 base::HistogramTester histogram_tester;
1796 data.RunFor(1);
1797 // Regression test of compression performance under the request fixture.
1798 switch (spdy_util_.spdy_version()) {
1799 case SPDY3:
1800 histogram_tester.ExpectBucketCount(
1801 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1802 break;
1803 case SPDY4:
1804 histogram_tester.ExpectBucketCount(
1805 "Net.SpdySynStreamCompressionPercentage", 82, 1);
1806 break;
1807 default:
1808 NOTREACHED();
1811 // Read and process EOF.
1812 data.RunFor(1);
1813 base::MessageLoop::current()->RunUntilIdle();
1814 EXPECT_TRUE(session == NULL);
1817 // Queue up a low-priority SYN_STREAM followed by a high-priority
1818 // one. The high priority one should still send first and receive
1819 // first.
1820 TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1821 // Construct the request.
1822 MockConnect connect_data(SYNCHRONOUS, OK);
1823 scoped_ptr<SpdyFrame> req_highest(
1824 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true));
1825 scoped_ptr<SpdyFrame> req_lowest(
1826 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1827 MockWrite writes[] = {
1828 CreateMockWrite(*req_highest, 0),
1829 CreateMockWrite(*req_lowest, 1),
1832 scoped_ptr<SpdyFrame> resp_highest(
1833 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1834 scoped_ptr<SpdyFrame> body_highest(
1835 spdy_util_.ConstructSpdyBodyFrame(1, true));
1836 scoped_ptr<SpdyFrame> resp_lowest(
1837 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1838 scoped_ptr<SpdyFrame> body_lowest(
1839 spdy_util_.ConstructSpdyBodyFrame(3, true));
1840 MockRead reads[] = {
1841 CreateMockRead(*resp_highest, 2),
1842 CreateMockRead(*body_highest, 3),
1843 CreateMockRead(*resp_lowest, 4),
1844 CreateMockRead(*body_lowest, 5),
1845 MockRead(ASYNC, 0, 6) // EOF
1848 session_deps_.host_resolver->set_synchronous_mode(true);
1850 DeterministicSocketData data(reads, arraysize(reads),
1851 writes, arraysize(writes));
1852 data.set_connect_data(connect_data);
1853 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1855 CreateDeterministicNetworkSession();
1857 base::WeakPtr<SpdySession> session =
1858 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1860 GURL url(kDefaultURL);
1862 base::WeakPtr<SpdyStream> spdy_stream_lowest =
1863 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1864 session, url, LOWEST, BoundNetLog());
1865 ASSERT_TRUE(spdy_stream_lowest);
1866 EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1867 test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1868 spdy_stream_lowest->SetDelegate(&delegate_lowest);
1870 base::WeakPtr<SpdyStream> spdy_stream_highest =
1871 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1872 session, url, HIGHEST, BoundNetLog());
1873 ASSERT_TRUE(spdy_stream_highest);
1874 EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1875 test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1876 spdy_stream_highest->SetDelegate(&delegate_highest);
1878 // Queue the lower priority one first.
1880 scoped_ptr<SpdyHeaderBlock> headers_lowest(
1881 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1882 spdy_stream_lowest->SendRequestHeaders(
1883 headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1884 EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1886 scoped_ptr<SpdyHeaderBlock> headers_highest(
1887 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1888 spdy_stream_highest->SendRequestHeaders(
1889 headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1890 EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1892 data.RunFor(7);
1894 EXPECT_FALSE(spdy_stream_lowest);
1895 EXPECT_FALSE(spdy_stream_highest);
1896 EXPECT_EQ(3u, delegate_lowest.stream_id());
1897 EXPECT_EQ(1u, delegate_highest.stream_id());
1900 TEST_P(SpdySessionTest, CancelStream) {
1901 MockConnect connect_data(SYNCHRONOUS, OK);
1902 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1903 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1904 scoped_ptr<SpdyFrame> req2(
1905 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1906 MockWrite writes[] = {
1907 CreateMockWrite(*req2, 0),
1910 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1911 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1912 MockRead reads[] = {
1913 CreateMockRead(*resp2, 1),
1914 CreateMockRead(*body2, 2),
1915 MockRead(ASYNC, 0, 3) // EOF
1918 session_deps_.host_resolver->set_synchronous_mode(true);
1920 DeterministicSocketData data(reads, arraysize(reads),
1921 writes, arraysize(writes));
1922 data.set_connect_data(connect_data);
1923 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1925 CreateDeterministicNetworkSession();
1927 base::WeakPtr<SpdySession> session =
1928 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1930 GURL url1(kDefaultURL);
1931 base::WeakPtr<SpdyStream> spdy_stream1 =
1932 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1933 session, url1, HIGHEST, BoundNetLog());
1934 ASSERT_TRUE(spdy_stream1.get() != NULL);
1935 EXPECT_EQ(0u, spdy_stream1->stream_id());
1936 test::StreamDelegateDoNothing delegate1(spdy_stream1);
1937 spdy_stream1->SetDelegate(&delegate1);
1939 GURL url2(kDefaultURL);
1940 base::WeakPtr<SpdyStream> spdy_stream2 =
1941 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1942 session, url2, LOWEST, BoundNetLog());
1943 ASSERT_TRUE(spdy_stream2.get() != NULL);
1944 EXPECT_EQ(0u, spdy_stream2->stream_id());
1945 test::StreamDelegateDoNothing delegate2(spdy_stream2);
1946 spdy_stream2->SetDelegate(&delegate2);
1948 scoped_ptr<SpdyHeaderBlock> headers(
1949 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1950 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1951 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1953 scoped_ptr<SpdyHeaderBlock> headers2(
1954 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1955 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1956 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1958 EXPECT_EQ(0u, spdy_stream1->stream_id());
1960 spdy_stream1->Cancel();
1961 EXPECT_EQ(NULL, spdy_stream1.get());
1963 EXPECT_EQ(0u, delegate1.stream_id());
1965 data.RunFor(1);
1967 EXPECT_EQ(0u, delegate1.stream_id());
1968 EXPECT_EQ(1u, delegate2.stream_id());
1970 spdy_stream2->Cancel();
1971 EXPECT_EQ(NULL, spdy_stream2.get());
1974 // Create two streams that are set to re-close themselves on close,
1975 // and then close the session. Nothing should blow up. Also a
1976 // regression test for http://crbug.com/139518 .
1977 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1978 session_deps_.host_resolver->set_synchronous_mode(true);
1980 MockConnect connect_data(SYNCHRONOUS, OK);
1982 // No actual data will be sent.
1983 MockWrite writes[] = {
1984 MockWrite(ASYNC, 0, 1) // EOF
1987 MockRead reads[] = {
1988 MockRead(ASYNC, 0, 0) // EOF
1990 DeterministicSocketData data(reads, arraysize(reads),
1991 writes, arraysize(writes));
1992 data.set_connect_data(connect_data);
1993 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1995 CreateDeterministicNetworkSession();
1997 base::WeakPtr<SpdySession> session =
1998 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2000 GURL url1(kDefaultURL);
2001 base::WeakPtr<SpdyStream> spdy_stream1 =
2002 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2003 session, url1, HIGHEST, BoundNetLog());
2004 ASSERT_TRUE(spdy_stream1.get() != NULL);
2005 EXPECT_EQ(0u, spdy_stream1->stream_id());
2007 GURL url2(kDefaultURL);
2008 base::WeakPtr<SpdyStream> spdy_stream2 =
2009 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2010 session, url2, LOWEST, BoundNetLog());
2011 ASSERT_TRUE(spdy_stream2.get() != NULL);
2012 EXPECT_EQ(0u, spdy_stream2->stream_id());
2014 test::ClosingDelegate delegate1(spdy_stream1);
2015 spdy_stream1->SetDelegate(&delegate1);
2017 test::ClosingDelegate delegate2(spdy_stream2);
2018 spdy_stream2->SetDelegate(&delegate2);
2020 scoped_ptr<SpdyHeaderBlock> headers(
2021 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2022 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2023 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2025 scoped_ptr<SpdyHeaderBlock> headers2(
2026 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2027 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2028 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2030 // Ensure that the streams have not yet been activated and assigned an id.
2031 EXPECT_EQ(0u, spdy_stream1->stream_id());
2032 EXPECT_EQ(0u, spdy_stream2->stream_id());
2034 // Ensure we don't crash while closing the session.
2035 session->CloseSessionOnError(ERR_ABORTED, std::string());
2037 EXPECT_EQ(NULL, spdy_stream1.get());
2038 EXPECT_EQ(NULL, spdy_stream2.get());
2040 EXPECT_TRUE(delegate1.StreamIsClosed());
2041 EXPECT_TRUE(delegate2.StreamIsClosed());
2043 base::MessageLoop::current()->RunUntilIdle();
2044 EXPECT_TRUE(session == NULL);
2047 // Create two streams that are set to close each other on close, and
2048 // then close the session. Nothing should blow up.
2049 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
2050 session_deps_.host_resolver->set_synchronous_mode(true);
2052 MockConnect connect_data(SYNCHRONOUS, OK);
2054 // No actual data will be sent.
2055 MockWrite writes[] = {
2056 MockWrite(ASYNC, 0, 1) // EOF
2059 MockRead reads[] = {
2060 MockRead(ASYNC, 0, 0) // EOF
2062 DeterministicSocketData data(reads, arraysize(reads),
2063 writes, arraysize(writes));
2064 data.set_connect_data(connect_data);
2065 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2067 CreateDeterministicNetworkSession();
2069 base::WeakPtr<SpdySession> session =
2070 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2072 GURL url1(kDefaultURL);
2073 base::WeakPtr<SpdyStream> spdy_stream1 =
2074 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2075 session, url1, HIGHEST, BoundNetLog());
2076 ASSERT_TRUE(spdy_stream1.get() != NULL);
2077 EXPECT_EQ(0u, spdy_stream1->stream_id());
2079 GURL url2(kDefaultURL);
2080 base::WeakPtr<SpdyStream> spdy_stream2 =
2081 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2082 session, url2, LOWEST, BoundNetLog());
2083 ASSERT_TRUE(spdy_stream2.get() != NULL);
2084 EXPECT_EQ(0u, spdy_stream2->stream_id());
2086 // Make |spdy_stream1| close |spdy_stream2|.
2087 test::ClosingDelegate delegate1(spdy_stream2);
2088 spdy_stream1->SetDelegate(&delegate1);
2090 // Make |spdy_stream2| close |spdy_stream1|.
2091 test::ClosingDelegate delegate2(spdy_stream1);
2092 spdy_stream2->SetDelegate(&delegate2);
2094 scoped_ptr<SpdyHeaderBlock> headers(
2095 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2096 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2097 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2099 scoped_ptr<SpdyHeaderBlock> headers2(
2100 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2101 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2102 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2104 // Ensure that the streams have not yet been activated and assigned an id.
2105 EXPECT_EQ(0u, spdy_stream1->stream_id());
2106 EXPECT_EQ(0u, spdy_stream2->stream_id());
2108 // Ensure we don't crash while closing the session.
2109 session->CloseSessionOnError(ERR_ABORTED, std::string());
2111 EXPECT_EQ(NULL, spdy_stream1.get());
2112 EXPECT_EQ(NULL, spdy_stream2.get());
2114 EXPECT_TRUE(delegate1.StreamIsClosed());
2115 EXPECT_TRUE(delegate2.StreamIsClosed());
2117 base::MessageLoop::current()->RunUntilIdle();
2118 EXPECT_TRUE(session == NULL);
2121 // Create two streams that are set to re-close themselves on close,
2122 // activate them, and then close the session. Nothing should blow up.
2123 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
2124 session_deps_.host_resolver->set_synchronous_mode(true);
2126 MockConnect connect_data(SYNCHRONOUS, OK);
2128 scoped_ptr<SpdyFrame> req1(
2129 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2130 scoped_ptr<SpdyFrame> req2(
2131 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2132 MockWrite writes[] = {
2133 CreateMockWrite(*req1, 0),
2134 CreateMockWrite(*req2, 1),
2137 MockRead reads[] = {
2138 MockRead(ASYNC, 0, 2) // EOF
2141 DeterministicSocketData data(reads, arraysize(reads),
2142 writes, arraysize(writes));
2143 data.set_connect_data(connect_data);
2144 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2146 CreateDeterministicNetworkSession();
2148 base::WeakPtr<SpdySession> session =
2149 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2151 GURL url1(kDefaultURL);
2152 base::WeakPtr<SpdyStream> spdy_stream1 =
2153 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2154 session, url1, MEDIUM, BoundNetLog());
2155 ASSERT_TRUE(spdy_stream1.get() != NULL);
2156 EXPECT_EQ(0u, spdy_stream1->stream_id());
2158 GURL url2(kDefaultURL);
2159 base::WeakPtr<SpdyStream> spdy_stream2 =
2160 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2161 session, url2, MEDIUM, BoundNetLog());
2162 ASSERT_TRUE(spdy_stream2.get() != NULL);
2163 EXPECT_EQ(0u, spdy_stream2->stream_id());
2165 test::ClosingDelegate delegate1(spdy_stream1);
2166 spdy_stream1->SetDelegate(&delegate1);
2168 test::ClosingDelegate delegate2(spdy_stream2);
2169 spdy_stream2->SetDelegate(&delegate2);
2171 scoped_ptr<SpdyHeaderBlock> headers(
2172 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2173 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2174 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2176 scoped_ptr<SpdyHeaderBlock> headers2(
2177 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2178 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2179 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2181 // Ensure that the streams have not yet been activated and assigned an id.
2182 EXPECT_EQ(0u, spdy_stream1->stream_id());
2183 EXPECT_EQ(0u, spdy_stream2->stream_id());
2185 data.RunFor(2);
2187 EXPECT_EQ(1u, spdy_stream1->stream_id());
2188 EXPECT_EQ(3u, spdy_stream2->stream_id());
2190 // Ensure we don't crash while closing the session.
2191 session->CloseSessionOnError(ERR_ABORTED, std::string());
2193 EXPECT_EQ(NULL, spdy_stream1.get());
2194 EXPECT_EQ(NULL, spdy_stream2.get());
2196 EXPECT_TRUE(delegate1.StreamIsClosed());
2197 EXPECT_TRUE(delegate2.StreamIsClosed());
2199 base::MessageLoop::current()->RunUntilIdle();
2200 EXPECT_TRUE(session == NULL);
2203 // Create two streams that are set to close each other on close,
2204 // activate them, and then close the session. Nothing should blow up.
2205 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2206 session_deps_.host_resolver->set_synchronous_mode(true);
2208 MockConnect connect_data(SYNCHRONOUS, OK);
2210 scoped_ptr<SpdyFrame> req1(
2211 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2212 scoped_ptr<SpdyFrame> req2(
2213 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2214 MockWrite writes[] = {
2215 CreateMockWrite(*req1, 0),
2216 CreateMockWrite(*req2, 1),
2219 MockRead reads[] = {
2220 MockRead(ASYNC, 0, 2) // EOF
2223 DeterministicSocketData data(reads, arraysize(reads),
2224 writes, arraysize(writes));
2225 data.set_connect_data(connect_data);
2226 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2228 CreateDeterministicNetworkSession();
2230 base::WeakPtr<SpdySession> session =
2231 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2233 GURL url1(kDefaultURL);
2234 base::WeakPtr<SpdyStream> spdy_stream1 =
2235 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2236 session, url1, MEDIUM, BoundNetLog());
2237 ASSERT_TRUE(spdy_stream1.get() != NULL);
2238 EXPECT_EQ(0u, spdy_stream1->stream_id());
2240 GURL url2(kDefaultURL);
2241 base::WeakPtr<SpdyStream> spdy_stream2 =
2242 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2243 session, url2, MEDIUM, BoundNetLog());
2244 ASSERT_TRUE(spdy_stream2.get() != NULL);
2245 EXPECT_EQ(0u, spdy_stream2->stream_id());
2247 // Make |spdy_stream1| close |spdy_stream2|.
2248 test::ClosingDelegate delegate1(spdy_stream2);
2249 spdy_stream1->SetDelegate(&delegate1);
2251 // Make |spdy_stream2| close |spdy_stream1|.
2252 test::ClosingDelegate delegate2(spdy_stream1);
2253 spdy_stream2->SetDelegate(&delegate2);
2255 scoped_ptr<SpdyHeaderBlock> headers(
2256 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2257 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2258 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2260 scoped_ptr<SpdyHeaderBlock> headers2(
2261 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2262 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2263 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2265 // Ensure that the streams have not yet been activated and assigned an id.
2266 EXPECT_EQ(0u, spdy_stream1->stream_id());
2267 EXPECT_EQ(0u, spdy_stream2->stream_id());
2269 data.RunFor(2);
2271 EXPECT_EQ(1u, spdy_stream1->stream_id());
2272 EXPECT_EQ(3u, spdy_stream2->stream_id());
2274 // Ensure we don't crash while closing the session.
2275 session->CloseSessionOnError(ERR_ABORTED, std::string());
2277 EXPECT_EQ(NULL, spdy_stream1.get());
2278 EXPECT_EQ(NULL, spdy_stream2.get());
2280 EXPECT_TRUE(delegate1.StreamIsClosed());
2281 EXPECT_TRUE(delegate2.StreamIsClosed());
2283 base::MessageLoop::current()->RunUntilIdle();
2284 EXPECT_TRUE(session == NULL);
2287 // Delegate that closes a given session when the stream is closed.
2288 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2289 public:
2290 SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2291 const base::WeakPtr<SpdySession>& session_to_close)
2292 : StreamDelegateDoNothing(stream),
2293 session_to_close_(session_to_close) {}
2295 ~SessionClosingDelegate() override {}
2297 void OnClose(int status) override {
2298 session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2301 private:
2302 base::WeakPtr<SpdySession> session_to_close_;
2305 // Close an activated stream that closes its session. Nothing should
2306 // blow up. This is a regression test for http://crbug.com/263691 .
2307 TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2308 session_deps_.host_resolver->set_synchronous_mode(true);
2310 MockConnect connect_data(SYNCHRONOUS, OK);
2312 scoped_ptr<SpdyFrame> req(
2313 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2314 scoped_ptr<SpdyFrame> rst(
2315 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2316 scoped_ptr<SpdyFrame> goaway(
2317 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2318 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2319 // despite being queued second.
2320 MockWrite writes[] = {
2321 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 1),
2322 CreateMockWrite(*rst, 2),
2325 MockRead reads[] = {
2326 MockRead(ASYNC, 0, 3) // EOF
2328 DeterministicSocketData data(reads, arraysize(reads),
2329 writes, arraysize(writes));
2330 data.set_connect_data(connect_data);
2331 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2333 CreateDeterministicNetworkSession();
2335 base::WeakPtr<SpdySession> session =
2336 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2338 GURL url(kDefaultURL);
2339 base::WeakPtr<SpdyStream> spdy_stream =
2340 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2341 session, url, MEDIUM, BoundNetLog());
2342 ASSERT_TRUE(spdy_stream.get() != NULL);
2343 EXPECT_EQ(0u, spdy_stream->stream_id());
2345 SessionClosingDelegate delegate(spdy_stream, session);
2346 spdy_stream->SetDelegate(&delegate);
2348 scoped_ptr<SpdyHeaderBlock> headers(
2349 spdy_util_.ConstructGetHeaderBlock(url.spec()));
2350 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2351 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2353 EXPECT_EQ(0u, spdy_stream->stream_id());
2355 data.RunFor(1);
2357 EXPECT_EQ(1u, spdy_stream->stream_id());
2359 // Ensure we don't crash while closing the stream (which closes the
2360 // session).
2361 spdy_stream->Cancel();
2363 EXPECT_EQ(NULL, spdy_stream.get());
2364 EXPECT_TRUE(delegate.StreamIsClosed());
2366 data.RunFor(2); // Write the RST_STREAM & GOAWAY.
2367 base::MessageLoop::current()->RunUntilIdle();
2368 EXPECT_TRUE(session == NULL);
2371 TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2372 session_deps_.host_resolver->set_synchronous_mode(true);
2374 MockConnect connect_data(SYNCHRONOUS, OK);
2376 // No actual data will be sent.
2377 MockWrite writes[] = {
2378 MockWrite(ASYNC, 0, 1) // EOF
2381 MockRead reads[] = {
2382 MockRead(ASYNC, 0, 0) // EOF
2384 DeterministicSocketData data(reads, arraysize(reads),
2385 writes, arraysize(writes));
2386 data.set_connect_data(connect_data);
2387 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2389 // Load a cert that is valid for:
2390 // www.example.org
2391 // mail.example.org
2392 // www.example.com
2393 base::FilePath certs_dir = GetTestCertsDirectory();
2394 scoped_refptr<X509Certificate> test_cert(
2395 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2396 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2398 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2399 ssl.cert = test_cert;
2400 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2402 CreateDeterministicNetworkSession();
2404 base::WeakPtr<SpdySession> session =
2405 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2407 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2408 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2409 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
2410 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2413 TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2414 session_deps_.host_resolver->set_synchronous_mode(true);
2416 MockConnect connect_data(SYNCHRONOUS, OK);
2418 // No actual data will be sent.
2419 MockWrite writes[] = {
2420 MockWrite(ASYNC, 0, 1) // EOF
2423 MockRead reads[] = {
2424 MockRead(ASYNC, 0, 0) // EOF
2426 DeterministicSocketData data(reads, arraysize(reads),
2427 writes, arraysize(writes));
2428 data.set_connect_data(connect_data);
2429 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2431 // Load a cert that is valid for:
2432 // www.example.org
2433 // mail.example.org
2434 // www.example.com
2435 base::FilePath certs_dir = GetTestCertsDirectory();
2436 scoped_refptr<X509Certificate> test_cert(
2437 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2438 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2440 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2441 ssl.channel_id_sent = true;
2442 ssl.cert = test_cert;
2443 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2445 CreateDeterministicNetworkSession();
2447 base::WeakPtr<SpdySession> session =
2448 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2450 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2451 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2452 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2453 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2456 TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2457 // TODO(rtenneti): Define a helper class/methods and move the common code in
2458 // this file.
2459 MockConnect connect_data(SYNCHRONOUS, OK);
2461 SettingsMap new_settings;
2462 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2463 const uint32 max_concurrent_streams = 1;
2464 new_settings[kSpdySettingsIds1] =
2465 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2467 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
2468 scoped_ptr<SpdyFrame> req1(
2469 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2470 scoped_ptr<SpdyFrame> req2(
2471 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
2472 scoped_ptr<SpdyFrame> req3(
2473 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
2474 MockWrite writes[] = {
2475 CreateMockWrite(*settings_ack, 1),
2476 CreateMockWrite(*req1, 2),
2477 CreateMockWrite(*req2, 5),
2478 CreateMockWrite(*req3, 8),
2481 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2482 // streams to 1.
2483 scoped_ptr<SpdyFrame> settings_frame(
2484 spdy_util_.ConstructSpdySettings(new_settings));
2486 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2487 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2489 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2490 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2492 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
2493 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2495 MockRead reads[] = {
2496 CreateMockRead(*settings_frame),
2497 CreateMockRead(*resp1, 3),
2498 CreateMockRead(*body1, 4),
2499 CreateMockRead(*resp2, 6),
2500 CreateMockRead(*body2, 7),
2501 CreateMockRead(*resp3, 9),
2502 CreateMockRead(*body3, 10),
2503 MockRead(ASYNC, 0, 11) // EOF
2506 DeterministicSocketData data(reads, arraysize(reads),
2507 writes, arraysize(writes));
2508 data.set_connect_data(connect_data);
2509 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2511 CreateDeterministicNetworkSession();
2513 base::WeakPtr<SpdySession> session =
2514 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2516 // Read the settings frame.
2517 data.RunFor(1);
2519 GURL url1(kDefaultURL);
2520 base::WeakPtr<SpdyStream> spdy_stream1 =
2521 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2522 session, url1, LOWEST, BoundNetLog());
2523 ASSERT_TRUE(spdy_stream1.get() != NULL);
2524 EXPECT_EQ(0u, spdy_stream1->stream_id());
2525 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2526 spdy_stream1->SetDelegate(&delegate1);
2528 TestCompletionCallback callback2;
2529 GURL url2(kDefaultURL);
2530 SpdyStreamRequest request2;
2531 ASSERT_EQ(ERR_IO_PENDING,
2532 request2.StartRequest(
2533 SPDY_REQUEST_RESPONSE_STREAM,
2534 session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2536 TestCompletionCallback callback3;
2537 GURL url3(kDefaultURL);
2538 SpdyStreamRequest request3;
2539 ASSERT_EQ(ERR_IO_PENDING,
2540 request3.StartRequest(
2541 SPDY_REQUEST_RESPONSE_STREAM,
2542 session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2544 EXPECT_EQ(0u, session->num_active_streams());
2545 EXPECT_EQ(1u, session->num_created_streams());
2546 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2548 scoped_ptr<SpdyHeaderBlock> headers(
2549 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2550 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2551 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2553 // Run until 1st stream is activated and then closed.
2554 EXPECT_EQ(0u, delegate1.stream_id());
2555 data.RunFor(4);
2556 EXPECT_EQ(NULL, spdy_stream1.get());
2557 EXPECT_EQ(1u, delegate1.stream_id());
2559 EXPECT_EQ(0u, session->num_active_streams());
2560 EXPECT_EQ(0u, session->num_created_streams());
2561 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2563 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2564 // create the 2nd stream.
2565 base::MessageLoop::current()->RunUntilIdle();
2567 EXPECT_EQ(0u, session->num_active_streams());
2568 EXPECT_EQ(1u, session->num_created_streams());
2569 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2571 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2572 test::StreamDelegateDoNothing delegate2(stream2);
2573 stream2->SetDelegate(&delegate2);
2574 scoped_ptr<SpdyHeaderBlock> headers2(
2575 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2576 stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2577 EXPECT_TRUE(stream2->HasUrlFromHeaders());
2579 // Run until 2nd stream is activated and then closed.
2580 EXPECT_EQ(0u, delegate2.stream_id());
2581 data.RunFor(3);
2582 EXPECT_EQ(NULL, stream2.get());
2583 EXPECT_EQ(3u, delegate2.stream_id());
2585 EXPECT_EQ(0u, session->num_active_streams());
2586 EXPECT_EQ(0u, session->num_created_streams());
2587 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2589 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2590 // create the 3rd stream.
2591 base::MessageLoop::current()->RunUntilIdle();
2593 EXPECT_EQ(0u, session->num_active_streams());
2594 EXPECT_EQ(1u, session->num_created_streams());
2595 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2597 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2598 test::StreamDelegateDoNothing delegate3(stream3);
2599 stream3->SetDelegate(&delegate3);
2600 scoped_ptr<SpdyHeaderBlock> headers3(
2601 spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2602 stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2603 EXPECT_TRUE(stream3->HasUrlFromHeaders());
2605 // Run until 2nd stream is activated and then closed.
2606 EXPECT_EQ(0u, delegate3.stream_id());
2607 data.RunFor(3);
2608 EXPECT_EQ(NULL, stream3.get());
2609 EXPECT_EQ(5u, delegate3.stream_id());
2611 EXPECT_EQ(0u, session->num_active_streams());
2612 EXPECT_EQ(0u, session->num_created_streams());
2613 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2615 data.RunFor(1);
2618 TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2619 session_deps_.host_resolver->set_synchronous_mode(true);
2621 MockRead reads[] = {
2622 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2625 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2626 MockConnect connect_data(SYNCHRONOUS, OK);
2628 data.set_connect_data(connect_data);
2629 session_deps_.socket_factory->AddSocketDataProvider(&data);
2631 CreateNetworkSession();
2633 base::WeakPtr<SpdySession> session =
2634 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2636 // Leave room for only one more stream to be created.
2637 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2638 base::WeakPtr<SpdyStream> spdy_stream =
2639 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2640 session, test_url_, MEDIUM, BoundNetLog());
2641 ASSERT_TRUE(spdy_stream != NULL);
2644 GURL url1(kDefaultURL);
2645 base::WeakPtr<SpdyStream> spdy_stream1 =
2646 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2647 session, url1, LOWEST, BoundNetLog());
2648 ASSERT_TRUE(spdy_stream1.get() != NULL);
2649 EXPECT_EQ(0u, spdy_stream1->stream_id());
2651 TestCompletionCallback callback2;
2652 GURL url2(kDefaultURL);
2653 SpdyStreamRequest request2;
2654 ASSERT_EQ(ERR_IO_PENDING,
2655 request2.StartRequest(
2656 SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2657 callback2.callback()));
2659 TestCompletionCallback callback3;
2660 GURL url3(kDefaultURL);
2661 SpdyStreamRequest request3;
2662 ASSERT_EQ(ERR_IO_PENDING,
2663 request3.StartRequest(
2664 SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2665 callback3.callback()));
2667 EXPECT_EQ(0u, session->num_active_streams());
2668 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2669 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2671 // Cancel the first stream; this will allow the second stream to be created.
2672 EXPECT_TRUE(spdy_stream1.get() != NULL);
2673 spdy_stream1->Cancel();
2674 EXPECT_EQ(NULL, spdy_stream1.get());
2676 EXPECT_EQ(OK, callback2.WaitForResult());
2677 EXPECT_EQ(0u, session->num_active_streams());
2678 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2679 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2681 // Cancel the second stream; this will allow the third stream to be created.
2682 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2683 spdy_stream2->Cancel();
2684 EXPECT_EQ(NULL, spdy_stream2.get());
2686 EXPECT_EQ(OK, callback3.WaitForResult());
2687 EXPECT_EQ(0u, session->num_active_streams());
2688 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2689 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2691 // Cancel the third stream.
2692 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2693 spdy_stream3->Cancel();
2694 EXPECT_EQ(NULL, spdy_stream3.get());
2695 EXPECT_EQ(0u, session->num_active_streams());
2696 EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
2697 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2700 // Test that SpdySession::DoReadLoop reads data from the socket
2701 // without yielding. This test makes 32k - 1 bytes of data available
2702 // on the socket for reading. It then verifies that it has read all
2703 // the available data without yielding.
2704 TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2705 MockConnect connect_data(SYNCHRONOUS, OK);
2706 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2708 scoped_ptr<SpdyFrame> req1(
2709 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2710 MockWrite writes[] = {
2711 CreateMockWrite(*req1, 0),
2714 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2715 // (-spdy_data_frame_size).
2716 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2717 const int kPayloadSize =
2718 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2719 TestDataStream test_stream;
2720 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2721 char* payload_data = payload->data();
2722 test_stream.GetBytes(payload_data, kPayloadSize);
2724 scoped_ptr<SpdyFrame> partial_data_frame(
2725 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2726 scoped_ptr<SpdyFrame> finish_data_frame(
2727 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2729 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2731 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2732 // bytes.
2733 MockRead reads[] = {
2734 CreateMockRead(*resp1, 1),
2735 CreateMockRead(*partial_data_frame, 2),
2736 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2737 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2738 CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2739 MockRead(ASYNC, 0, 6) // EOF
2742 // Create SpdySession and SpdyStream and send the request.
2743 DeterministicSocketData data(reads, arraysize(reads),
2744 writes, arraysize(writes));
2745 data.set_connect_data(connect_data);
2746 session_deps_.host_resolver->set_synchronous_mode(true);
2747 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2749 CreateDeterministicNetworkSession();
2751 base::WeakPtr<SpdySession> session =
2752 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2754 GURL url1(kDefaultURL);
2755 base::WeakPtr<SpdyStream> spdy_stream1 =
2756 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2757 session, url1, MEDIUM, BoundNetLog());
2758 ASSERT_TRUE(spdy_stream1.get() != NULL);
2759 EXPECT_EQ(0u, spdy_stream1->stream_id());
2760 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2761 spdy_stream1->SetDelegate(&delegate1);
2763 scoped_ptr<SpdyHeaderBlock> headers1(
2764 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2765 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2766 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2768 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2769 // post a task.
2770 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2772 // Run until 1st read.
2773 EXPECT_EQ(0u, delegate1.stream_id());
2774 data.RunFor(2);
2775 EXPECT_EQ(1u, delegate1.stream_id());
2776 EXPECT_EQ(0u, observer.executed_count());
2778 // Read all the data and verify SpdySession::DoReadLoop has not
2779 // posted a task.
2780 data.RunFor(4);
2781 EXPECT_EQ(NULL, spdy_stream1.get());
2783 // Verify task observer's executed_count is zero, which indicates DoRead read
2784 // all the available data.
2785 EXPECT_EQ(0u, observer.executed_count());
2786 EXPECT_TRUE(data.at_write_eof());
2787 EXPECT_TRUE(data.at_read_eof());
2790 // Test that SpdySession::DoReadLoop yields while reading the
2791 // data. This test makes 32k + 1 bytes of data available on the socket
2792 // for reading. It then verifies that DoRead has yielded even though
2793 // there is data available for it to read (i.e, socket()->Read didn't
2794 // return ERR_IO_PENDING during socket reads).
2795 TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2796 MockConnect connect_data(SYNCHRONOUS, OK);
2797 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2799 scoped_ptr<SpdyFrame> req1(
2800 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2801 MockWrite writes[] = {
2802 CreateMockWrite(*req1, 0),
2805 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2806 // (-spdy_data_frame_size).
2807 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2808 const int kPayloadSize =
2809 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2810 TestDataStream test_stream;
2811 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2812 char* payload_data = payload->data();
2813 test_stream.GetBytes(payload_data, kPayloadSize);
2815 scoped_ptr<SpdyFrame> partial_data_frame(
2816 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2817 scoped_ptr<SpdyFrame> finish_data_frame(
2818 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2820 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2822 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2823 MockRead reads[] = {
2824 CreateMockRead(*resp1, 1),
2825 CreateMockRead(*partial_data_frame, 2),
2826 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2827 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2828 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2829 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2830 MockRead(ASYNC, 0, 7) // EOF
2833 // Create SpdySession and SpdyStream and send the request.
2834 DeterministicSocketData data(reads, arraysize(reads),
2835 writes, arraysize(writes));
2836 data.set_connect_data(connect_data);
2837 session_deps_.host_resolver->set_synchronous_mode(true);
2838 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2840 CreateDeterministicNetworkSession();
2842 base::WeakPtr<SpdySession> session =
2843 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2845 GURL url1(kDefaultURL);
2846 base::WeakPtr<SpdyStream> spdy_stream1 =
2847 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2848 session, url1, MEDIUM, BoundNetLog());
2849 ASSERT_TRUE(spdy_stream1.get() != NULL);
2850 EXPECT_EQ(0u, spdy_stream1->stream_id());
2851 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2852 spdy_stream1->SetDelegate(&delegate1);
2854 scoped_ptr<SpdyHeaderBlock> headers1(
2855 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2856 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2857 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2859 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2860 // task.
2861 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2863 // Run until 1st read.
2864 EXPECT_EQ(0u, delegate1.stream_id());
2865 data.RunFor(2);
2866 EXPECT_EQ(1u, delegate1.stream_id());
2867 EXPECT_EQ(0u, observer.executed_count());
2869 // Read all the data and verify SpdySession::DoReadLoop has posted a
2870 // task.
2871 data.RunFor(6);
2872 EXPECT_EQ(NULL, spdy_stream1.get());
2874 // Verify task observer's executed_count is 1, which indicates DoRead has
2875 // posted only one task and thus yielded though there is data available for it
2876 // to read.
2877 EXPECT_EQ(1u, observer.executed_count());
2878 EXPECT_TRUE(data.at_write_eof());
2879 EXPECT_TRUE(data.at_read_eof());
2882 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2883 // + async, by doing the following MockReads.
2885 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2886 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2888 // The above reads 26K synchronously. Since that is less that 32K, we
2889 // will attempt to read again. However, that DoRead() will return
2890 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2891 // yield. When we come back, DoRead() will read the results from the
2892 // async read, and rest of the data synchronously.
2893 TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2894 MockConnect connect_data(SYNCHRONOUS, OK);
2895 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2897 scoped_ptr<SpdyFrame> req1(
2898 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2899 MockWrite writes[] = {
2900 CreateMockWrite(*req1, 0),
2903 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2904 // (-spdy_data_frame_size).
2905 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2906 TestDataStream test_stream;
2907 const int kEightKPayloadSize =
2908 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2909 scoped_refptr<net::IOBuffer> eightk_payload(
2910 new net::IOBuffer(kEightKPayloadSize));
2911 char* eightk_payload_data = eightk_payload->data();
2912 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2914 // Build buffer of 2k size.
2915 TestDataStream test_stream2;
2916 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2917 scoped_refptr<net::IOBuffer> twok_payload(
2918 new net::IOBuffer(kTwoKPayloadSize));
2919 char* twok_payload_data = twok_payload->data();
2920 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2922 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2923 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2924 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2925 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2926 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2927 1, "h", 1, DATA_FLAG_FIN));
2929 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2931 MockRead reads[] = {
2932 CreateMockRead(*resp1, 1),
2933 CreateMockRead(*eightk_data_frame, 2),
2934 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
2935 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2936 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
2937 CreateMockRead(*eightk_data_frame, 6, ASYNC),
2938 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
2939 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2940 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2941 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
2942 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
2943 MockRead(ASYNC, 0, 12) // EOF
2946 // Create SpdySession and SpdyStream and send the request.
2947 DeterministicSocketData data(reads, arraysize(reads),
2948 writes, arraysize(writes));
2949 data.set_connect_data(connect_data);
2950 session_deps_.host_resolver->set_synchronous_mode(true);
2951 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2953 CreateDeterministicNetworkSession();
2955 base::WeakPtr<SpdySession> session =
2956 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2958 GURL url1(kDefaultURL);
2959 base::WeakPtr<SpdyStream> spdy_stream1 =
2960 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2961 session, url1, MEDIUM, BoundNetLog());
2962 ASSERT_TRUE(spdy_stream1.get() != NULL);
2963 EXPECT_EQ(0u, spdy_stream1->stream_id());
2964 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2965 spdy_stream1->SetDelegate(&delegate1);
2967 scoped_ptr<SpdyHeaderBlock> headers1(
2968 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2969 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2970 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2972 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2973 // posting of tasks.
2974 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2976 // Run until 1st read.
2977 EXPECT_EQ(0u, delegate1.stream_id());
2978 data.RunFor(2);
2979 EXPECT_EQ(1u, delegate1.stream_id());
2980 EXPECT_EQ(0u, observer.executed_count());
2982 // Read all the data and verify SpdySession::DoReadLoop has posted a
2983 // task.
2984 data.RunFor(12);
2985 EXPECT_EQ(NULL, spdy_stream1.get());
2987 // Verify task observer's executed_count is 1, which indicates DoRead has
2988 // posted only one task and thus yielded though there is data available for
2989 // it to read.
2990 EXPECT_EQ(1u, observer.executed_count());
2991 EXPECT_TRUE(data.at_write_eof());
2992 EXPECT_TRUE(data.at_read_eof());
2995 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2996 // nothing blows up.
2997 TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
2998 MockConnect connect_data(SYNCHRONOUS, OK);
2999 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3001 scoped_ptr<SpdyFrame> req1(
3002 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3003 MockWrite writes[] = {
3004 CreateMockWrite(*req1, 0),
3007 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3008 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
3009 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
3011 MockRead reads[] = {
3012 CreateMockRead(*resp1, 1),
3013 CreateMockRead(*body1, 2),
3014 CreateMockRead(*goaway, 3),
3017 // Create SpdySession and SpdyStream and send the request.
3018 DeterministicSocketData data(reads, arraysize(reads),
3019 writes, arraysize(writes));
3020 data.set_connect_data(connect_data);
3021 session_deps_.host_resolver->set_synchronous_mode(true);
3022 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3024 CreateDeterministicNetworkSession();
3026 base::WeakPtr<SpdySession> session =
3027 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3029 GURL url1(kDefaultURL);
3030 base::WeakPtr<SpdyStream> spdy_stream1 =
3031 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3032 session, url1, MEDIUM, BoundNetLog());
3033 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3034 spdy_stream1->SetDelegate(&delegate1);
3035 ASSERT_TRUE(spdy_stream1.get() != NULL);
3036 EXPECT_EQ(0u, spdy_stream1->stream_id());
3038 scoped_ptr<SpdyHeaderBlock> headers1(
3039 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3040 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
3041 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3043 // Run until 1st read.
3044 EXPECT_EQ(0u, spdy_stream1->stream_id());
3045 data.RunFor(1);
3046 EXPECT_EQ(1u, spdy_stream1->stream_id());
3048 // Run until GoAway.
3049 data.RunFor(3);
3050 EXPECT_EQ(NULL, spdy_stream1.get());
3051 EXPECT_TRUE(data.at_write_eof());
3052 EXPECT_TRUE(data.at_read_eof());
3053 EXPECT_TRUE(session == NULL);
3056 // Within this framework, a SpdySession should be initialized with
3057 // flow control disabled for protocol version 2, with flow control
3058 // enabled only for streams for protocol version 3, and with flow
3059 // control enabled for streams and sessions for higher versions.
3060 TEST_P(SpdySessionTest, ProtocolNegotiation) {
3061 session_deps_.host_resolver->set_synchronous_mode(true);
3063 MockConnect connect_data(SYNCHRONOUS, OK);
3064 MockRead reads[] = {
3065 MockRead(SYNCHRONOUS, 0, 0) // EOF
3067 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3068 data.set_connect_data(connect_data);
3069 session_deps_.socket_factory->AddSocketDataProvider(&data);
3071 CreateNetworkSession();
3072 base::WeakPtr<SpdySession> session =
3073 CreateFakeSpdySession(spdy_session_pool_, key_);
3075 EXPECT_EQ(spdy_util_.spdy_version(),
3076 session->buffered_spdy_framer_->protocol_version());
3077 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3078 session->flow_control_state());
3079 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3080 session->session_send_window_size_);
3081 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3082 session->session_recv_window_size_);
3083 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3086 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3087 // pointers to the idle session are currently held.
3088 TEST_P(SpdySessionTest, CloseOneIdleConnection) {
3089 ClientSocketPoolManager::set_max_sockets_per_group(
3090 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3091 ClientSocketPoolManager::set_max_sockets_per_pool(
3092 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3094 MockConnect connect_data(SYNCHRONOUS, OK);
3095 MockRead reads[] = {
3096 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3098 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3099 data.set_connect_data(connect_data);
3100 session_deps_.socket_factory->AddSocketDataProvider(&data);
3101 session_deps_.socket_factory->AddSocketDataProvider(&data);
3103 CreateNetworkSession();
3105 TransportClientSocketPool* pool =
3106 http_session_->GetTransportSocketPool(
3107 HttpNetworkSession::NORMAL_SOCKET_POOL);
3109 // Create an idle SPDY session.
3110 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3111 PRIVACY_MODE_DISABLED);
3112 base::WeakPtr<SpdySession> session1 =
3113 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3114 EXPECT_FALSE(pool->IsStalled());
3116 // Trying to create a new connection should cause the pool to be stalled, and
3117 // post a task asynchronously to try and close the session.
3118 TestCompletionCallback callback2;
3119 HostPortPair host_port2("2.com", 80);
3120 scoped_refptr<TransportSocketParams> params2(
3121 new TransportSocketParams(
3122 host_port2, false, false, OnHostResolutionCallback(),
3123 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3124 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3125 EXPECT_EQ(ERR_IO_PENDING,
3126 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3127 callback2.callback(), pool, BoundNetLog()));
3128 EXPECT_TRUE(pool->IsStalled());
3130 // The socket pool should close the connection asynchronously and establish a
3131 // new connection.
3132 EXPECT_EQ(OK, callback2.WaitForResult());
3133 EXPECT_FALSE(pool->IsStalled());
3134 EXPECT_TRUE(session1 == NULL);
3137 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3138 // pointers to the idle session are currently held, in the case the SPDY session
3139 // has an alias.
3140 TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
3141 ClientSocketPoolManager::set_max_sockets_per_group(
3142 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3143 ClientSocketPoolManager::set_max_sockets_per_pool(
3144 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3146 MockConnect connect_data(SYNCHRONOUS, OK);
3147 MockRead reads[] = {
3148 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3150 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3151 data.set_connect_data(connect_data);
3152 session_deps_.socket_factory->AddSocketDataProvider(&data);
3153 session_deps_.socket_factory->AddSocketDataProvider(&data);
3155 session_deps_.host_resolver->set_synchronous_mode(true);
3156 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3157 "1.com", "192.168.0.2", std::string());
3158 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3159 "2.com", "192.168.0.2", std::string());
3160 // Not strictly needed.
3161 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3162 "3.com", "192.168.0.3", std::string());
3164 CreateNetworkSession();
3166 TransportClientSocketPool* pool =
3167 http_session_->GetTransportSocketPool(
3168 HttpNetworkSession::NORMAL_SOCKET_POOL);
3170 // Create an idle SPDY session.
3171 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3172 PRIVACY_MODE_DISABLED);
3173 base::WeakPtr<SpdySession> session1 =
3174 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3175 EXPECT_FALSE(pool->IsStalled());
3177 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3178 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3179 PRIVACY_MODE_DISABLED);
3180 HostResolver::RequestInfo info(key2.host_port_pair());
3181 AddressList addresses;
3182 // Pre-populate the DNS cache, since a synchronous resolution is required in
3183 // order to create the alias.
3184 session_deps_.host_resolver->Resolve(info,
3185 DEFAULT_PRIORITY,
3186 &addresses,
3187 CompletionCallback(),
3188 NULL,
3189 BoundNetLog());
3190 // Get a session for |key2|, which should return the session created earlier.
3191 base::WeakPtr<SpdySession> session2 =
3192 spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3193 ASSERT_EQ(session1.get(), session2.get());
3194 EXPECT_FALSE(pool->IsStalled());
3196 // Trying to create a new connection should cause the pool to be stalled, and
3197 // post a task asynchronously to try and close the session.
3198 TestCompletionCallback callback3;
3199 HostPortPair host_port3("3.com", 80);
3200 scoped_refptr<TransportSocketParams> params3(
3201 new TransportSocketParams(
3202 host_port3, false, false, OnHostResolutionCallback(),
3203 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3204 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3205 EXPECT_EQ(ERR_IO_PENDING,
3206 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3207 callback3.callback(), pool, BoundNetLog()));
3208 EXPECT_TRUE(pool->IsStalled());
3210 // The socket pool should close the connection asynchronously and establish a
3211 // new connection.
3212 EXPECT_EQ(OK, callback3.WaitForResult());
3213 EXPECT_FALSE(pool->IsStalled());
3214 EXPECT_TRUE(session1 == NULL);
3215 EXPECT_TRUE(session2 == NULL);
3218 // Tests that when a SPDY session becomes idle, it closes itself if there is
3219 // a lower layer pool stalled on the per-pool socket limit.
3220 TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3221 ClientSocketPoolManager::set_max_sockets_per_group(
3222 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3223 ClientSocketPoolManager::set_max_sockets_per_pool(
3224 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3226 MockConnect connect_data(SYNCHRONOUS, OK);
3227 MockRead reads[] = {
3228 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3230 scoped_ptr<SpdyFrame> req1(
3231 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3232 scoped_ptr<SpdyFrame> cancel1(
3233 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3234 MockWrite writes[] = {
3235 CreateMockWrite(*req1, 1),
3236 CreateMockWrite(*cancel1, 1),
3238 StaticSocketDataProvider data(reads, arraysize(reads),
3239 writes, arraysize(writes));
3240 data.set_connect_data(connect_data);
3241 session_deps_.socket_factory->AddSocketDataProvider(&data);
3243 MockRead http_reads[] = {
3244 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3246 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
3247 NULL, 0);
3248 http_data.set_connect_data(connect_data);
3249 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3252 CreateNetworkSession();
3254 TransportClientSocketPool* pool =
3255 http_session_->GetTransportSocketPool(
3256 HttpNetworkSession::NORMAL_SOCKET_POOL);
3258 // Create a SPDY session.
3259 GURL url1(kDefaultURL);
3260 SpdySessionKey key1(HostPortPair(url1.host(), 80),
3261 ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3262 base::WeakPtr<SpdySession> session1 =
3263 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3264 EXPECT_FALSE(pool->IsStalled());
3266 // Create a stream using the session, and send a request.
3268 TestCompletionCallback callback1;
3269 base::WeakPtr<SpdyStream> spdy_stream1 =
3270 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3271 session1, url1, DEFAULT_PRIORITY,
3272 BoundNetLog());
3273 ASSERT_TRUE(spdy_stream1.get());
3274 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3275 spdy_stream1->SetDelegate(&delegate1);
3277 scoped_ptr<SpdyHeaderBlock> headers1(
3278 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3279 EXPECT_EQ(ERR_IO_PENDING,
3280 spdy_stream1->SendRequestHeaders(
3281 headers1.Pass(), NO_MORE_DATA_TO_SEND));
3282 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3284 base::MessageLoop::current()->RunUntilIdle();
3286 // Trying to create a new connection should cause the pool to be stalled, and
3287 // post a task asynchronously to try and close the session.
3288 TestCompletionCallback callback2;
3289 HostPortPair host_port2("2.com", 80);
3290 scoped_refptr<TransportSocketParams> params2(
3291 new TransportSocketParams(
3292 host_port2, false, false, OnHostResolutionCallback(),
3293 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3294 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3295 EXPECT_EQ(ERR_IO_PENDING,
3296 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3297 callback2.callback(), pool, BoundNetLog()));
3298 EXPECT_TRUE(pool->IsStalled());
3300 // Running the message loop should cause the socket pool to ask the SPDY
3301 // session to close an idle socket, but since the socket is in use, nothing
3302 // happens.
3303 base::RunLoop().RunUntilIdle();
3304 EXPECT_TRUE(pool->IsStalled());
3305 EXPECT_FALSE(callback2.have_result());
3307 // Cancelling the request should result in the session's socket being
3308 // closed, since the pool is stalled.
3309 ASSERT_TRUE(spdy_stream1.get());
3310 spdy_stream1->Cancel();
3311 base::RunLoop().RunUntilIdle();
3312 ASSERT_FALSE(pool->IsStalled());
3313 EXPECT_EQ(OK, callback2.WaitForResult());
3316 // Verify that SpdySessionKey and therefore SpdySession is different when
3317 // privacy mode is enabled or disabled.
3318 TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3319 CreateDeterministicNetworkSession();
3321 HostPortPair host_port_pair("www.google.com", 443);
3322 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3323 PRIVACY_MODE_ENABLED);
3324 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3325 PRIVACY_MODE_DISABLED);
3327 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3328 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3330 // Add SpdySession with PrivacyMode Enabled to the pool.
3331 base::WeakPtr<SpdySession> session_privacy_enabled =
3332 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3334 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3335 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3337 // Add SpdySession with PrivacyMode Disabled to the pool.
3338 base::WeakPtr<SpdySession> session_privacy_disabled =
3339 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3341 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3342 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3344 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3345 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3346 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3348 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3349 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3350 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3353 // Delegate that creates another stream when its stream is closed.
3354 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3355 public:
3356 StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3357 const base::WeakPtr<SpdySession>& session)
3358 : StreamDelegateDoNothing(stream),
3359 session_(session) {}
3361 ~StreamCreatingDelegate() override {}
3363 void OnClose(int status) override {
3364 GURL url(kDefaultURL);
3365 ignore_result(
3366 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3367 session_, url, MEDIUM, BoundNetLog()));
3370 private:
3371 const base::WeakPtr<SpdySession> session_;
3374 // Create another stream in response to a stream being reset. Nothing
3375 // should blow up. This is a regression test for
3376 // http://crbug.com/263690 .
3377 TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3378 session_deps_.host_resolver->set_synchronous_mode(true);
3380 MockConnect connect_data(SYNCHRONOUS, OK);
3382 scoped_ptr<SpdyFrame> req(
3383 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3384 MockWrite writes[] = {
3385 CreateMockWrite(*req, 0),
3388 scoped_ptr<SpdyFrame> rst(
3389 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3390 MockRead reads[] = {
3391 CreateMockRead(*rst, 1),
3392 MockRead(ASYNC, 0, 2) // EOF
3394 DeterministicSocketData data(reads, arraysize(reads),
3395 writes, arraysize(writes));
3396 data.set_connect_data(connect_data);
3397 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3399 CreateDeterministicNetworkSession();
3401 base::WeakPtr<SpdySession> session =
3402 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3404 GURL url(kDefaultURL);
3405 base::WeakPtr<SpdyStream> spdy_stream =
3406 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3407 session, url, MEDIUM, BoundNetLog());
3408 ASSERT_TRUE(spdy_stream.get() != NULL);
3409 EXPECT_EQ(0u, spdy_stream->stream_id());
3411 StreamCreatingDelegate delegate(spdy_stream, session);
3412 spdy_stream->SetDelegate(&delegate);
3414 scoped_ptr<SpdyHeaderBlock> headers(
3415 spdy_util_.ConstructGetHeaderBlock(url.spec()));
3416 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3417 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3419 EXPECT_EQ(0u, spdy_stream->stream_id());
3421 data.RunFor(1);
3423 EXPECT_EQ(1u, spdy_stream->stream_id());
3425 // Cause the stream to be reset, which should cause another stream
3426 // to be created.
3427 data.RunFor(1);
3429 EXPECT_EQ(NULL, spdy_stream.get());
3430 EXPECT_TRUE(delegate.StreamIsClosed());
3431 EXPECT_EQ(0u, session->num_active_streams());
3432 EXPECT_EQ(1u, session->num_created_streams());
3435 // The tests below are only for SPDY/3 and above.
3437 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3438 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3439 // gets sent.
3440 SettingsMap new_settings;
3441 int32 window_size = 1;
3442 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3443 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3445 // Set up the socket so we read a SETTINGS frame that sets
3446 // INITIAL_WINDOW_SIZE.
3447 MockConnect connect_data(SYNCHRONOUS, OK);
3448 scoped_ptr<SpdyFrame> settings_frame(
3449 spdy_util_.ConstructSpdySettings(new_settings));
3450 MockRead reads[] = {
3451 CreateMockRead(*settings_frame, 0),
3452 MockRead(ASYNC, 0, 1) // EOF
3455 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3456 MockWrite writes[] = {
3457 CreateMockWrite(*settings_ack, 2),
3460 session_deps_.host_resolver->set_synchronous_mode(true);
3462 DeterministicSocketData data(reads, arraysize(reads),
3463 writes, arraysize(writes));
3464 data.set_connect_data(connect_data);
3465 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3467 CreateDeterministicNetworkSession();
3469 base::WeakPtr<SpdySession> session =
3470 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3471 base::WeakPtr<SpdyStream> spdy_stream1 =
3472 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3473 session, test_url_, MEDIUM, BoundNetLog());
3474 ASSERT_TRUE(spdy_stream1.get() != NULL);
3475 TestCompletionCallback callback1;
3476 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3478 data.RunFor(1); // Process the SETTINGS frame, but not the EOF
3479 base::MessageLoop::current()->RunUntilIdle();
3480 EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3481 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3483 // Release the first one, this will allow the second to be created.
3484 spdy_stream1->Cancel();
3485 EXPECT_EQ(NULL, spdy_stream1.get());
3487 base::WeakPtr<SpdyStream> spdy_stream2 =
3488 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3489 session, test_url_, MEDIUM, BoundNetLog());
3490 ASSERT_TRUE(spdy_stream2.get() != NULL);
3491 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3492 spdy_stream2->Cancel();
3493 EXPECT_EQ(NULL, spdy_stream2.get());
3496 // The tests below are only for SPDY/3.1 and above.
3498 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3499 // adjust the session receive window size for SPDY 3.1 and higher. In
3500 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3501 // sending a WINDOW_UPDATE frame for a large enough delta.
3502 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3503 if (GetParam() < kProtoSPDY31)
3504 return;
3506 session_deps_.host_resolver->set_synchronous_mode(true);
3508 const int32 initial_window_size =
3509 SpdySession::GetInitialWindowSize(GetParam());
3510 const int32 delta_window_size = 100;
3512 MockConnect connect_data(SYNCHRONOUS, OK);
3513 MockRead reads[] = {
3514 MockRead(ASYNC, 0, 1) // EOF
3516 scoped_ptr<SpdyFrame> window_update(spdy_util_.ConstructSpdyWindowUpdate(
3517 kSessionFlowControlStreamId, initial_window_size + delta_window_size));
3518 MockWrite writes[] = {
3519 CreateMockWrite(*window_update, 0),
3521 DeterministicSocketData data(reads, arraysize(reads),
3522 writes, arraysize(writes));
3523 data.set_connect_data(connect_data);
3524 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3526 CreateDeterministicNetworkSession();
3527 base::WeakPtr<SpdySession> session =
3528 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3529 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3530 session->flow_control_state());
3532 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3533 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3535 session->IncreaseRecvWindowSize(delta_window_size);
3536 EXPECT_EQ(initial_window_size + delta_window_size,
3537 session->session_recv_window_size_);
3538 EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3540 // Should trigger sending a WINDOW_UPDATE frame.
3541 session->IncreaseRecvWindowSize(initial_window_size);
3542 EXPECT_EQ(initial_window_size + delta_window_size + initial_window_size,
3543 session->session_recv_window_size_);
3544 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3546 data.RunFor(1);
3548 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3549 session->in_io_loop_ = true;
3550 session->DecreaseRecvWindowSize(initial_window_size + delta_window_size +
3551 initial_window_size);
3552 session->in_io_loop_ = false;
3553 EXPECT_EQ(0, session->session_recv_window_size_);
3554 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3557 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3558 // adjust the session send window size when the "enable_spdy_31" flag
3559 // is set.
3560 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3561 if (GetParam() < kProtoSPDY31)
3562 return;
3564 session_deps_.host_resolver->set_synchronous_mode(true);
3566 MockConnect connect_data(SYNCHRONOUS, OK);
3567 MockRead reads[] = {
3568 MockRead(SYNCHRONOUS, 0, 0) // EOF
3570 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3571 data.set_connect_data(connect_data);
3572 session_deps_.socket_factory->AddSocketDataProvider(&data);
3574 CreateNetworkSession();
3575 base::WeakPtr<SpdySession> session =
3576 CreateFakeSpdySession(spdy_session_pool_, key_);
3577 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3578 session->flow_control_state());
3580 const int32 initial_window_size =
3581 SpdySession::GetInitialWindowSize(GetParam());
3582 const int32 delta_window_size = 100;
3584 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3586 session->IncreaseSendWindowSize(delta_window_size);
3587 EXPECT_EQ(initial_window_size + delta_window_size,
3588 session->session_send_window_size_);
3590 session->DecreaseSendWindowSize(delta_window_size);
3591 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3594 // Incoming data for an inactive stream should not cause the session
3595 // receive window size to decrease, but it should cause the unacked
3596 // bytes to increase.
3597 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3598 if (GetParam() < kProtoSPDY31)
3599 return;
3601 session_deps_.host_resolver->set_synchronous_mode(true);
3603 MockConnect connect_data(SYNCHRONOUS, OK);
3604 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3605 MockRead reads[] = {
3606 CreateMockRead(*resp, 0),
3607 MockRead(ASYNC, 0, 1) // EOF
3609 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3610 data.set_connect_data(connect_data);
3611 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3613 CreateDeterministicNetworkSession();
3614 base::WeakPtr<SpdySession> session =
3615 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3616 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3617 session->flow_control_state());
3619 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3620 session->session_recv_window_size_);
3621 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3623 data.RunFor(1);
3625 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3626 session->session_recv_window_size_);
3627 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3629 data.RunFor(1);
3632 // A delegate that drops any received data.
3633 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3634 public:
3635 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3636 base::StringPiece data)
3637 : StreamDelegateSendImmediate(stream, data) {}
3639 ~DropReceivedDataDelegate() override {}
3641 // Drop any received data.
3642 void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override {}
3645 // Send data back and forth but use a delegate that drops its received
3646 // data. The receive window should still increase to its original
3647 // value, i.e. we shouldn't "leak" receive window bytes.
3648 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3649 if (GetParam() < kProtoSPDY31)
3650 return;
3652 const char kStreamUrl[] = "http://www.google.com/";
3654 const int32 msg_data_size = 100;
3655 const std::string msg_data(msg_data_size, 'a');
3657 MockConnect connect_data(SYNCHRONOUS, OK);
3659 scoped_ptr<SpdyFrame> req(
3660 spdy_util_.ConstructSpdyPost(
3661 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3662 scoped_ptr<SpdyFrame> msg(
3663 spdy_util_.ConstructSpdyBodyFrame(
3664 1, msg_data.data(), msg_data_size, false));
3665 MockWrite writes[] = {
3666 CreateMockWrite(*req, 0),
3667 CreateMockWrite(*msg, 2),
3670 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3671 scoped_ptr<SpdyFrame> echo(
3672 spdy_util_.ConstructSpdyBodyFrame(
3673 1, msg_data.data(), msg_data_size, false));
3674 scoped_ptr<SpdyFrame> window_update(
3675 spdy_util_.ConstructSpdyWindowUpdate(
3676 kSessionFlowControlStreamId, msg_data_size));
3677 MockRead reads[] = {
3678 CreateMockRead(*resp, 1),
3679 CreateMockRead(*echo, 3),
3680 MockRead(ASYNC, 0, 4) // EOF
3683 // Create SpdySession and SpdyStream and send the request.
3684 DeterministicSocketData data(reads, arraysize(reads),
3685 writes, arraysize(writes));
3686 data.set_connect_data(connect_data);
3687 session_deps_.host_resolver->set_synchronous_mode(true);
3688 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3690 CreateDeterministicNetworkSession();
3692 base::WeakPtr<SpdySession> session =
3693 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3695 GURL url(kStreamUrl);
3696 base::WeakPtr<SpdyStream> stream =
3697 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3698 session, url, MEDIUM, BoundNetLog());
3699 ASSERT_TRUE(stream.get() != NULL);
3700 EXPECT_EQ(0u, stream->stream_id());
3702 DropReceivedDataDelegate delegate(stream, msg_data);
3703 stream->SetDelegate(&delegate);
3705 scoped_ptr<SpdyHeaderBlock> headers(
3706 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3707 EXPECT_EQ(ERR_IO_PENDING,
3708 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3709 EXPECT_TRUE(stream->HasUrlFromHeaders());
3711 const int32 initial_window_size =
3712 SpdySession::GetInitialWindowSize(GetParam());
3713 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3714 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3716 data.RunFor(4);
3718 EXPECT_TRUE(data.at_write_eof());
3719 EXPECT_TRUE(data.at_read_eof());
3721 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3722 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3724 stream->Close();
3725 EXPECT_EQ(NULL, stream.get());
3727 EXPECT_EQ(OK, delegate.WaitForClose());
3729 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3730 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3733 // Send data back and forth but close the stream before its data frame
3734 // can be written to the socket. The send window should then increase
3735 // to its original value, i.e. we shouldn't "leak" send window bytes.
3736 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3737 if (GetParam() < kProtoSPDY31)
3738 return;
3740 const char kStreamUrl[] = "http://www.google.com/";
3742 const int32 msg_data_size = 100;
3743 const std::string msg_data(msg_data_size, 'a');
3745 MockConnect connect_data(SYNCHRONOUS, OK);
3747 scoped_ptr<SpdyFrame> req(
3748 spdy_util_.ConstructSpdyPost(
3749 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3750 MockWrite writes[] = {
3751 CreateMockWrite(*req, 0),
3754 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3755 MockRead reads[] = {
3756 CreateMockRead(*resp, 1),
3757 MockRead(ASYNC, 0, 2) // EOF
3760 // Create SpdySession and SpdyStream and send the request.
3761 DeterministicSocketData data(reads, arraysize(reads),
3762 writes, arraysize(writes));
3763 data.set_connect_data(connect_data);
3764 session_deps_.host_resolver->set_synchronous_mode(true);
3765 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3767 CreateDeterministicNetworkSession();
3769 base::WeakPtr<SpdySession> session =
3770 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3772 GURL url(kStreamUrl);
3773 base::WeakPtr<SpdyStream> stream =
3774 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3775 session, url, MEDIUM, BoundNetLog());
3776 ASSERT_TRUE(stream.get() != NULL);
3777 EXPECT_EQ(0u, stream->stream_id());
3779 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3780 stream->SetDelegate(&delegate);
3782 scoped_ptr<SpdyHeaderBlock> headers(
3783 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3784 EXPECT_EQ(ERR_IO_PENDING,
3785 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3786 EXPECT_TRUE(stream->HasUrlFromHeaders());
3788 const int32 initial_window_size =
3789 SpdySession::GetInitialWindowSize(GetParam());
3790 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3792 data.RunFor(1);
3794 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3796 data.RunFor(1);
3798 EXPECT_TRUE(data.at_write_eof());
3799 EXPECT_TRUE(data.at_read_eof());
3801 EXPECT_EQ(initial_window_size - msg_data_size,
3802 session->session_send_window_size_);
3804 // Closing the stream should increase the session's send window.
3805 stream->Close();
3806 EXPECT_EQ(NULL, stream.get());
3808 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3810 EXPECT_EQ(OK, delegate.WaitForClose());
3813 // Send data back and forth; the send and receive windows should
3814 // change appropriately.
3815 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
3816 if (GetParam() < kProtoSPDY31)
3817 return;
3819 const char kStreamUrl[] = "http://www.google.com/";
3821 const int32 msg_data_size = 100;
3822 const std::string msg_data(msg_data_size, 'a');
3824 MockConnect connect_data(SYNCHRONOUS, OK);
3826 scoped_ptr<SpdyFrame> req(
3827 spdy_util_.ConstructSpdyPost(
3828 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3829 scoped_ptr<SpdyFrame> msg(
3830 spdy_util_.ConstructSpdyBodyFrame(
3831 1, msg_data.data(), msg_data_size, false));
3832 MockWrite writes[] = {
3833 CreateMockWrite(*req, 0),
3834 CreateMockWrite(*msg, 2),
3837 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3838 scoped_ptr<SpdyFrame> echo(
3839 spdy_util_.ConstructSpdyBodyFrame(
3840 1, msg_data.data(), msg_data_size, false));
3841 scoped_ptr<SpdyFrame> window_update(
3842 spdy_util_.ConstructSpdyWindowUpdate(
3843 kSessionFlowControlStreamId, msg_data_size));
3844 MockRead reads[] = {
3845 CreateMockRead(*resp, 1),
3846 CreateMockRead(*echo, 3),
3847 CreateMockRead(*window_update, 4),
3848 MockRead(ASYNC, 0, 5) // EOF
3851 // Create SpdySession and SpdyStream and send the request.
3852 DeterministicSocketData data(reads, arraysize(reads),
3853 writes, arraysize(writes));
3854 data.set_connect_data(connect_data);
3855 session_deps_.host_resolver->set_synchronous_mode(true);
3856 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3858 CreateDeterministicNetworkSession();
3860 base::WeakPtr<SpdySession> session =
3861 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3863 GURL url(kStreamUrl);
3864 base::WeakPtr<SpdyStream> stream =
3865 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3866 session, url, MEDIUM, BoundNetLog());
3867 ASSERT_TRUE(stream.get() != NULL);
3868 EXPECT_EQ(0u, stream->stream_id());
3870 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3871 stream->SetDelegate(&delegate);
3873 scoped_ptr<SpdyHeaderBlock> headers(
3874 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3875 EXPECT_EQ(ERR_IO_PENDING,
3876 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3877 EXPECT_TRUE(stream->HasUrlFromHeaders());
3879 const int32 initial_window_size =
3880 SpdySession::GetInitialWindowSize(GetParam());
3881 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3882 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3883 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3885 data.RunFor(1);
3887 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3888 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3889 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3891 data.RunFor(1);
3893 EXPECT_EQ(initial_window_size - msg_data_size,
3894 session->session_send_window_size_);
3895 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3896 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3898 data.RunFor(1);
3900 EXPECT_EQ(initial_window_size - msg_data_size,
3901 session->session_send_window_size_);
3902 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3903 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3905 data.RunFor(1);
3907 EXPECT_EQ(initial_window_size - msg_data_size,
3908 session->session_send_window_size_);
3909 EXPECT_EQ(initial_window_size - msg_data_size,
3910 session->session_recv_window_size_);
3911 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3913 data.RunFor(1);
3915 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3916 EXPECT_EQ(initial_window_size - msg_data_size,
3917 session->session_recv_window_size_);
3918 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3920 EXPECT_TRUE(data.at_write_eof());
3921 EXPECT_TRUE(data.at_read_eof());
3923 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
3925 // Draining the delegate's read queue should increase the session's
3926 // receive window.
3927 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3928 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3929 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3931 stream->Close();
3932 EXPECT_EQ(NULL, stream.get());
3934 EXPECT_EQ(OK, delegate.WaitForClose());
3936 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3937 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3938 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3941 // Given a stall function and an unstall function, runs a test to make
3942 // sure that a stream resumes after unstall.
3943 void SpdySessionTest::RunResumeAfterUnstallTest(
3944 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
3945 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
3946 unstall_function) {
3947 const char kStreamUrl[] = "http://www.google.com/";
3948 GURL url(kStreamUrl);
3950 session_deps_.host_resolver->set_synchronous_mode(true);
3952 scoped_ptr<SpdyFrame> req(
3953 spdy_util_.ConstructSpdyPost(
3954 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3955 scoped_ptr<SpdyFrame> body(
3956 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3957 MockWrite writes[] = {
3958 CreateMockWrite(*req, 0),
3959 CreateMockWrite(*body, 1),
3962 scoped_ptr<SpdyFrame> resp(
3963 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3964 scoped_ptr<SpdyFrame> echo(
3965 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
3966 MockRead reads[] = {
3967 CreateMockRead(*resp, 2),
3968 MockRead(ASYNC, 0, 0, 3), // EOF
3971 DeterministicSocketData data(reads, arraysize(reads),
3972 writes, arraysize(writes));
3973 MockConnect connect_data(SYNCHRONOUS, OK);
3974 data.set_connect_data(connect_data);
3976 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3978 CreateDeterministicNetworkSession();
3979 base::WeakPtr<SpdySession> session =
3980 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3981 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3982 session->flow_control_state());
3984 base::WeakPtr<SpdyStream> stream =
3985 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3986 session, url, LOWEST, BoundNetLog());
3987 ASSERT_TRUE(stream.get() != NULL);
3989 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
3990 stream->SetDelegate(&delegate);
3992 EXPECT_FALSE(stream->HasUrlFromHeaders());
3993 EXPECT_FALSE(stream->send_stalled_by_flow_control());
3995 scoped_ptr<SpdyHeaderBlock> headers(
3996 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3997 EXPECT_EQ(ERR_IO_PENDING,
3998 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3999 EXPECT_TRUE(stream->HasUrlFromHeaders());
4000 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
4002 stall_function.Run(session.get(), stream.get());
4004 data.RunFor(1);
4006 EXPECT_TRUE(stream->send_stalled_by_flow_control());
4008 unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
4010 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4012 data.RunFor(3);
4014 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
4016 EXPECT_TRUE(delegate.send_headers_completed());
4017 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
4018 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
4019 EXPECT_TRUE(data.at_write_eof());
4022 // Run the resume-after-unstall test with all possible stall and
4023 // unstall sequences.
4025 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
4026 if (GetParam() < kProtoSPDY31)
4027 return;
4029 RunResumeAfterUnstallTest(
4030 base::Bind(&SpdySessionTest::StallSessionOnly,
4031 base::Unretained(this)),
4032 base::Bind(&SpdySessionTest::UnstallSessionOnly,
4033 base::Unretained(this)));
4036 // Equivalent to
4037 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4038 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
4039 if (GetParam() < kProtoSPDY31)
4040 return;
4042 RunResumeAfterUnstallTest(
4043 base::Bind(&SpdySessionTest::StallStreamOnly,
4044 base::Unretained(this)),
4045 base::Bind(&SpdySessionTest::UnstallStreamOnly,
4046 base::Unretained(this)));
4049 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4050 if (GetParam() < kProtoSPDY31)
4051 return;
4053 RunResumeAfterUnstallTest(
4054 base::Bind(&SpdySessionTest::StallSessionStream,
4055 base::Unretained(this)),
4056 base::Bind(&SpdySessionTest::UnstallSessionStream,
4057 base::Unretained(this)));
4060 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4061 if (GetParam() < kProtoSPDY31)
4062 return;
4064 RunResumeAfterUnstallTest(
4065 base::Bind(&SpdySessionTest::StallStreamSession,
4066 base::Unretained(this)),
4067 base::Bind(&SpdySessionTest::UnstallSessionStream,
4068 base::Unretained(this)));
4071 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4072 if (GetParam() < kProtoSPDY31)
4073 return;
4075 RunResumeAfterUnstallTest(
4076 base::Bind(&SpdySessionTest::StallStreamSession,
4077 base::Unretained(this)),
4078 base::Bind(&SpdySessionTest::UnstallStreamSession,
4079 base::Unretained(this)));
4082 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4083 if (GetParam() < kProtoSPDY31)
4084 return;
4086 RunResumeAfterUnstallTest(
4087 base::Bind(&SpdySessionTest::StallSessionStream,
4088 base::Unretained(this)),
4089 base::Bind(&SpdySessionTest::UnstallStreamSession,
4090 base::Unretained(this)));
4093 // Cause a stall by reducing the flow control send window to 0. The
4094 // streams should resume in priority order when that window is then
4095 // increased.
4096 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4097 if (GetParam() < kProtoSPDY31)
4098 return;
4100 const char kStreamUrl[] = "http://www.google.com/";
4101 GURL url(kStreamUrl);
4103 session_deps_.host_resolver->set_synchronous_mode(true);
4105 scoped_ptr<SpdyFrame> req1(
4106 spdy_util_.ConstructSpdyPost(
4107 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4108 scoped_ptr<SpdyFrame> req2(
4109 spdy_util_.ConstructSpdyPost(
4110 kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
4111 scoped_ptr<SpdyFrame> body1(
4112 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4113 scoped_ptr<SpdyFrame> body2(
4114 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4115 MockWrite writes[] = {
4116 CreateMockWrite(*req1, 0),
4117 CreateMockWrite(*req2, 1),
4118 CreateMockWrite(*body2, 2),
4119 CreateMockWrite(*body1, 3),
4122 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4123 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4124 MockRead reads[] = {
4125 CreateMockRead(*resp1, 4),
4126 CreateMockRead(*resp2, 5),
4127 MockRead(ASYNC, 0, 0, 6), // EOF
4130 DeterministicSocketData data(reads, arraysize(reads),
4131 writes, arraysize(writes));
4132 MockConnect connect_data(SYNCHRONOUS, OK);
4133 data.set_connect_data(connect_data);
4135 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4137 CreateDeterministicNetworkSession();
4138 base::WeakPtr<SpdySession> session =
4139 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4140 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4141 session->flow_control_state());
4143 base::WeakPtr<SpdyStream> stream1 =
4144 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4145 session, url, LOWEST, BoundNetLog());
4146 ASSERT_TRUE(stream1.get() != NULL);
4148 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4149 stream1->SetDelegate(&delegate1);
4151 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4153 base::WeakPtr<SpdyStream> stream2 =
4154 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4155 session, url, MEDIUM, BoundNetLog());
4156 ASSERT_TRUE(stream2.get() != NULL);
4158 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4159 stream2->SetDelegate(&delegate2);
4161 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4163 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4164 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4166 StallSessionSend(session.get());
4168 scoped_ptr<SpdyHeaderBlock> headers1(
4169 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4170 EXPECT_EQ(ERR_IO_PENDING,
4171 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4172 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4173 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4175 data.RunFor(1);
4176 EXPECT_EQ(1u, stream1->stream_id());
4177 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4179 scoped_ptr<SpdyHeaderBlock> headers2(
4180 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4181 EXPECT_EQ(ERR_IO_PENDING,
4182 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4183 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4184 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4186 data.RunFor(1);
4187 EXPECT_EQ(3u, stream2->stream_id());
4188 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4190 // This should unstall only stream2.
4191 UnstallSessionSend(session.get(), kBodyDataSize);
4193 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4194 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4196 data.RunFor(1);
4198 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4199 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4201 // This should then unstall stream1.
4202 UnstallSessionSend(session.get(), kBodyDataSize);
4204 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4205 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4207 data.RunFor(4);
4209 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4210 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4212 EXPECT_TRUE(delegate1.send_headers_completed());
4213 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4214 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4216 EXPECT_TRUE(delegate2.send_headers_completed());
4217 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4218 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4220 EXPECT_TRUE(data.at_write_eof());
4223 // Delegate that closes a given stream after sending its body.
4224 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4225 public:
4226 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4227 base::StringPiece data)
4228 : StreamDelegateWithBody(stream, data) {}
4230 ~StreamClosingDelegate() override {}
4232 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4233 stream_to_close_ = stream_to_close;
4236 void OnDataSent() override {
4237 test::StreamDelegateWithBody::OnDataSent();
4238 if (stream_to_close_.get()) {
4239 stream_to_close_->Close();
4240 EXPECT_EQ(NULL, stream_to_close_.get());
4244 private:
4245 base::WeakPtr<SpdyStream> stream_to_close_;
4248 // Cause a stall by reducing the flow control send window to
4249 // 0. Unstalling the session should properly handle deleted streams.
4250 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4251 if (GetParam() < kProtoSPDY31)
4252 return;
4254 const char kStreamUrl[] = "http://www.google.com/";
4255 GURL url(kStreamUrl);
4257 session_deps_.host_resolver->set_synchronous_mode(true);
4259 scoped_ptr<SpdyFrame> req1(
4260 spdy_util_.ConstructSpdyPost(
4261 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4262 scoped_ptr<SpdyFrame> req2(
4263 spdy_util_.ConstructSpdyPost(
4264 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4265 scoped_ptr<SpdyFrame> req3(
4266 spdy_util_.ConstructSpdyPost(
4267 kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
4268 scoped_ptr<SpdyFrame> body2(
4269 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4270 MockWrite writes[] = {
4271 CreateMockWrite(*req1, 0),
4272 CreateMockWrite(*req2, 1),
4273 CreateMockWrite(*req3, 2),
4274 CreateMockWrite(*body2, 3),
4277 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4278 MockRead reads[] = {
4279 CreateMockRead(*resp2, 4),
4280 MockRead(ASYNC, 0, 0, 5), // EOF
4283 DeterministicSocketData data(reads, arraysize(reads),
4284 writes, arraysize(writes));
4285 MockConnect connect_data(SYNCHRONOUS, OK);
4286 data.set_connect_data(connect_data);
4288 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4290 CreateDeterministicNetworkSession();
4291 base::WeakPtr<SpdySession> session =
4292 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4293 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4294 session->flow_control_state());
4296 base::WeakPtr<SpdyStream> stream1 =
4297 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4298 session, url, LOWEST, BoundNetLog());
4299 ASSERT_TRUE(stream1.get() != NULL);
4301 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4302 stream1->SetDelegate(&delegate1);
4304 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4306 base::WeakPtr<SpdyStream> stream2 =
4307 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4308 session, url, LOWEST, BoundNetLog());
4309 ASSERT_TRUE(stream2.get() != NULL);
4311 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4312 stream2->SetDelegate(&delegate2);
4314 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4316 base::WeakPtr<SpdyStream> stream3 =
4317 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4318 session, url, LOWEST, BoundNetLog());
4319 ASSERT_TRUE(stream3.get() != NULL);
4321 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4322 stream3->SetDelegate(&delegate3);
4324 EXPECT_FALSE(stream3->HasUrlFromHeaders());
4326 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4327 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4328 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4330 StallSessionSend(session.get());
4332 scoped_ptr<SpdyHeaderBlock> headers1(
4333 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4334 EXPECT_EQ(ERR_IO_PENDING,
4335 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4336 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4337 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4339 data.RunFor(1);
4340 EXPECT_EQ(1u, stream1->stream_id());
4341 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4343 scoped_ptr<SpdyHeaderBlock> headers2(
4344 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4345 EXPECT_EQ(ERR_IO_PENDING,
4346 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4347 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4348 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4350 data.RunFor(1);
4351 EXPECT_EQ(3u, stream2->stream_id());
4352 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4354 scoped_ptr<SpdyHeaderBlock> headers3(
4355 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4356 EXPECT_EQ(ERR_IO_PENDING,
4357 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4358 EXPECT_TRUE(stream3->HasUrlFromHeaders());
4359 EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4361 data.RunFor(1);
4362 EXPECT_EQ(5u, stream3->stream_id());
4363 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4365 SpdyStreamId stream_id1 = stream1->stream_id();
4366 SpdyStreamId stream_id2 = stream2->stream_id();
4367 SpdyStreamId stream_id3 = stream3->stream_id();
4369 // Close stream1 preemptively.
4370 session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4371 EXPECT_EQ(NULL, stream1.get());
4373 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4374 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4375 EXPECT_TRUE(session->IsStreamActive(stream_id3));
4377 // Unstall stream2, which should then close stream3.
4378 delegate2.set_stream_to_close(stream3);
4379 UnstallSessionSend(session.get(), kBodyDataSize);
4381 data.RunFor(1);
4382 EXPECT_EQ(NULL, stream3.get());
4384 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4385 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4386 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4387 EXPECT_FALSE(session->IsStreamActive(stream_id3));
4389 data.RunFor(2);
4390 EXPECT_EQ(NULL, stream2.get());
4392 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4393 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4394 EXPECT_EQ(OK, delegate3.WaitForClose());
4396 EXPECT_TRUE(delegate1.send_headers_completed());
4397 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4399 EXPECT_TRUE(delegate2.send_headers_completed());
4400 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4401 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4403 EXPECT_TRUE(delegate3.send_headers_completed());
4404 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4406 EXPECT_TRUE(data.at_write_eof());
4409 // Cause a stall by reducing the flow control send window to
4410 // 0. Unstalling the session should properly handle the session itself
4411 // being closed.
4412 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4413 if (GetParam() < kProtoSPDY31)
4414 return;
4416 const char kStreamUrl[] = "http://www.google.com/";
4417 GURL url(kStreamUrl);
4419 session_deps_.host_resolver->set_synchronous_mode(true);
4421 scoped_ptr<SpdyFrame> req1(
4422 spdy_util_.ConstructSpdyPost(
4423 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4424 scoped_ptr<SpdyFrame> req2(
4425 spdy_util_.ConstructSpdyPost(
4426 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4427 scoped_ptr<SpdyFrame> body1(
4428 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4429 MockWrite writes[] = {
4430 CreateMockWrite(*req1, 0),
4431 CreateMockWrite(*req2, 1),
4434 MockRead reads[] = {
4435 MockRead(ASYNC, 0, 0, 2), // EOF
4438 DeterministicSocketData data(reads, arraysize(reads),
4439 writes, arraysize(writes));
4440 MockConnect connect_data(SYNCHRONOUS, OK);
4441 data.set_connect_data(connect_data);
4443 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4445 CreateDeterministicNetworkSession();
4446 base::WeakPtr<SpdySession> session =
4447 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4448 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4449 session->flow_control_state());
4451 base::WeakPtr<SpdyStream> stream1 =
4452 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4453 session, url, LOWEST, BoundNetLog());
4454 ASSERT_TRUE(stream1.get() != NULL);
4456 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4457 stream1->SetDelegate(&delegate1);
4459 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4461 base::WeakPtr<SpdyStream> stream2 =
4462 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4463 session, url, LOWEST, BoundNetLog());
4464 ASSERT_TRUE(stream2.get() != NULL);
4466 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4467 stream2->SetDelegate(&delegate2);
4469 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4471 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4472 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4474 StallSessionSend(session.get());
4476 scoped_ptr<SpdyHeaderBlock> headers1(
4477 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4478 EXPECT_EQ(ERR_IO_PENDING,
4479 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4480 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4481 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4483 data.RunFor(1);
4484 EXPECT_EQ(1u, stream1->stream_id());
4485 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4487 scoped_ptr<SpdyHeaderBlock> headers2(
4488 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4489 EXPECT_EQ(ERR_IO_PENDING,
4490 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4491 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4492 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4494 data.RunFor(1);
4495 EXPECT_EQ(3u, stream2->stream_id());
4496 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4498 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4500 // Unstall stream1.
4501 UnstallSessionSend(session.get(), kBodyDataSize);
4503 // Close the session (since we can't do it from within the delegate
4504 // method, since it's in the stream's loop).
4505 session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4506 base::RunLoop().RunUntilIdle();
4507 EXPECT_TRUE(session == NULL);
4509 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4511 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4512 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4514 EXPECT_TRUE(delegate1.send_headers_completed());
4515 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4517 EXPECT_TRUE(delegate2.send_headers_completed());
4518 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4520 EXPECT_TRUE(data.at_write_eof());
4523 TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4524 if (GetParam() < kProtoSPDY31)
4525 return;
4527 MockConnect connect_data(SYNCHRONOUS, OK);
4529 scoped_ptr<SpdyFrame> req(
4530 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4531 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4533 GOAWAY_FLOW_CONTROL_ERROR,
4534 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4535 "the receive window size of 1"));
4536 MockWrite writes[] = {
4537 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
4540 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4541 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4542 MockRead reads[] = {
4543 CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
4546 DeterministicSocketData data(
4547 reads, arraysize(reads), writes, arraysize(writes));
4548 data.set_connect_data(connect_data);
4549 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4551 CreateDeterministicNetworkSession();
4553 base::WeakPtr<SpdySession> session =
4554 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4556 GURL url(kDefaultURL);
4557 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4558 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
4559 ASSERT_TRUE(spdy_stream.get() != NULL);
4560 test::StreamDelegateDoNothing delegate(spdy_stream);
4561 spdy_stream->SetDelegate(&delegate);
4563 scoped_ptr<SpdyHeaderBlock> headers(
4564 spdy_util_.ConstructGetHeaderBlock(url.spec()));
4565 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4567 data.RunFor(1); // Write request.
4569 // Put session on the edge of overflowing it's recv window.
4570 session->session_recv_window_size_ = 1;
4572 // Read response headers & body. Body overflows the session window, and a
4573 // goaway is written.
4574 data.RunFor(3);
4575 base::MessageLoop::current()->RunUntilIdle();
4577 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4578 EXPECT_TRUE(session == NULL);
4581 TEST_P(SpdySessionTest, SplitHeaders) {
4582 GURL kStreamUrl("http://www.google.com/foo.dat");
4583 SpdyHeaderBlock headers;
4584 spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4585 headers["alpha"] = "beta";
4587 SpdyHeaderBlock request_headers;
4588 SpdyHeaderBlock response_headers;
4590 SplitPushedHeadersToRequestAndResponse(
4591 headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4593 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4594 std::string alpha_val =
4595 (it == response_headers.end()) ? std::string() : it->second;
4596 EXPECT_EQ("beta", alpha_val);
4598 GURL request_url =
4599 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4600 EXPECT_EQ(kStreamUrl, request_url);
4603 // Regression. Sorta. Push streams and client streams were sharing a single
4604 // limit for a long time.
4605 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4606 SettingsMap new_settings;
4607 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4608 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4609 scoped_ptr<SpdyFrame> settings_frame(
4610 spdy_util_.ConstructSpdySettings(new_settings));
4611 scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4612 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4613 MockRead reads[] = {
4614 CreateMockRead(*settings_frame), CreateMockRead(*pushed, 3),
4615 MockRead(ASYNC, 0, 4),
4618 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4619 scoped_ptr<SpdyFrame> req(
4620 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4621 MockWrite writes[] = {
4622 CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4625 DeterministicSocketData data(
4626 reads, arraysize(reads), writes, arraysize(writes));
4627 MockConnect connect_data(SYNCHRONOUS, OK);
4628 data.set_connect_data(connect_data);
4629 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4631 CreateDeterministicNetworkSession();
4633 base::WeakPtr<SpdySession> session =
4634 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4636 // Read the settings frame.
4637 data.RunFor(1);
4639 GURL url1(kDefaultURL);
4640 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4641 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4642 ASSERT_TRUE(spdy_stream1.get() != NULL);
4643 EXPECT_EQ(0u, spdy_stream1->stream_id());
4644 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4645 spdy_stream1->SetDelegate(&delegate1);
4647 EXPECT_EQ(0u, session->num_active_streams());
4648 EXPECT_EQ(1u, session->num_created_streams());
4649 EXPECT_EQ(0u, session->num_pushed_streams());
4650 EXPECT_EQ(0u, session->num_active_pushed_streams());
4652 scoped_ptr<SpdyHeaderBlock> headers(
4653 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4654 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4655 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4657 // Run until 1st stream is activated.
4658 EXPECT_EQ(0u, delegate1.stream_id());
4659 data.RunFor(2);
4660 EXPECT_EQ(1u, delegate1.stream_id());
4661 EXPECT_EQ(1u, session->num_active_streams());
4662 EXPECT_EQ(0u, session->num_created_streams());
4663 EXPECT_EQ(0u, session->num_pushed_streams());
4664 EXPECT_EQ(0u, session->num_active_pushed_streams());
4666 // Run until pushed stream is created.
4667 data.RunFor(1);
4668 EXPECT_EQ(2u, session->num_active_streams());
4669 EXPECT_EQ(0u, session->num_created_streams());
4670 EXPECT_EQ(1u, session->num_pushed_streams());
4671 EXPECT_EQ(1u, session->num_active_pushed_streams());
4673 // Second stream should not be stalled, although we have 2 active streams, but
4674 // one of them is push stream and should not be taken into account when we
4675 // create streams on the client.
4676 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4677 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4678 EXPECT_TRUE(spdy_stream2.get() != NULL);
4679 EXPECT_EQ(2u, session->num_active_streams());
4680 EXPECT_EQ(1u, session->num_created_streams());
4681 EXPECT_EQ(1u, session->num_pushed_streams());
4682 EXPECT_EQ(1u, session->num_active_pushed_streams());
4684 // Read EOF.
4685 data.RunFor(1);
4688 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4689 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4690 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4691 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4692 NULL, 0, 4, 1, "http://www.google.com/b.dat"));
4693 MockRead reads[] = {
4694 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4695 MockRead(ASYNC, 0, 4),
4698 scoped_ptr<SpdyFrame> req(
4699 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4700 scoped_ptr<SpdyFrame> rst(
4701 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4702 MockWrite writes[] = {
4703 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4706 DeterministicSocketData data(
4707 reads, arraysize(reads), writes, arraysize(writes));
4708 MockConnect connect_data(SYNCHRONOUS, OK);
4709 data.set_connect_data(connect_data);
4710 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4712 CreateDeterministicNetworkSession();
4714 base::WeakPtr<SpdySession> session =
4715 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4716 session->set_max_concurrent_pushed_streams(1);
4718 GURL url1(kDefaultURL);
4719 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4720 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4721 ASSERT_TRUE(spdy_stream1.get() != NULL);
4722 EXPECT_EQ(0u, spdy_stream1->stream_id());
4723 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4724 spdy_stream1->SetDelegate(&delegate1);
4726 EXPECT_EQ(0u, session->num_active_streams());
4727 EXPECT_EQ(1u, session->num_created_streams());
4728 EXPECT_EQ(0u, session->num_pushed_streams());
4729 EXPECT_EQ(0u, session->num_active_pushed_streams());
4731 scoped_ptr<SpdyHeaderBlock> headers(
4732 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4733 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4734 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4736 // Run until 1st stream is activated.
4737 EXPECT_EQ(0u, delegate1.stream_id());
4738 data.RunFor(1);
4739 EXPECT_EQ(1u, delegate1.stream_id());
4740 EXPECT_EQ(1u, session->num_active_streams());
4741 EXPECT_EQ(0u, session->num_created_streams());
4742 EXPECT_EQ(0u, session->num_pushed_streams());
4743 EXPECT_EQ(0u, session->num_active_pushed_streams());
4745 // Run until pushed stream is created.
4746 data.RunFor(1);
4747 EXPECT_EQ(2u, session->num_active_streams());
4748 EXPECT_EQ(0u, session->num_created_streams());
4749 EXPECT_EQ(1u, session->num_pushed_streams());
4750 EXPECT_EQ(1u, session->num_active_pushed_streams());
4752 // Reset incoming pushed stream.
4753 data.RunFor(2);
4754 EXPECT_EQ(2u, session->num_active_streams());
4755 EXPECT_EQ(0u, session->num_created_streams());
4756 EXPECT_EQ(1u, session->num_pushed_streams());
4757 EXPECT_EQ(1u, session->num_active_pushed_streams());
4759 // Read EOF.
4760 data.RunFor(1);
4763 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4764 // Streams in reserved remote state exist only in SPDY4.
4765 if (spdy_util_.spdy_version() < SPDY4)
4766 return;
4768 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4769 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4770 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4771 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
4772 push_headers.get());
4773 scoped_ptr<SpdyFrame> push_b(
4774 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4775 scoped_ptr<SpdyFrame> headers_b(
4776 spdy_util_.ConstructSpdyPushHeaders(4, NULL, 0));
4777 MockRead reads[] = {
4778 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4779 CreateMockRead(*headers_b, 3), MockRead(ASYNC, 0, 5),
4782 scoped_ptr<SpdyFrame> req(
4783 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4784 scoped_ptr<SpdyFrame> rst(
4785 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4786 MockWrite writes[] = {
4787 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
4790 DeterministicSocketData data(
4791 reads, arraysize(reads), writes, arraysize(writes));
4792 MockConnect connect_data(SYNCHRONOUS, OK);
4793 data.set_connect_data(connect_data);
4794 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4796 CreateDeterministicNetworkSession();
4798 base::WeakPtr<SpdySession> session =
4799 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4800 session->set_max_concurrent_pushed_streams(1);
4802 GURL url1(kDefaultURL);
4803 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4804 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4805 ASSERT_TRUE(spdy_stream1.get() != NULL);
4806 EXPECT_EQ(0u, spdy_stream1->stream_id());
4807 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4808 spdy_stream1->SetDelegate(&delegate1);
4810 EXPECT_EQ(0u, session->num_active_streams());
4811 EXPECT_EQ(1u, session->num_created_streams());
4812 EXPECT_EQ(0u, session->num_pushed_streams());
4813 EXPECT_EQ(0u, session->num_active_pushed_streams());
4815 scoped_ptr<SpdyHeaderBlock> headers(
4816 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4817 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4818 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4820 // Run until 1st stream is activated.
4821 EXPECT_EQ(0u, delegate1.stream_id());
4822 data.RunFor(1);
4823 EXPECT_EQ(1u, delegate1.stream_id());
4824 EXPECT_EQ(1u, session->num_active_streams());
4825 EXPECT_EQ(0u, session->num_created_streams());
4826 EXPECT_EQ(0u, session->num_pushed_streams());
4827 EXPECT_EQ(0u, session->num_active_pushed_streams());
4829 // Run until pushed stream is created.
4830 data.RunFor(1);
4831 EXPECT_EQ(2u, session->num_active_streams());
4832 EXPECT_EQ(0u, session->num_created_streams());
4833 EXPECT_EQ(1u, session->num_pushed_streams());
4834 EXPECT_EQ(1u, session->num_active_pushed_streams());
4836 // Accept promised stream. It should not count towards pushed stream limit.
4837 data.RunFor(1);
4838 EXPECT_EQ(3u, session->num_active_streams());
4839 EXPECT_EQ(0u, session->num_created_streams());
4840 EXPECT_EQ(2u, session->num_pushed_streams());
4841 EXPECT_EQ(1u, session->num_active_pushed_streams());
4843 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4844 // while we accept only one.
4845 data.RunFor(2);
4846 EXPECT_EQ(2u, session->num_active_streams());
4847 EXPECT_EQ(0u, session->num_created_streams());
4848 EXPECT_EQ(1u, session->num_pushed_streams());
4849 EXPECT_EQ(1u, session->num_active_pushed_streams());
4851 // Read EOF.
4852 data.RunFor(1);
4855 TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
4856 // Streams in reserved remote state exist only in SPDY4.
4857 if (spdy_util_.spdy_version() < SPDY4)
4858 return;
4860 const char kPushedUrl[] = "http://www.google.com/a.dat";
4861 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4862 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
4863 scoped_ptr<SpdyFrame> push_promise(
4864 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
4865 scoped_ptr<SpdyFrame> headers_frame(
4866 spdy_util_.ConstructSpdyPushHeaders(2, NULL, 0));
4867 MockRead reads[] = {
4868 CreateMockRead(*push_promise, 1), CreateMockRead(*headers_frame, 2),
4869 MockRead(ASYNC, 0, 4),
4872 scoped_ptr<SpdyFrame> req(
4873 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4874 scoped_ptr<SpdyFrame> rst(
4875 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
4876 MockWrite writes[] = {
4877 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4880 DeterministicSocketData data(
4881 reads, arraysize(reads), writes, arraysize(writes));
4882 MockConnect connect_data(SYNCHRONOUS, OK);
4883 data.set_connect_data(connect_data);
4884 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4886 CreateDeterministicNetworkSession();
4888 base::WeakPtr<SpdySession> session =
4889 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4891 GURL url1(kDefaultURL);
4892 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4893 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4894 ASSERT_TRUE(spdy_stream1.get() != NULL);
4895 EXPECT_EQ(0u, spdy_stream1->stream_id());
4896 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4897 spdy_stream1->SetDelegate(&delegate1);
4899 EXPECT_EQ(0u, session->num_active_streams());
4900 EXPECT_EQ(1u, session->num_created_streams());
4901 EXPECT_EQ(0u, session->num_pushed_streams());
4902 EXPECT_EQ(0u, session->num_active_pushed_streams());
4904 scoped_ptr<SpdyHeaderBlock> headers(
4905 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4906 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4907 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4909 // Run until 1st stream is activated.
4910 EXPECT_EQ(0u, delegate1.stream_id());
4911 data.RunFor(1);
4912 EXPECT_EQ(1u, delegate1.stream_id());
4913 EXPECT_EQ(1u, session->num_active_streams());
4914 EXPECT_EQ(0u, session->num_created_streams());
4915 EXPECT_EQ(0u, session->num_pushed_streams());
4916 EXPECT_EQ(0u, session->num_active_pushed_streams());
4918 // Run until pushed stream is created.
4919 data.RunFor(1);
4920 EXPECT_EQ(2u, session->num_active_streams());
4921 EXPECT_EQ(0u, session->num_created_streams());
4922 EXPECT_EQ(1u, session->num_pushed_streams());
4923 EXPECT_EQ(0u, session->num_active_pushed_streams());
4925 base::WeakPtr<SpdyStream> pushed_stream;
4926 int rv =
4927 session->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
4928 ASSERT_EQ(OK, rv);
4929 ASSERT_TRUE(pushed_stream.get() != NULL);
4930 test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
4931 pushed_stream->SetDelegate(&delegate2);
4933 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4934 // that all our counters are in consistent state.
4935 data.RunFor(1);
4936 EXPECT_EQ(1u, session->num_active_streams());
4937 EXPECT_EQ(0u, session->num_created_streams());
4938 EXPECT_EQ(0u, session->num_pushed_streams());
4939 EXPECT_EQ(0u, session->num_active_pushed_streams());
4941 // Read EOF.
4942 data.RunFor(2);
4945 TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
4946 session_deps_.host_resolver->set_synchronous_mode(true);
4948 MockRead reads[] = {
4949 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
4952 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
4954 MockConnect connect_data(SYNCHRONOUS, OK);
4955 data.set_connect_data(connect_data);
4956 session_deps_.socket_factory->AddSocketDataProvider(&data);
4958 CreateNetworkSession();
4959 base::WeakPtr<SpdySession> session =
4960 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4962 session->stream_hi_water_mark_ = 5;
4963 // Low client (odd) ids are fine.
4964 EXPECT_TRUE(session->OnUnknownFrame(3, 0));
4965 // Client id exceeding watermark.
4966 EXPECT_FALSE(session->OnUnknownFrame(9, 0));
4968 session->last_accepted_push_stream_id_ = 6;
4969 // Low server (even) ids are fine.
4970 EXPECT_TRUE(session->OnUnknownFrame(2, 0));
4971 // Server id exceeding last accepted id.
4972 EXPECT_FALSE(session->OnUnknownFrame(8, 0));
4975 TEST(MapFramerErrorToProtocolError, MapsValues) {
4976 CHECK_EQ(
4977 SPDY_ERROR_INVALID_CONTROL_FRAME,
4978 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4979 CHECK_EQ(
4980 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4981 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4982 CHECK_EQ(
4983 SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
4984 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
4985 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
4986 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
4989 TEST(MapFramerErrorToNetError, MapsValue) {
4990 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
4991 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4992 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4993 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
4994 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4995 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4996 CHECK_EQ(
4997 ERR_SPDY_FRAME_SIZE_ERROR,
4998 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
5001 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
5002 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
5003 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
5004 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
5005 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
5006 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
5007 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
5008 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY,
5009 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY));
5010 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED,
5011 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED));
5014 TEST(MapNetErrorToGoAwayStatus, MapsValue) {
5015 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
5016 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
5017 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
5018 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
5019 CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
5020 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
5021 CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
5022 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
5023 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
5024 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
5025 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
5028 TEST(CanPoolTest, CanPool) {
5029 // Load a cert that is valid for:
5030 // www.example.org
5031 // mail.example.org
5032 // www.example.com
5034 TransportSecurityState tss;
5035 SSLInfo ssl_info;
5036 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5037 "spdy_pooling.pem");
5039 EXPECT_TRUE(SpdySession::CanPool(
5040 &tss, ssl_info, "www.example.org", "www.example.org"));
5041 EXPECT_TRUE(SpdySession::CanPool(
5042 &tss, ssl_info, "www.example.org", "mail.example.org"));
5043 EXPECT_TRUE(SpdySession::CanPool(
5044 &tss, ssl_info, "www.example.org", "mail.example.com"));
5045 EXPECT_FALSE(SpdySession::CanPool(
5046 &tss, ssl_info, "www.example.org", "mail.google.com"));
5049 TEST(CanPoolTest, CanNotPoolWithCertErrors) {
5050 // Load a cert that is valid for:
5051 // www.example.org
5052 // mail.example.org
5053 // www.example.com
5055 TransportSecurityState tss;
5056 SSLInfo ssl_info;
5057 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5058 "spdy_pooling.pem");
5059 ssl_info.cert_status = CERT_STATUS_REVOKED;
5061 EXPECT_FALSE(SpdySession::CanPool(
5062 &tss, ssl_info, "www.example.org", "mail.example.org"));
5065 TEST(CanPoolTest, CanNotPoolWithClientCerts) {
5066 // Load a cert that is valid for:
5067 // www.example.org
5068 // mail.example.org
5069 // www.example.com
5071 TransportSecurityState tss;
5072 SSLInfo ssl_info;
5073 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5074 "spdy_pooling.pem");
5075 ssl_info.client_cert_sent = true;
5077 EXPECT_FALSE(SpdySession::CanPool(
5078 &tss, ssl_info, "www.example.org", "mail.example.org"));
5081 TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
5082 // Load a cert that is valid for:
5083 // www.example.org
5084 // mail.example.org
5085 // www.example.com
5087 TransportSecurityState tss;
5088 SSLInfo ssl_info;
5089 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5090 "spdy_pooling.pem");
5091 ssl_info.channel_id_sent = true;
5093 EXPECT_TRUE(SpdySession::CanPool(
5094 &tss, ssl_info, "www.example.org", "mail.example.org"));
5095 EXPECT_FALSE(SpdySession::CanPool(
5096 &tss, ssl_info, "www.example.org", "www.example.com"));
5099 TEST(CanPoolTest, CanNotPoolWithBadPins) {
5100 uint8 primary_pin = 1;
5101 uint8 backup_pin = 2;
5102 uint8 bad_pin = 3;
5103 TransportSecurityState tss;
5104 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5106 SSLInfo ssl_info;
5107 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5108 "spdy_pooling.pem");
5109 ssl_info.is_issued_by_known_root = true;
5110 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
5112 EXPECT_FALSE(SpdySession::CanPool(
5113 &tss, ssl_info, "www.example.org", "mail.example.org"));
5116 TEST(CanPoolTest, CanPoolWithAcceptablePins) {
5117 uint8 primary_pin = 1;
5118 uint8 backup_pin = 2;
5119 TransportSecurityState tss;
5120 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5122 SSLInfo ssl_info;
5123 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5124 "spdy_pooling.pem");
5125 ssl_info.is_issued_by_known_root = true;
5126 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
5128 EXPECT_TRUE(SpdySession::CanPool(
5129 &tss, ssl_info, "www.example.org", "mail.example.org"));
5132 } // namespace net