Roll src/third_party/skia f16c00e:f89f60f
[chromium-blink-merge.git] / net / spdy / spdy_session_unittest.cc
blobba3cb611ac849157ca10ea0a9d55b01820ad6239
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_SPDY_SESSION_INITIALIZED correctly.
1655 int pos = net::ExpectLogContainsSomewhere(
1656 entries, 0,
1657 net::NetLog::TYPE_SPDY_SESSION_INITIALIZED,
1658 net::NetLog::PHASE_NONE);
1659 EXPECT_LT(0, pos);
1661 CapturingNetLog::CapturedEntry entry = entries[pos];
1662 NetLog::Source socket_source;
1663 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1664 &socket_source));
1665 EXPECT_TRUE(socket_source.IsValid());
1666 EXPECT_NE(log.bound().source().id, socket_source.id);
1669 TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
1670 session_deps_.host_resolver->set_synchronous_mode(true);
1672 MockConnect connect_data(SYNCHRONOUS, OK);
1673 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
1674 MockRead reads[] = {
1675 CreateMockRead(*goaway),
1676 MockRead(SYNCHRONOUS, 0, 0) // EOF
1679 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1680 data.set_connect_data(connect_data);
1681 session_deps_.socket_factory->AddSocketDataProvider(&data);
1683 CreateNetworkSession();
1685 CapturingBoundNetLog log;
1686 base::WeakPtr<SpdySession> session =
1687 CreateInsecureSpdySession(http_session_, key_, log.bound());
1688 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1690 // Flush the read completion task.
1691 base::MessageLoop::current()->RunUntilIdle();
1693 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1694 EXPECT_TRUE(session == NULL);
1696 // Check that the NetLog was filled reasonably.
1697 net::CapturingNetLog::CapturedEntryList entries;
1698 log.GetEntries(&entries);
1699 EXPECT_LT(0u, entries.size());
1701 // Check that we logged SPDY_SESSION_CLOSE correctly.
1702 int pos = net::ExpectLogContainsSomewhere(
1703 entries, 0,
1704 net::NetLog::TYPE_SPDY_SESSION_CLOSE,
1705 net::NetLog::PHASE_NONE);
1707 if (pos < static_cast<int>(entries.size())) {
1708 CapturingNetLog::CapturedEntry entry = entries[pos];
1709 int error_code = 0;
1710 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1711 EXPECT_EQ(OK, error_code);
1712 } else {
1713 ADD_FAILURE();
1717 TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1718 session_deps_.host_resolver->set_synchronous_mode(true);
1720 MockConnect connect_data(SYNCHRONOUS, OK);
1721 MockRead reads[] = {
1722 MockRead(SYNCHRONOUS, 0, 0) // EOF
1725 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1726 data.set_connect_data(connect_data);
1727 session_deps_.socket_factory->AddSocketDataProvider(&data);
1729 CreateNetworkSession();
1731 CapturingBoundNetLog log;
1732 base::WeakPtr<SpdySession> session =
1733 CreateInsecureSpdySession(http_session_, key_, log.bound());
1734 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1736 // Flush the read completion task.
1737 base::MessageLoop::current()->RunUntilIdle();
1739 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1740 EXPECT_TRUE(session == NULL);
1742 // Check that the NetLog was filled reasonably.
1743 net::CapturingNetLog::CapturedEntryList entries;
1744 log.GetEntries(&entries);
1745 EXPECT_LT(0u, entries.size());
1747 // Check that we logged SPDY_SESSION_CLOSE correctly.
1748 int pos =
1749 net::ExpectLogContainsSomewhere(entries,
1751 net::NetLog::TYPE_SPDY_SESSION_CLOSE,
1752 net::NetLog::PHASE_NONE);
1754 if (pos < static_cast<int>(entries.size())) {
1755 CapturingNetLog::CapturedEntry entry = entries[pos];
1756 int error_code = 0;
1757 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1758 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1759 } else {
1760 ADD_FAILURE();
1764 TEST_P(SpdySessionTest, SynCompressionHistograms) {
1765 session_deps_.enable_compression = true;
1767 scoped_ptr<SpdyFrame> req(
1768 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, MEDIUM, true));
1769 MockWrite writes[] = {
1770 CreateMockWrite(*req, 0),
1772 MockRead reads[] = {
1773 MockRead(ASYNC, 0, 1) // EOF
1775 DeterministicSocketData data(reads, arraysize(reads),
1776 writes, arraysize(writes));
1777 MockConnect connect_data(SYNCHRONOUS, OK);
1778 data.set_connect_data(connect_data);
1779 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1781 CreateDeterministicNetworkSession();
1782 base::WeakPtr<SpdySession> session =
1783 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1785 GURL url(kDefaultURL);
1786 base::WeakPtr<SpdyStream> spdy_stream =
1787 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1788 session, url, MEDIUM, BoundNetLog());
1789 test::StreamDelegateDoNothing delegate(spdy_stream);
1790 spdy_stream->SetDelegate(&delegate);
1792 scoped_ptr<SpdyHeaderBlock> headers(
1793 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1794 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1795 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1797 // Write request headers & capture resulting histogram update.
1798 base::HistogramTester histogram_tester;
1800 data.RunFor(1);
1801 // Regression test of compression performance under the request fixture.
1802 switch (spdy_util_.spdy_version()) {
1803 case SPDY3:
1804 histogram_tester.ExpectBucketCount(
1805 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1806 break;
1807 case SPDY4:
1808 histogram_tester.ExpectBucketCount(
1809 "Net.SpdySynStreamCompressionPercentage", 82, 1);
1810 break;
1811 default:
1812 NOTREACHED();
1815 // Read and process EOF.
1816 data.RunFor(1);
1817 base::MessageLoop::current()->RunUntilIdle();
1818 EXPECT_TRUE(session == NULL);
1821 // Queue up a low-priority SYN_STREAM followed by a high-priority
1822 // one. The high priority one should still send first and receive
1823 // first.
1824 TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1825 // Construct the request.
1826 MockConnect connect_data(SYNCHRONOUS, OK);
1827 scoped_ptr<SpdyFrame> req_highest(
1828 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true));
1829 scoped_ptr<SpdyFrame> req_lowest(
1830 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1831 MockWrite writes[] = {
1832 CreateMockWrite(*req_highest, 0),
1833 CreateMockWrite(*req_lowest, 1),
1836 scoped_ptr<SpdyFrame> resp_highest(
1837 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1838 scoped_ptr<SpdyFrame> body_highest(
1839 spdy_util_.ConstructSpdyBodyFrame(1, true));
1840 scoped_ptr<SpdyFrame> resp_lowest(
1841 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1842 scoped_ptr<SpdyFrame> body_lowest(
1843 spdy_util_.ConstructSpdyBodyFrame(3, true));
1844 MockRead reads[] = {
1845 CreateMockRead(*resp_highest, 2),
1846 CreateMockRead(*body_highest, 3),
1847 CreateMockRead(*resp_lowest, 4),
1848 CreateMockRead(*body_lowest, 5),
1849 MockRead(ASYNC, 0, 6) // EOF
1852 session_deps_.host_resolver->set_synchronous_mode(true);
1854 DeterministicSocketData data(reads, arraysize(reads),
1855 writes, arraysize(writes));
1856 data.set_connect_data(connect_data);
1857 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1859 CreateDeterministicNetworkSession();
1861 base::WeakPtr<SpdySession> session =
1862 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1864 GURL url(kDefaultURL);
1866 base::WeakPtr<SpdyStream> spdy_stream_lowest =
1867 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1868 session, url, LOWEST, BoundNetLog());
1869 ASSERT_TRUE(spdy_stream_lowest);
1870 EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1871 test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1872 spdy_stream_lowest->SetDelegate(&delegate_lowest);
1874 base::WeakPtr<SpdyStream> spdy_stream_highest =
1875 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1876 session, url, HIGHEST, BoundNetLog());
1877 ASSERT_TRUE(spdy_stream_highest);
1878 EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1879 test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1880 spdy_stream_highest->SetDelegate(&delegate_highest);
1882 // Queue the lower priority one first.
1884 scoped_ptr<SpdyHeaderBlock> headers_lowest(
1885 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1886 spdy_stream_lowest->SendRequestHeaders(
1887 headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1888 EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1890 scoped_ptr<SpdyHeaderBlock> headers_highest(
1891 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1892 spdy_stream_highest->SendRequestHeaders(
1893 headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1894 EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1896 data.RunFor(7);
1898 EXPECT_FALSE(spdy_stream_lowest);
1899 EXPECT_FALSE(spdy_stream_highest);
1900 EXPECT_EQ(3u, delegate_lowest.stream_id());
1901 EXPECT_EQ(1u, delegate_highest.stream_id());
1904 TEST_P(SpdySessionTest, CancelStream) {
1905 MockConnect connect_data(SYNCHRONOUS, OK);
1906 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1907 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1908 scoped_ptr<SpdyFrame> req2(
1909 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1910 MockWrite writes[] = {
1911 CreateMockWrite(*req2, 0),
1914 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1915 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1916 MockRead reads[] = {
1917 CreateMockRead(*resp2, 1),
1918 CreateMockRead(*body2, 2),
1919 MockRead(ASYNC, 0, 3) // EOF
1922 session_deps_.host_resolver->set_synchronous_mode(true);
1924 DeterministicSocketData data(reads, arraysize(reads),
1925 writes, arraysize(writes));
1926 data.set_connect_data(connect_data);
1927 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1929 CreateDeterministicNetworkSession();
1931 base::WeakPtr<SpdySession> session =
1932 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1934 GURL url1(kDefaultURL);
1935 base::WeakPtr<SpdyStream> spdy_stream1 =
1936 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1937 session, url1, HIGHEST, BoundNetLog());
1938 ASSERT_TRUE(spdy_stream1.get() != NULL);
1939 EXPECT_EQ(0u, spdy_stream1->stream_id());
1940 test::StreamDelegateDoNothing delegate1(spdy_stream1);
1941 spdy_stream1->SetDelegate(&delegate1);
1943 GURL url2(kDefaultURL);
1944 base::WeakPtr<SpdyStream> spdy_stream2 =
1945 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1946 session, url2, LOWEST, BoundNetLog());
1947 ASSERT_TRUE(spdy_stream2.get() != NULL);
1948 EXPECT_EQ(0u, spdy_stream2->stream_id());
1949 test::StreamDelegateDoNothing delegate2(spdy_stream2);
1950 spdy_stream2->SetDelegate(&delegate2);
1952 scoped_ptr<SpdyHeaderBlock> headers(
1953 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1954 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1955 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1957 scoped_ptr<SpdyHeaderBlock> headers2(
1958 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1959 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1960 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1962 EXPECT_EQ(0u, spdy_stream1->stream_id());
1964 spdy_stream1->Cancel();
1965 EXPECT_EQ(NULL, spdy_stream1.get());
1967 EXPECT_EQ(0u, delegate1.stream_id());
1969 data.RunFor(1);
1971 EXPECT_EQ(0u, delegate1.stream_id());
1972 EXPECT_EQ(1u, delegate2.stream_id());
1974 spdy_stream2->Cancel();
1975 EXPECT_EQ(NULL, spdy_stream2.get());
1978 // Create two streams that are set to re-close themselves on close,
1979 // and then close the session. Nothing should blow up. Also a
1980 // regression test for http://crbug.com/139518 .
1981 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1982 session_deps_.host_resolver->set_synchronous_mode(true);
1984 MockConnect connect_data(SYNCHRONOUS, OK);
1986 // No actual data will be sent.
1987 MockWrite writes[] = {
1988 MockWrite(ASYNC, 0, 1) // EOF
1991 MockRead reads[] = {
1992 MockRead(ASYNC, 0, 0) // EOF
1994 DeterministicSocketData data(reads, arraysize(reads),
1995 writes, arraysize(writes));
1996 data.set_connect_data(connect_data);
1997 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1999 CreateDeterministicNetworkSession();
2001 base::WeakPtr<SpdySession> session =
2002 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2004 GURL url1(kDefaultURL);
2005 base::WeakPtr<SpdyStream> spdy_stream1 =
2006 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2007 session, url1, HIGHEST, BoundNetLog());
2008 ASSERT_TRUE(spdy_stream1.get() != NULL);
2009 EXPECT_EQ(0u, spdy_stream1->stream_id());
2011 GURL url2(kDefaultURL);
2012 base::WeakPtr<SpdyStream> spdy_stream2 =
2013 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2014 session, url2, LOWEST, BoundNetLog());
2015 ASSERT_TRUE(spdy_stream2.get() != NULL);
2016 EXPECT_EQ(0u, spdy_stream2->stream_id());
2018 test::ClosingDelegate delegate1(spdy_stream1);
2019 spdy_stream1->SetDelegate(&delegate1);
2021 test::ClosingDelegate delegate2(spdy_stream2);
2022 spdy_stream2->SetDelegate(&delegate2);
2024 scoped_ptr<SpdyHeaderBlock> headers(
2025 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2026 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2027 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2029 scoped_ptr<SpdyHeaderBlock> headers2(
2030 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2031 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2032 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2034 // Ensure that the streams have not yet been activated and assigned an id.
2035 EXPECT_EQ(0u, spdy_stream1->stream_id());
2036 EXPECT_EQ(0u, spdy_stream2->stream_id());
2038 // Ensure we don't crash while closing the session.
2039 session->CloseSessionOnError(ERR_ABORTED, std::string());
2041 EXPECT_EQ(NULL, spdy_stream1.get());
2042 EXPECT_EQ(NULL, spdy_stream2.get());
2044 EXPECT_TRUE(delegate1.StreamIsClosed());
2045 EXPECT_TRUE(delegate2.StreamIsClosed());
2047 base::MessageLoop::current()->RunUntilIdle();
2048 EXPECT_TRUE(session == NULL);
2051 // Create two streams that are set to close each other on close, and
2052 // then close the session. Nothing should blow up.
2053 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
2054 session_deps_.host_resolver->set_synchronous_mode(true);
2056 MockConnect connect_data(SYNCHRONOUS, OK);
2058 // No actual data will be sent.
2059 MockWrite writes[] = {
2060 MockWrite(ASYNC, 0, 1) // EOF
2063 MockRead reads[] = {
2064 MockRead(ASYNC, 0, 0) // EOF
2066 DeterministicSocketData data(reads, arraysize(reads),
2067 writes, arraysize(writes));
2068 data.set_connect_data(connect_data);
2069 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2071 CreateDeterministicNetworkSession();
2073 base::WeakPtr<SpdySession> session =
2074 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2076 GURL url1(kDefaultURL);
2077 base::WeakPtr<SpdyStream> spdy_stream1 =
2078 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2079 session, url1, HIGHEST, BoundNetLog());
2080 ASSERT_TRUE(spdy_stream1.get() != NULL);
2081 EXPECT_EQ(0u, spdy_stream1->stream_id());
2083 GURL url2(kDefaultURL);
2084 base::WeakPtr<SpdyStream> spdy_stream2 =
2085 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2086 session, url2, LOWEST, BoundNetLog());
2087 ASSERT_TRUE(spdy_stream2.get() != NULL);
2088 EXPECT_EQ(0u, spdy_stream2->stream_id());
2090 // Make |spdy_stream1| close |spdy_stream2|.
2091 test::ClosingDelegate delegate1(spdy_stream2);
2092 spdy_stream1->SetDelegate(&delegate1);
2094 // Make |spdy_stream2| close |spdy_stream1|.
2095 test::ClosingDelegate delegate2(spdy_stream1);
2096 spdy_stream2->SetDelegate(&delegate2);
2098 scoped_ptr<SpdyHeaderBlock> headers(
2099 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2100 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2101 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2103 scoped_ptr<SpdyHeaderBlock> headers2(
2104 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2105 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2106 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2108 // Ensure that the streams have not yet been activated and assigned an id.
2109 EXPECT_EQ(0u, spdy_stream1->stream_id());
2110 EXPECT_EQ(0u, spdy_stream2->stream_id());
2112 // Ensure we don't crash while closing the session.
2113 session->CloseSessionOnError(ERR_ABORTED, std::string());
2115 EXPECT_EQ(NULL, spdy_stream1.get());
2116 EXPECT_EQ(NULL, spdy_stream2.get());
2118 EXPECT_TRUE(delegate1.StreamIsClosed());
2119 EXPECT_TRUE(delegate2.StreamIsClosed());
2121 base::MessageLoop::current()->RunUntilIdle();
2122 EXPECT_TRUE(session == NULL);
2125 // Create two streams that are set to re-close themselves on close,
2126 // activate them, and then close the session. Nothing should blow up.
2127 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
2128 session_deps_.host_resolver->set_synchronous_mode(true);
2130 MockConnect connect_data(SYNCHRONOUS, OK);
2132 scoped_ptr<SpdyFrame> req1(
2133 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2134 scoped_ptr<SpdyFrame> req2(
2135 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2136 MockWrite writes[] = {
2137 CreateMockWrite(*req1, 0),
2138 CreateMockWrite(*req2, 1),
2141 MockRead reads[] = {
2142 MockRead(ASYNC, 0, 2) // EOF
2145 DeterministicSocketData data(reads, arraysize(reads),
2146 writes, arraysize(writes));
2147 data.set_connect_data(connect_data);
2148 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2150 CreateDeterministicNetworkSession();
2152 base::WeakPtr<SpdySession> session =
2153 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2155 GURL url1(kDefaultURL);
2156 base::WeakPtr<SpdyStream> spdy_stream1 =
2157 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2158 session, url1, MEDIUM, BoundNetLog());
2159 ASSERT_TRUE(spdy_stream1.get() != NULL);
2160 EXPECT_EQ(0u, spdy_stream1->stream_id());
2162 GURL url2(kDefaultURL);
2163 base::WeakPtr<SpdyStream> spdy_stream2 =
2164 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2165 session, url2, MEDIUM, BoundNetLog());
2166 ASSERT_TRUE(spdy_stream2.get() != NULL);
2167 EXPECT_EQ(0u, spdy_stream2->stream_id());
2169 test::ClosingDelegate delegate1(spdy_stream1);
2170 spdy_stream1->SetDelegate(&delegate1);
2172 test::ClosingDelegate delegate2(spdy_stream2);
2173 spdy_stream2->SetDelegate(&delegate2);
2175 scoped_ptr<SpdyHeaderBlock> headers(
2176 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2177 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2178 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2180 scoped_ptr<SpdyHeaderBlock> headers2(
2181 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2182 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2183 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2185 // Ensure that the streams have not yet been activated and assigned an id.
2186 EXPECT_EQ(0u, spdy_stream1->stream_id());
2187 EXPECT_EQ(0u, spdy_stream2->stream_id());
2189 data.RunFor(2);
2191 EXPECT_EQ(1u, spdy_stream1->stream_id());
2192 EXPECT_EQ(3u, spdy_stream2->stream_id());
2194 // Ensure we don't crash while closing the session.
2195 session->CloseSessionOnError(ERR_ABORTED, std::string());
2197 EXPECT_EQ(NULL, spdy_stream1.get());
2198 EXPECT_EQ(NULL, spdy_stream2.get());
2200 EXPECT_TRUE(delegate1.StreamIsClosed());
2201 EXPECT_TRUE(delegate2.StreamIsClosed());
2203 base::MessageLoop::current()->RunUntilIdle();
2204 EXPECT_TRUE(session == NULL);
2207 // Create two streams that are set to close each other on close,
2208 // activate them, and then close the session. Nothing should blow up.
2209 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2210 session_deps_.host_resolver->set_synchronous_mode(true);
2212 MockConnect connect_data(SYNCHRONOUS, OK);
2214 scoped_ptr<SpdyFrame> req1(
2215 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2216 scoped_ptr<SpdyFrame> req2(
2217 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2218 MockWrite writes[] = {
2219 CreateMockWrite(*req1, 0),
2220 CreateMockWrite(*req2, 1),
2223 MockRead reads[] = {
2224 MockRead(ASYNC, 0, 2) // EOF
2227 DeterministicSocketData data(reads, arraysize(reads),
2228 writes, arraysize(writes));
2229 data.set_connect_data(connect_data);
2230 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2232 CreateDeterministicNetworkSession();
2234 base::WeakPtr<SpdySession> session =
2235 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2237 GURL url1(kDefaultURL);
2238 base::WeakPtr<SpdyStream> spdy_stream1 =
2239 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2240 session, url1, MEDIUM, BoundNetLog());
2241 ASSERT_TRUE(spdy_stream1.get() != NULL);
2242 EXPECT_EQ(0u, spdy_stream1->stream_id());
2244 GURL url2(kDefaultURL);
2245 base::WeakPtr<SpdyStream> spdy_stream2 =
2246 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2247 session, url2, MEDIUM, BoundNetLog());
2248 ASSERT_TRUE(spdy_stream2.get() != NULL);
2249 EXPECT_EQ(0u, spdy_stream2->stream_id());
2251 // Make |spdy_stream1| close |spdy_stream2|.
2252 test::ClosingDelegate delegate1(spdy_stream2);
2253 spdy_stream1->SetDelegate(&delegate1);
2255 // Make |spdy_stream2| close |spdy_stream1|.
2256 test::ClosingDelegate delegate2(spdy_stream1);
2257 spdy_stream2->SetDelegate(&delegate2);
2259 scoped_ptr<SpdyHeaderBlock> headers(
2260 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2261 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2262 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2264 scoped_ptr<SpdyHeaderBlock> headers2(
2265 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2266 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2267 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2269 // Ensure that the streams have not yet been activated and assigned an id.
2270 EXPECT_EQ(0u, spdy_stream1->stream_id());
2271 EXPECT_EQ(0u, spdy_stream2->stream_id());
2273 data.RunFor(2);
2275 EXPECT_EQ(1u, spdy_stream1->stream_id());
2276 EXPECT_EQ(3u, spdy_stream2->stream_id());
2278 // Ensure we don't crash while closing the session.
2279 session->CloseSessionOnError(ERR_ABORTED, std::string());
2281 EXPECT_EQ(NULL, spdy_stream1.get());
2282 EXPECT_EQ(NULL, spdy_stream2.get());
2284 EXPECT_TRUE(delegate1.StreamIsClosed());
2285 EXPECT_TRUE(delegate2.StreamIsClosed());
2287 base::MessageLoop::current()->RunUntilIdle();
2288 EXPECT_TRUE(session == NULL);
2291 // Delegate that closes a given session when the stream is closed.
2292 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2293 public:
2294 SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2295 const base::WeakPtr<SpdySession>& session_to_close)
2296 : StreamDelegateDoNothing(stream),
2297 session_to_close_(session_to_close) {}
2299 ~SessionClosingDelegate() override {}
2301 void OnClose(int status) override {
2302 session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2305 private:
2306 base::WeakPtr<SpdySession> session_to_close_;
2309 // Close an activated stream that closes its session. Nothing should
2310 // blow up. This is a regression test for http://crbug.com/263691 .
2311 TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2312 session_deps_.host_resolver->set_synchronous_mode(true);
2314 MockConnect connect_data(SYNCHRONOUS, OK);
2316 scoped_ptr<SpdyFrame> req(
2317 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2318 scoped_ptr<SpdyFrame> rst(
2319 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2320 scoped_ptr<SpdyFrame> goaway(
2321 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2322 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2323 // despite being queued second.
2324 MockWrite writes[] = {
2325 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 1),
2326 CreateMockWrite(*rst, 2),
2329 MockRead reads[] = {
2330 MockRead(ASYNC, 0, 3) // EOF
2332 DeterministicSocketData data(reads, arraysize(reads),
2333 writes, arraysize(writes));
2334 data.set_connect_data(connect_data);
2335 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2337 CreateDeterministicNetworkSession();
2339 base::WeakPtr<SpdySession> session =
2340 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2342 GURL url(kDefaultURL);
2343 base::WeakPtr<SpdyStream> spdy_stream =
2344 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2345 session, url, MEDIUM, BoundNetLog());
2346 ASSERT_TRUE(spdy_stream.get() != NULL);
2347 EXPECT_EQ(0u, spdy_stream->stream_id());
2349 SessionClosingDelegate delegate(spdy_stream, session);
2350 spdy_stream->SetDelegate(&delegate);
2352 scoped_ptr<SpdyHeaderBlock> headers(
2353 spdy_util_.ConstructGetHeaderBlock(url.spec()));
2354 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2355 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2357 EXPECT_EQ(0u, spdy_stream->stream_id());
2359 data.RunFor(1);
2361 EXPECT_EQ(1u, spdy_stream->stream_id());
2363 // Ensure we don't crash while closing the stream (which closes the
2364 // session).
2365 spdy_stream->Cancel();
2367 EXPECT_EQ(NULL, spdy_stream.get());
2368 EXPECT_TRUE(delegate.StreamIsClosed());
2370 data.RunFor(2); // Write the RST_STREAM & GOAWAY.
2371 base::MessageLoop::current()->RunUntilIdle();
2372 EXPECT_TRUE(session == NULL);
2375 TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2376 session_deps_.host_resolver->set_synchronous_mode(true);
2378 MockConnect connect_data(SYNCHRONOUS, OK);
2380 // No actual data will be sent.
2381 MockWrite writes[] = {
2382 MockWrite(ASYNC, 0, 1) // EOF
2385 MockRead reads[] = {
2386 MockRead(ASYNC, 0, 0) // EOF
2388 DeterministicSocketData data(reads, arraysize(reads),
2389 writes, arraysize(writes));
2390 data.set_connect_data(connect_data);
2391 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2393 // Load a cert that is valid for:
2394 // www.example.org
2395 // mail.example.org
2396 // www.example.com
2397 base::FilePath certs_dir = GetTestCertsDirectory();
2398 scoped_refptr<X509Certificate> test_cert(
2399 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2400 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2402 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2403 ssl.cert = test_cert;
2404 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2406 CreateDeterministicNetworkSession();
2408 base::WeakPtr<SpdySession> session =
2409 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2411 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2412 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2413 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
2414 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2417 TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2418 session_deps_.host_resolver->set_synchronous_mode(true);
2420 MockConnect connect_data(SYNCHRONOUS, OK);
2422 // No actual data will be sent.
2423 MockWrite writes[] = {
2424 MockWrite(ASYNC, 0, 1) // EOF
2427 MockRead reads[] = {
2428 MockRead(ASYNC, 0, 0) // EOF
2430 DeterministicSocketData data(reads, arraysize(reads),
2431 writes, arraysize(writes));
2432 data.set_connect_data(connect_data);
2433 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2435 // Load a cert that is valid for:
2436 // www.example.org
2437 // mail.example.org
2438 // www.example.com
2439 base::FilePath certs_dir = GetTestCertsDirectory();
2440 scoped_refptr<X509Certificate> test_cert(
2441 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2442 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2444 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2445 ssl.channel_id_sent = true;
2446 ssl.cert = test_cert;
2447 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2449 CreateDeterministicNetworkSession();
2451 base::WeakPtr<SpdySession> session =
2452 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2454 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2455 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2456 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2457 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2460 TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2461 // TODO(rtenneti): Define a helper class/methods and move the common code in
2462 // this file.
2463 MockConnect connect_data(SYNCHRONOUS, OK);
2465 SettingsMap new_settings;
2466 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2467 const uint32 max_concurrent_streams = 1;
2468 new_settings[kSpdySettingsIds1] =
2469 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2471 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
2472 scoped_ptr<SpdyFrame> req1(
2473 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2474 scoped_ptr<SpdyFrame> req2(
2475 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
2476 scoped_ptr<SpdyFrame> req3(
2477 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
2478 MockWrite writes[] = {
2479 CreateMockWrite(*settings_ack, 1),
2480 CreateMockWrite(*req1, 2),
2481 CreateMockWrite(*req2, 5),
2482 CreateMockWrite(*req3, 8),
2485 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2486 // streams to 1.
2487 scoped_ptr<SpdyFrame> settings_frame(
2488 spdy_util_.ConstructSpdySettings(new_settings));
2490 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2491 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2493 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2494 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2496 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
2497 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2499 MockRead reads[] = {
2500 CreateMockRead(*settings_frame),
2501 CreateMockRead(*resp1, 3),
2502 CreateMockRead(*body1, 4),
2503 CreateMockRead(*resp2, 6),
2504 CreateMockRead(*body2, 7),
2505 CreateMockRead(*resp3, 9),
2506 CreateMockRead(*body3, 10),
2507 MockRead(ASYNC, 0, 11) // EOF
2510 DeterministicSocketData data(reads, arraysize(reads),
2511 writes, arraysize(writes));
2512 data.set_connect_data(connect_data);
2513 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2515 CreateDeterministicNetworkSession();
2517 base::WeakPtr<SpdySession> session =
2518 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2520 // Read the settings frame.
2521 data.RunFor(1);
2523 GURL url1(kDefaultURL);
2524 base::WeakPtr<SpdyStream> spdy_stream1 =
2525 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2526 session, url1, LOWEST, BoundNetLog());
2527 ASSERT_TRUE(spdy_stream1.get() != NULL);
2528 EXPECT_EQ(0u, spdy_stream1->stream_id());
2529 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2530 spdy_stream1->SetDelegate(&delegate1);
2532 TestCompletionCallback callback2;
2533 GURL url2(kDefaultURL);
2534 SpdyStreamRequest request2;
2535 ASSERT_EQ(ERR_IO_PENDING,
2536 request2.StartRequest(
2537 SPDY_REQUEST_RESPONSE_STREAM,
2538 session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2540 TestCompletionCallback callback3;
2541 GURL url3(kDefaultURL);
2542 SpdyStreamRequest request3;
2543 ASSERT_EQ(ERR_IO_PENDING,
2544 request3.StartRequest(
2545 SPDY_REQUEST_RESPONSE_STREAM,
2546 session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2548 EXPECT_EQ(0u, session->num_active_streams());
2549 EXPECT_EQ(1u, session->num_created_streams());
2550 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2552 scoped_ptr<SpdyHeaderBlock> headers(
2553 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2554 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2555 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2557 // Run until 1st stream is activated and then closed.
2558 EXPECT_EQ(0u, delegate1.stream_id());
2559 data.RunFor(4);
2560 EXPECT_EQ(NULL, spdy_stream1.get());
2561 EXPECT_EQ(1u, delegate1.stream_id());
2563 EXPECT_EQ(0u, session->num_active_streams());
2564 EXPECT_EQ(0u, session->num_created_streams());
2565 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2567 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2568 // create the 2nd stream.
2569 base::MessageLoop::current()->RunUntilIdle();
2571 EXPECT_EQ(0u, session->num_active_streams());
2572 EXPECT_EQ(1u, session->num_created_streams());
2573 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2575 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2576 test::StreamDelegateDoNothing delegate2(stream2);
2577 stream2->SetDelegate(&delegate2);
2578 scoped_ptr<SpdyHeaderBlock> headers2(
2579 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2580 stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2581 EXPECT_TRUE(stream2->HasUrlFromHeaders());
2583 // Run until 2nd stream is activated and then closed.
2584 EXPECT_EQ(0u, delegate2.stream_id());
2585 data.RunFor(3);
2586 EXPECT_EQ(NULL, stream2.get());
2587 EXPECT_EQ(3u, delegate2.stream_id());
2589 EXPECT_EQ(0u, session->num_active_streams());
2590 EXPECT_EQ(0u, session->num_created_streams());
2591 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2593 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2594 // create the 3rd stream.
2595 base::MessageLoop::current()->RunUntilIdle();
2597 EXPECT_EQ(0u, session->num_active_streams());
2598 EXPECT_EQ(1u, session->num_created_streams());
2599 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2601 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2602 test::StreamDelegateDoNothing delegate3(stream3);
2603 stream3->SetDelegate(&delegate3);
2604 scoped_ptr<SpdyHeaderBlock> headers3(
2605 spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2606 stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2607 EXPECT_TRUE(stream3->HasUrlFromHeaders());
2609 // Run until 2nd stream is activated and then closed.
2610 EXPECT_EQ(0u, delegate3.stream_id());
2611 data.RunFor(3);
2612 EXPECT_EQ(NULL, stream3.get());
2613 EXPECT_EQ(5u, delegate3.stream_id());
2615 EXPECT_EQ(0u, session->num_active_streams());
2616 EXPECT_EQ(0u, session->num_created_streams());
2617 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2619 data.RunFor(1);
2622 TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2623 session_deps_.host_resolver->set_synchronous_mode(true);
2625 MockRead reads[] = {
2626 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2629 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2630 MockConnect connect_data(SYNCHRONOUS, OK);
2632 data.set_connect_data(connect_data);
2633 session_deps_.socket_factory->AddSocketDataProvider(&data);
2635 CreateNetworkSession();
2637 base::WeakPtr<SpdySession> session =
2638 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2640 // Leave room for only one more stream to be created.
2641 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2642 base::WeakPtr<SpdyStream> spdy_stream =
2643 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2644 session, test_url_, MEDIUM, BoundNetLog());
2645 ASSERT_TRUE(spdy_stream != NULL);
2648 GURL url1(kDefaultURL);
2649 base::WeakPtr<SpdyStream> spdy_stream1 =
2650 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2651 session, url1, LOWEST, BoundNetLog());
2652 ASSERT_TRUE(spdy_stream1.get() != NULL);
2653 EXPECT_EQ(0u, spdy_stream1->stream_id());
2655 TestCompletionCallback callback2;
2656 GURL url2(kDefaultURL);
2657 SpdyStreamRequest request2;
2658 ASSERT_EQ(ERR_IO_PENDING,
2659 request2.StartRequest(
2660 SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2661 callback2.callback()));
2663 TestCompletionCallback callback3;
2664 GURL url3(kDefaultURL);
2665 SpdyStreamRequest request3;
2666 ASSERT_EQ(ERR_IO_PENDING,
2667 request3.StartRequest(
2668 SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2669 callback3.callback()));
2671 EXPECT_EQ(0u, session->num_active_streams());
2672 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2673 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2675 // Cancel the first stream; this will allow the second stream to be created.
2676 EXPECT_TRUE(spdy_stream1.get() != NULL);
2677 spdy_stream1->Cancel();
2678 EXPECT_EQ(NULL, spdy_stream1.get());
2680 EXPECT_EQ(OK, callback2.WaitForResult());
2681 EXPECT_EQ(0u, session->num_active_streams());
2682 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2683 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2685 // Cancel the second stream; this will allow the third stream to be created.
2686 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2687 spdy_stream2->Cancel();
2688 EXPECT_EQ(NULL, spdy_stream2.get());
2690 EXPECT_EQ(OK, callback3.WaitForResult());
2691 EXPECT_EQ(0u, session->num_active_streams());
2692 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2693 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2695 // Cancel the third stream.
2696 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2697 spdy_stream3->Cancel();
2698 EXPECT_EQ(NULL, spdy_stream3.get());
2699 EXPECT_EQ(0u, session->num_active_streams());
2700 EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
2701 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2704 // Test that SpdySession::DoReadLoop reads data from the socket
2705 // without yielding. This test makes 32k - 1 bytes of data available
2706 // on the socket for reading. It then verifies that it has read all
2707 // the available data without yielding.
2708 TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2709 MockConnect connect_data(SYNCHRONOUS, OK);
2710 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2712 scoped_ptr<SpdyFrame> req1(
2713 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2714 MockWrite writes[] = {
2715 CreateMockWrite(*req1, 0),
2718 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2719 // (-spdy_data_frame_size).
2720 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2721 const int kPayloadSize =
2722 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2723 TestDataStream test_stream;
2724 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2725 char* payload_data = payload->data();
2726 test_stream.GetBytes(payload_data, kPayloadSize);
2728 scoped_ptr<SpdyFrame> partial_data_frame(
2729 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2730 scoped_ptr<SpdyFrame> finish_data_frame(
2731 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2733 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2735 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2736 // bytes.
2737 MockRead reads[] = {
2738 CreateMockRead(*resp1, 1),
2739 CreateMockRead(*partial_data_frame, 2),
2740 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2741 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2742 CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2743 MockRead(ASYNC, 0, 6) // EOF
2746 // Create SpdySession and SpdyStream and send the request.
2747 DeterministicSocketData data(reads, arraysize(reads),
2748 writes, arraysize(writes));
2749 data.set_connect_data(connect_data);
2750 session_deps_.host_resolver->set_synchronous_mode(true);
2751 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2753 CreateDeterministicNetworkSession();
2755 base::WeakPtr<SpdySession> session =
2756 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2758 GURL url1(kDefaultURL);
2759 base::WeakPtr<SpdyStream> spdy_stream1 =
2760 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2761 session, url1, MEDIUM, BoundNetLog());
2762 ASSERT_TRUE(spdy_stream1.get() != NULL);
2763 EXPECT_EQ(0u, spdy_stream1->stream_id());
2764 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2765 spdy_stream1->SetDelegate(&delegate1);
2767 scoped_ptr<SpdyHeaderBlock> headers1(
2768 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2769 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2770 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2772 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2773 // post a task.
2774 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2776 // Run until 1st read.
2777 EXPECT_EQ(0u, delegate1.stream_id());
2778 data.RunFor(2);
2779 EXPECT_EQ(1u, delegate1.stream_id());
2780 EXPECT_EQ(0u, observer.executed_count());
2782 // Read all the data and verify SpdySession::DoReadLoop has not
2783 // posted a task.
2784 data.RunFor(4);
2785 EXPECT_EQ(NULL, spdy_stream1.get());
2787 // Verify task observer's executed_count is zero, which indicates DoRead read
2788 // all the available data.
2789 EXPECT_EQ(0u, observer.executed_count());
2790 EXPECT_TRUE(data.at_write_eof());
2791 EXPECT_TRUE(data.at_read_eof());
2794 // Test that SpdySession::DoReadLoop yields while reading the
2795 // data. This test makes 32k + 1 bytes of data available on the socket
2796 // for reading. It then verifies that DoRead has yielded even though
2797 // there is data available for it to read (i.e, socket()->Read didn't
2798 // return ERR_IO_PENDING during socket reads).
2799 TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2800 MockConnect connect_data(SYNCHRONOUS, OK);
2801 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2803 scoped_ptr<SpdyFrame> req1(
2804 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2805 MockWrite writes[] = {
2806 CreateMockWrite(*req1, 0),
2809 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2810 // (-spdy_data_frame_size).
2811 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2812 const int kPayloadSize =
2813 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2814 TestDataStream test_stream;
2815 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2816 char* payload_data = payload->data();
2817 test_stream.GetBytes(payload_data, kPayloadSize);
2819 scoped_ptr<SpdyFrame> partial_data_frame(
2820 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2821 scoped_ptr<SpdyFrame> finish_data_frame(
2822 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2824 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2826 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2827 MockRead reads[] = {
2828 CreateMockRead(*resp1, 1),
2829 CreateMockRead(*partial_data_frame, 2),
2830 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2831 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2832 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2833 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2834 MockRead(ASYNC, 0, 7) // EOF
2837 // Create SpdySession and SpdyStream and send the request.
2838 DeterministicSocketData data(reads, arraysize(reads),
2839 writes, arraysize(writes));
2840 data.set_connect_data(connect_data);
2841 session_deps_.host_resolver->set_synchronous_mode(true);
2842 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2844 CreateDeterministicNetworkSession();
2846 base::WeakPtr<SpdySession> session =
2847 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2849 GURL url1(kDefaultURL);
2850 base::WeakPtr<SpdyStream> spdy_stream1 =
2851 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2852 session, url1, MEDIUM, BoundNetLog());
2853 ASSERT_TRUE(spdy_stream1.get() != NULL);
2854 EXPECT_EQ(0u, spdy_stream1->stream_id());
2855 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2856 spdy_stream1->SetDelegate(&delegate1);
2858 scoped_ptr<SpdyHeaderBlock> headers1(
2859 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2860 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2861 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2863 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2864 // task.
2865 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2867 // Run until 1st read.
2868 EXPECT_EQ(0u, delegate1.stream_id());
2869 data.RunFor(2);
2870 EXPECT_EQ(1u, delegate1.stream_id());
2871 EXPECT_EQ(0u, observer.executed_count());
2873 // Read all the data and verify SpdySession::DoReadLoop has posted a
2874 // task.
2875 data.RunFor(6);
2876 EXPECT_EQ(NULL, spdy_stream1.get());
2878 // Verify task observer's executed_count is 1, which indicates DoRead has
2879 // posted only one task and thus yielded though there is data available for it
2880 // to read.
2881 EXPECT_EQ(1u, observer.executed_count());
2882 EXPECT_TRUE(data.at_write_eof());
2883 EXPECT_TRUE(data.at_read_eof());
2886 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2887 // + async, by doing the following MockReads.
2889 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2890 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2892 // The above reads 26K synchronously. Since that is less that 32K, we
2893 // will attempt to read again. However, that DoRead() will return
2894 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2895 // yield. When we come back, DoRead() will read the results from the
2896 // async read, and rest of the data synchronously.
2897 TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2898 MockConnect connect_data(SYNCHRONOUS, OK);
2899 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2901 scoped_ptr<SpdyFrame> req1(
2902 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2903 MockWrite writes[] = {
2904 CreateMockWrite(*req1, 0),
2907 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2908 // (-spdy_data_frame_size).
2909 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2910 TestDataStream test_stream;
2911 const int kEightKPayloadSize =
2912 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2913 scoped_refptr<net::IOBuffer> eightk_payload(
2914 new net::IOBuffer(kEightKPayloadSize));
2915 char* eightk_payload_data = eightk_payload->data();
2916 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2918 // Build buffer of 2k size.
2919 TestDataStream test_stream2;
2920 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2921 scoped_refptr<net::IOBuffer> twok_payload(
2922 new net::IOBuffer(kTwoKPayloadSize));
2923 char* twok_payload_data = twok_payload->data();
2924 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2926 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2927 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2928 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2929 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2930 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2931 1, "h", 1, DATA_FLAG_FIN));
2933 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2935 MockRead reads[] = {
2936 CreateMockRead(*resp1, 1),
2937 CreateMockRead(*eightk_data_frame, 2),
2938 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
2939 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2940 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
2941 CreateMockRead(*eightk_data_frame, 6, ASYNC),
2942 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
2943 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2944 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2945 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
2946 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
2947 MockRead(ASYNC, 0, 12) // EOF
2950 // Create SpdySession and SpdyStream and send the request.
2951 DeterministicSocketData data(reads, arraysize(reads),
2952 writes, arraysize(writes));
2953 data.set_connect_data(connect_data);
2954 session_deps_.host_resolver->set_synchronous_mode(true);
2955 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2957 CreateDeterministicNetworkSession();
2959 base::WeakPtr<SpdySession> session =
2960 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2962 GURL url1(kDefaultURL);
2963 base::WeakPtr<SpdyStream> spdy_stream1 =
2964 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2965 session, url1, MEDIUM, BoundNetLog());
2966 ASSERT_TRUE(spdy_stream1.get() != NULL);
2967 EXPECT_EQ(0u, spdy_stream1->stream_id());
2968 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2969 spdy_stream1->SetDelegate(&delegate1);
2971 scoped_ptr<SpdyHeaderBlock> headers1(
2972 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2973 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2974 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2976 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2977 // posting of tasks.
2978 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2980 // Run until 1st read.
2981 EXPECT_EQ(0u, delegate1.stream_id());
2982 data.RunFor(2);
2983 EXPECT_EQ(1u, delegate1.stream_id());
2984 EXPECT_EQ(0u, observer.executed_count());
2986 // Read all the data and verify SpdySession::DoReadLoop has posted a
2987 // task.
2988 data.RunFor(12);
2989 EXPECT_EQ(NULL, spdy_stream1.get());
2991 // Verify task observer's executed_count is 1, which indicates DoRead has
2992 // posted only one task and thus yielded though there is data available for
2993 // it to read.
2994 EXPECT_EQ(1u, observer.executed_count());
2995 EXPECT_TRUE(data.at_write_eof());
2996 EXPECT_TRUE(data.at_read_eof());
2999 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
3000 // nothing blows up.
3001 TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
3002 MockConnect connect_data(SYNCHRONOUS, OK);
3003 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3005 scoped_ptr<SpdyFrame> req1(
3006 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3007 MockWrite writes[] = {
3008 CreateMockWrite(*req1, 0),
3011 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3012 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
3013 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
3015 MockRead reads[] = {
3016 CreateMockRead(*resp1, 1),
3017 CreateMockRead(*body1, 2),
3018 CreateMockRead(*goaway, 3),
3021 // Create SpdySession and SpdyStream and send the request.
3022 DeterministicSocketData data(reads, arraysize(reads),
3023 writes, arraysize(writes));
3024 data.set_connect_data(connect_data);
3025 session_deps_.host_resolver->set_synchronous_mode(true);
3026 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3028 CreateDeterministicNetworkSession();
3030 base::WeakPtr<SpdySession> session =
3031 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3033 GURL url1(kDefaultURL);
3034 base::WeakPtr<SpdyStream> spdy_stream1 =
3035 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3036 session, url1, MEDIUM, BoundNetLog());
3037 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3038 spdy_stream1->SetDelegate(&delegate1);
3039 ASSERT_TRUE(spdy_stream1.get() != NULL);
3040 EXPECT_EQ(0u, spdy_stream1->stream_id());
3042 scoped_ptr<SpdyHeaderBlock> headers1(
3043 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3044 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
3045 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3047 // Run until 1st read.
3048 EXPECT_EQ(0u, spdy_stream1->stream_id());
3049 data.RunFor(1);
3050 EXPECT_EQ(1u, spdy_stream1->stream_id());
3052 // Run until GoAway.
3053 data.RunFor(3);
3054 EXPECT_EQ(NULL, spdy_stream1.get());
3055 EXPECT_TRUE(data.at_write_eof());
3056 EXPECT_TRUE(data.at_read_eof());
3057 EXPECT_TRUE(session == NULL);
3060 // Within this framework, a SpdySession should be initialized with
3061 // flow control disabled for protocol version 2, with flow control
3062 // enabled only for streams for protocol version 3, and with flow
3063 // control enabled for streams and sessions for higher versions.
3064 TEST_P(SpdySessionTest, ProtocolNegotiation) {
3065 session_deps_.host_resolver->set_synchronous_mode(true);
3067 MockConnect connect_data(SYNCHRONOUS, OK);
3068 MockRead reads[] = {
3069 MockRead(SYNCHRONOUS, 0, 0) // EOF
3071 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3072 data.set_connect_data(connect_data);
3073 session_deps_.socket_factory->AddSocketDataProvider(&data);
3075 CreateNetworkSession();
3076 base::WeakPtr<SpdySession> session =
3077 CreateFakeSpdySession(spdy_session_pool_, key_);
3079 EXPECT_EQ(spdy_util_.spdy_version(),
3080 session->buffered_spdy_framer_->protocol_version());
3081 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3082 session->flow_control_state());
3083 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3084 session->session_send_window_size_);
3085 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3086 session->session_recv_window_size_);
3087 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3090 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3091 // pointers to the idle session are currently held.
3092 TEST_P(SpdySessionTest, CloseOneIdleConnection) {
3093 ClientSocketPoolManager::set_max_sockets_per_group(
3094 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3095 ClientSocketPoolManager::set_max_sockets_per_pool(
3096 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3098 MockConnect connect_data(SYNCHRONOUS, OK);
3099 MockRead reads[] = {
3100 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3102 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3103 data.set_connect_data(connect_data);
3104 session_deps_.socket_factory->AddSocketDataProvider(&data);
3105 session_deps_.socket_factory->AddSocketDataProvider(&data);
3107 CreateNetworkSession();
3109 TransportClientSocketPool* pool =
3110 http_session_->GetTransportSocketPool(
3111 HttpNetworkSession::NORMAL_SOCKET_POOL);
3113 // Create an idle SPDY session.
3114 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3115 PRIVACY_MODE_DISABLED);
3116 base::WeakPtr<SpdySession> session1 =
3117 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3118 EXPECT_FALSE(pool->IsStalled());
3120 // Trying to create a new connection should cause the pool to be stalled, and
3121 // post a task asynchronously to try and close the session.
3122 TestCompletionCallback callback2;
3123 HostPortPair host_port2("2.com", 80);
3124 scoped_refptr<TransportSocketParams> params2(
3125 new TransportSocketParams(
3126 host_port2, false, false, OnHostResolutionCallback(),
3127 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3128 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3129 EXPECT_EQ(ERR_IO_PENDING,
3130 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3131 callback2.callback(), pool, BoundNetLog()));
3132 EXPECT_TRUE(pool->IsStalled());
3134 // The socket pool should close the connection asynchronously and establish a
3135 // new connection.
3136 EXPECT_EQ(OK, callback2.WaitForResult());
3137 EXPECT_FALSE(pool->IsStalled());
3138 EXPECT_TRUE(session1 == NULL);
3141 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3142 // pointers to the idle session are currently held, in the case the SPDY session
3143 // has an alias.
3144 TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
3145 ClientSocketPoolManager::set_max_sockets_per_group(
3146 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3147 ClientSocketPoolManager::set_max_sockets_per_pool(
3148 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3150 MockConnect connect_data(SYNCHRONOUS, OK);
3151 MockRead reads[] = {
3152 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3154 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3155 data.set_connect_data(connect_data);
3156 session_deps_.socket_factory->AddSocketDataProvider(&data);
3157 session_deps_.socket_factory->AddSocketDataProvider(&data);
3159 session_deps_.host_resolver->set_synchronous_mode(true);
3160 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3161 "1.com", "192.168.0.2", std::string());
3162 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3163 "2.com", "192.168.0.2", std::string());
3164 // Not strictly needed.
3165 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3166 "3.com", "192.168.0.3", std::string());
3168 CreateNetworkSession();
3170 TransportClientSocketPool* pool =
3171 http_session_->GetTransportSocketPool(
3172 HttpNetworkSession::NORMAL_SOCKET_POOL);
3174 // Create an idle SPDY session.
3175 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3176 PRIVACY_MODE_DISABLED);
3177 base::WeakPtr<SpdySession> session1 =
3178 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3179 EXPECT_FALSE(pool->IsStalled());
3181 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3182 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3183 PRIVACY_MODE_DISABLED);
3184 HostResolver::RequestInfo info(key2.host_port_pair());
3185 AddressList addresses;
3186 // Pre-populate the DNS cache, since a synchronous resolution is required in
3187 // order to create the alias.
3188 session_deps_.host_resolver->Resolve(info,
3189 DEFAULT_PRIORITY,
3190 &addresses,
3191 CompletionCallback(),
3192 NULL,
3193 BoundNetLog());
3194 // Get a session for |key2|, which should return the session created earlier.
3195 base::WeakPtr<SpdySession> session2 =
3196 spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3197 ASSERT_EQ(session1.get(), session2.get());
3198 EXPECT_FALSE(pool->IsStalled());
3200 // Trying to create a new connection should cause the pool to be stalled, and
3201 // post a task asynchronously to try and close the session.
3202 TestCompletionCallback callback3;
3203 HostPortPair host_port3("3.com", 80);
3204 scoped_refptr<TransportSocketParams> params3(
3205 new TransportSocketParams(
3206 host_port3, false, false, OnHostResolutionCallback(),
3207 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3208 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3209 EXPECT_EQ(ERR_IO_PENDING,
3210 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3211 callback3.callback(), pool, BoundNetLog()));
3212 EXPECT_TRUE(pool->IsStalled());
3214 // The socket pool should close the connection asynchronously and establish a
3215 // new connection.
3216 EXPECT_EQ(OK, callback3.WaitForResult());
3217 EXPECT_FALSE(pool->IsStalled());
3218 EXPECT_TRUE(session1 == NULL);
3219 EXPECT_TRUE(session2 == NULL);
3222 // Tests that when a SPDY session becomes idle, it closes itself if there is
3223 // a lower layer pool stalled on the per-pool socket limit.
3224 TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3225 ClientSocketPoolManager::set_max_sockets_per_group(
3226 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3227 ClientSocketPoolManager::set_max_sockets_per_pool(
3228 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3230 MockConnect connect_data(SYNCHRONOUS, OK);
3231 MockRead reads[] = {
3232 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3234 scoped_ptr<SpdyFrame> req1(
3235 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3236 scoped_ptr<SpdyFrame> cancel1(
3237 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3238 MockWrite writes[] = {
3239 CreateMockWrite(*req1, 1),
3240 CreateMockWrite(*cancel1, 1),
3242 StaticSocketDataProvider data(reads, arraysize(reads),
3243 writes, arraysize(writes));
3244 data.set_connect_data(connect_data);
3245 session_deps_.socket_factory->AddSocketDataProvider(&data);
3247 MockRead http_reads[] = {
3248 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3250 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
3251 NULL, 0);
3252 http_data.set_connect_data(connect_data);
3253 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3256 CreateNetworkSession();
3258 TransportClientSocketPool* pool =
3259 http_session_->GetTransportSocketPool(
3260 HttpNetworkSession::NORMAL_SOCKET_POOL);
3262 // Create a SPDY session.
3263 GURL url1(kDefaultURL);
3264 SpdySessionKey key1(HostPortPair(url1.host(), 80),
3265 ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3266 base::WeakPtr<SpdySession> session1 =
3267 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3268 EXPECT_FALSE(pool->IsStalled());
3270 // Create a stream using the session, and send a request.
3272 TestCompletionCallback callback1;
3273 base::WeakPtr<SpdyStream> spdy_stream1 =
3274 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3275 session1, url1, DEFAULT_PRIORITY,
3276 BoundNetLog());
3277 ASSERT_TRUE(spdy_stream1.get());
3278 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3279 spdy_stream1->SetDelegate(&delegate1);
3281 scoped_ptr<SpdyHeaderBlock> headers1(
3282 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3283 EXPECT_EQ(ERR_IO_PENDING,
3284 spdy_stream1->SendRequestHeaders(
3285 headers1.Pass(), NO_MORE_DATA_TO_SEND));
3286 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3288 base::MessageLoop::current()->RunUntilIdle();
3290 // Trying to create a new connection should cause the pool to be stalled, and
3291 // post a task asynchronously to try and close the session.
3292 TestCompletionCallback callback2;
3293 HostPortPair host_port2("2.com", 80);
3294 scoped_refptr<TransportSocketParams> params2(
3295 new TransportSocketParams(
3296 host_port2, false, false, OnHostResolutionCallback(),
3297 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3298 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3299 EXPECT_EQ(ERR_IO_PENDING,
3300 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3301 callback2.callback(), pool, BoundNetLog()));
3302 EXPECT_TRUE(pool->IsStalled());
3304 // Running the message loop should cause the socket pool to ask the SPDY
3305 // session to close an idle socket, but since the socket is in use, nothing
3306 // happens.
3307 base::RunLoop().RunUntilIdle();
3308 EXPECT_TRUE(pool->IsStalled());
3309 EXPECT_FALSE(callback2.have_result());
3311 // Cancelling the request should result in the session's socket being
3312 // closed, since the pool is stalled.
3313 ASSERT_TRUE(spdy_stream1.get());
3314 spdy_stream1->Cancel();
3315 base::RunLoop().RunUntilIdle();
3316 ASSERT_FALSE(pool->IsStalled());
3317 EXPECT_EQ(OK, callback2.WaitForResult());
3320 // Verify that SpdySessionKey and therefore SpdySession is different when
3321 // privacy mode is enabled or disabled.
3322 TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3323 CreateDeterministicNetworkSession();
3325 HostPortPair host_port_pair("www.google.com", 443);
3326 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3327 PRIVACY_MODE_ENABLED);
3328 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3329 PRIVACY_MODE_DISABLED);
3331 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3332 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3334 // Add SpdySession with PrivacyMode Enabled to the pool.
3335 base::WeakPtr<SpdySession> session_privacy_enabled =
3336 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3338 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3339 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3341 // Add SpdySession with PrivacyMode Disabled to the pool.
3342 base::WeakPtr<SpdySession> session_privacy_disabled =
3343 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3345 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3346 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3348 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3349 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3350 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3352 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3353 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3354 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3357 // Delegate that creates another stream when its stream is closed.
3358 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3359 public:
3360 StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3361 const base::WeakPtr<SpdySession>& session)
3362 : StreamDelegateDoNothing(stream),
3363 session_(session) {}
3365 ~StreamCreatingDelegate() override {}
3367 void OnClose(int status) override {
3368 GURL url(kDefaultURL);
3369 ignore_result(
3370 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3371 session_, url, MEDIUM, BoundNetLog()));
3374 private:
3375 const base::WeakPtr<SpdySession> session_;
3378 // Create another stream in response to a stream being reset. Nothing
3379 // should blow up. This is a regression test for
3380 // http://crbug.com/263690 .
3381 TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3382 session_deps_.host_resolver->set_synchronous_mode(true);
3384 MockConnect connect_data(SYNCHRONOUS, OK);
3386 scoped_ptr<SpdyFrame> req(
3387 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3388 MockWrite writes[] = {
3389 CreateMockWrite(*req, 0),
3392 scoped_ptr<SpdyFrame> rst(
3393 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3394 MockRead reads[] = {
3395 CreateMockRead(*rst, 1),
3396 MockRead(ASYNC, 0, 2) // EOF
3398 DeterministicSocketData data(reads, arraysize(reads),
3399 writes, arraysize(writes));
3400 data.set_connect_data(connect_data);
3401 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3403 CreateDeterministicNetworkSession();
3405 base::WeakPtr<SpdySession> session =
3406 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3408 GURL url(kDefaultURL);
3409 base::WeakPtr<SpdyStream> spdy_stream =
3410 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3411 session, url, MEDIUM, BoundNetLog());
3412 ASSERT_TRUE(spdy_stream.get() != NULL);
3413 EXPECT_EQ(0u, spdy_stream->stream_id());
3415 StreamCreatingDelegate delegate(spdy_stream, session);
3416 spdy_stream->SetDelegate(&delegate);
3418 scoped_ptr<SpdyHeaderBlock> headers(
3419 spdy_util_.ConstructGetHeaderBlock(url.spec()));
3420 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3421 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3423 EXPECT_EQ(0u, spdy_stream->stream_id());
3425 data.RunFor(1);
3427 EXPECT_EQ(1u, spdy_stream->stream_id());
3429 // Cause the stream to be reset, which should cause another stream
3430 // to be created.
3431 data.RunFor(1);
3433 EXPECT_EQ(NULL, spdy_stream.get());
3434 EXPECT_TRUE(delegate.StreamIsClosed());
3435 EXPECT_EQ(0u, session->num_active_streams());
3436 EXPECT_EQ(1u, session->num_created_streams());
3439 // The tests below are only for SPDY/3 and above.
3441 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3442 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3443 // gets sent.
3444 SettingsMap new_settings;
3445 int32 window_size = 1;
3446 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3447 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3449 // Set up the socket so we read a SETTINGS frame that sets
3450 // INITIAL_WINDOW_SIZE.
3451 MockConnect connect_data(SYNCHRONOUS, OK);
3452 scoped_ptr<SpdyFrame> settings_frame(
3453 spdy_util_.ConstructSpdySettings(new_settings));
3454 MockRead reads[] = {
3455 CreateMockRead(*settings_frame, 0),
3456 MockRead(ASYNC, 0, 1) // EOF
3459 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3460 MockWrite writes[] = {
3461 CreateMockWrite(*settings_ack, 2),
3464 session_deps_.host_resolver->set_synchronous_mode(true);
3466 DeterministicSocketData data(reads, arraysize(reads),
3467 writes, arraysize(writes));
3468 data.set_connect_data(connect_data);
3469 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3471 CreateDeterministicNetworkSession();
3473 base::WeakPtr<SpdySession> session =
3474 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3475 base::WeakPtr<SpdyStream> spdy_stream1 =
3476 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3477 session, test_url_, MEDIUM, BoundNetLog());
3478 ASSERT_TRUE(spdy_stream1.get() != NULL);
3479 TestCompletionCallback callback1;
3480 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3482 data.RunFor(1); // Process the SETTINGS frame, but not the EOF
3483 base::MessageLoop::current()->RunUntilIdle();
3484 EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3485 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3487 // Release the first one, this will allow the second to be created.
3488 spdy_stream1->Cancel();
3489 EXPECT_EQ(NULL, spdy_stream1.get());
3491 base::WeakPtr<SpdyStream> spdy_stream2 =
3492 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3493 session, test_url_, MEDIUM, BoundNetLog());
3494 ASSERT_TRUE(spdy_stream2.get() != NULL);
3495 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3496 spdy_stream2->Cancel();
3497 EXPECT_EQ(NULL, spdy_stream2.get());
3500 // The tests below are only for SPDY/3.1 and above.
3502 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3503 // adjust the session receive window size for SPDY 3.1 and higher. In
3504 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3505 // sending a WINDOW_UPDATE frame for a large enough delta.
3506 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3507 if (GetParam() < kProtoSPDY31)
3508 return;
3510 session_deps_.host_resolver->set_synchronous_mode(true);
3512 const int32 initial_window_size =
3513 SpdySession::GetInitialWindowSize(GetParam());
3514 const int32 delta_window_size = 100;
3516 MockConnect connect_data(SYNCHRONOUS, OK);
3517 MockRead reads[] = {
3518 MockRead(ASYNC, 0, 1) // EOF
3520 scoped_ptr<SpdyFrame> window_update(spdy_util_.ConstructSpdyWindowUpdate(
3521 kSessionFlowControlStreamId, initial_window_size + delta_window_size));
3522 MockWrite writes[] = {
3523 CreateMockWrite(*window_update, 0),
3525 DeterministicSocketData data(reads, arraysize(reads),
3526 writes, arraysize(writes));
3527 data.set_connect_data(connect_data);
3528 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3530 CreateDeterministicNetworkSession();
3531 base::WeakPtr<SpdySession> session =
3532 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3533 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3534 session->flow_control_state());
3536 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3537 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3539 session->IncreaseRecvWindowSize(delta_window_size);
3540 EXPECT_EQ(initial_window_size + delta_window_size,
3541 session->session_recv_window_size_);
3542 EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3544 // Should trigger sending a WINDOW_UPDATE frame.
3545 session->IncreaseRecvWindowSize(initial_window_size);
3546 EXPECT_EQ(initial_window_size + delta_window_size + initial_window_size,
3547 session->session_recv_window_size_);
3548 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3550 data.RunFor(1);
3552 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3553 session->in_io_loop_ = true;
3554 session->DecreaseRecvWindowSize(initial_window_size + delta_window_size +
3555 initial_window_size);
3556 session->in_io_loop_ = false;
3557 EXPECT_EQ(0, session->session_recv_window_size_);
3558 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3561 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3562 // adjust the session send window size when the "enable_spdy_31" flag
3563 // is set.
3564 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3565 if (GetParam() < kProtoSPDY31)
3566 return;
3568 session_deps_.host_resolver->set_synchronous_mode(true);
3570 MockConnect connect_data(SYNCHRONOUS, OK);
3571 MockRead reads[] = {
3572 MockRead(SYNCHRONOUS, 0, 0) // EOF
3574 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3575 data.set_connect_data(connect_data);
3576 session_deps_.socket_factory->AddSocketDataProvider(&data);
3578 CreateNetworkSession();
3579 base::WeakPtr<SpdySession> session =
3580 CreateFakeSpdySession(spdy_session_pool_, key_);
3581 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3582 session->flow_control_state());
3584 const int32 initial_window_size =
3585 SpdySession::GetInitialWindowSize(GetParam());
3586 const int32 delta_window_size = 100;
3588 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3590 session->IncreaseSendWindowSize(delta_window_size);
3591 EXPECT_EQ(initial_window_size + delta_window_size,
3592 session->session_send_window_size_);
3594 session->DecreaseSendWindowSize(delta_window_size);
3595 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3598 // Incoming data for an inactive stream should not cause the session
3599 // receive window size to decrease, but it should cause the unacked
3600 // bytes to increase.
3601 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3602 if (GetParam() < kProtoSPDY31)
3603 return;
3605 session_deps_.host_resolver->set_synchronous_mode(true);
3607 MockConnect connect_data(SYNCHRONOUS, OK);
3608 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3609 MockRead reads[] = {
3610 CreateMockRead(*resp, 0),
3611 MockRead(ASYNC, 0, 1) // EOF
3613 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3614 data.set_connect_data(connect_data);
3615 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3617 CreateDeterministicNetworkSession();
3618 base::WeakPtr<SpdySession> session =
3619 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3620 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3621 session->flow_control_state());
3623 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3624 session->session_recv_window_size_);
3625 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3627 data.RunFor(1);
3629 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3630 session->session_recv_window_size_);
3631 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3633 data.RunFor(1);
3636 // A delegate that drops any received data.
3637 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3638 public:
3639 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3640 base::StringPiece data)
3641 : StreamDelegateSendImmediate(stream, data) {}
3643 ~DropReceivedDataDelegate() override {}
3645 // Drop any received data.
3646 void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override {}
3649 // Send data back and forth but use a delegate that drops its received
3650 // data. The receive window should still increase to its original
3651 // value, i.e. we shouldn't "leak" receive window bytes.
3652 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3653 if (GetParam() < kProtoSPDY31)
3654 return;
3656 const char kStreamUrl[] = "http://www.google.com/";
3658 const int32 msg_data_size = 100;
3659 const std::string msg_data(msg_data_size, 'a');
3661 MockConnect connect_data(SYNCHRONOUS, OK);
3663 scoped_ptr<SpdyFrame> req(
3664 spdy_util_.ConstructSpdyPost(
3665 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3666 scoped_ptr<SpdyFrame> msg(
3667 spdy_util_.ConstructSpdyBodyFrame(
3668 1, msg_data.data(), msg_data_size, false));
3669 MockWrite writes[] = {
3670 CreateMockWrite(*req, 0),
3671 CreateMockWrite(*msg, 2),
3674 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3675 scoped_ptr<SpdyFrame> echo(
3676 spdy_util_.ConstructSpdyBodyFrame(
3677 1, msg_data.data(), msg_data_size, false));
3678 scoped_ptr<SpdyFrame> window_update(
3679 spdy_util_.ConstructSpdyWindowUpdate(
3680 kSessionFlowControlStreamId, msg_data_size));
3681 MockRead reads[] = {
3682 CreateMockRead(*resp, 1),
3683 CreateMockRead(*echo, 3),
3684 MockRead(ASYNC, 0, 4) // EOF
3687 // Create SpdySession and SpdyStream and send the request.
3688 DeterministicSocketData data(reads, arraysize(reads),
3689 writes, arraysize(writes));
3690 data.set_connect_data(connect_data);
3691 session_deps_.host_resolver->set_synchronous_mode(true);
3692 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3694 CreateDeterministicNetworkSession();
3696 base::WeakPtr<SpdySession> session =
3697 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3699 GURL url(kStreamUrl);
3700 base::WeakPtr<SpdyStream> stream =
3701 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3702 session, url, MEDIUM, BoundNetLog());
3703 ASSERT_TRUE(stream.get() != NULL);
3704 EXPECT_EQ(0u, stream->stream_id());
3706 DropReceivedDataDelegate delegate(stream, msg_data);
3707 stream->SetDelegate(&delegate);
3709 scoped_ptr<SpdyHeaderBlock> headers(
3710 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3711 EXPECT_EQ(ERR_IO_PENDING,
3712 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3713 EXPECT_TRUE(stream->HasUrlFromHeaders());
3715 const int32 initial_window_size =
3716 SpdySession::GetInitialWindowSize(GetParam());
3717 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3718 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3720 data.RunFor(4);
3722 EXPECT_TRUE(data.at_write_eof());
3723 EXPECT_TRUE(data.at_read_eof());
3725 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3726 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3728 stream->Close();
3729 EXPECT_EQ(NULL, stream.get());
3731 EXPECT_EQ(OK, delegate.WaitForClose());
3733 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3734 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3737 // Send data back and forth but close the stream before its data frame
3738 // can be written to the socket. The send window should then increase
3739 // to its original value, i.e. we shouldn't "leak" send window bytes.
3740 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3741 if (GetParam() < kProtoSPDY31)
3742 return;
3744 const char kStreamUrl[] = "http://www.google.com/";
3746 const int32 msg_data_size = 100;
3747 const std::string msg_data(msg_data_size, 'a');
3749 MockConnect connect_data(SYNCHRONOUS, OK);
3751 scoped_ptr<SpdyFrame> req(
3752 spdy_util_.ConstructSpdyPost(
3753 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3754 MockWrite writes[] = {
3755 CreateMockWrite(*req, 0),
3758 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3759 MockRead reads[] = {
3760 CreateMockRead(*resp, 1),
3761 MockRead(ASYNC, 0, 2) // EOF
3764 // Create SpdySession and SpdyStream and send the request.
3765 DeterministicSocketData data(reads, arraysize(reads),
3766 writes, arraysize(writes));
3767 data.set_connect_data(connect_data);
3768 session_deps_.host_resolver->set_synchronous_mode(true);
3769 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3771 CreateDeterministicNetworkSession();
3773 base::WeakPtr<SpdySession> session =
3774 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3776 GURL url(kStreamUrl);
3777 base::WeakPtr<SpdyStream> stream =
3778 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3779 session, url, MEDIUM, BoundNetLog());
3780 ASSERT_TRUE(stream.get() != NULL);
3781 EXPECT_EQ(0u, stream->stream_id());
3783 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3784 stream->SetDelegate(&delegate);
3786 scoped_ptr<SpdyHeaderBlock> headers(
3787 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3788 EXPECT_EQ(ERR_IO_PENDING,
3789 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3790 EXPECT_TRUE(stream->HasUrlFromHeaders());
3792 const int32 initial_window_size =
3793 SpdySession::GetInitialWindowSize(GetParam());
3794 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3796 data.RunFor(1);
3798 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3800 data.RunFor(1);
3802 EXPECT_TRUE(data.at_write_eof());
3803 EXPECT_TRUE(data.at_read_eof());
3805 EXPECT_EQ(initial_window_size - msg_data_size,
3806 session->session_send_window_size_);
3808 // Closing the stream should increase the session's send window.
3809 stream->Close();
3810 EXPECT_EQ(NULL, stream.get());
3812 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3814 EXPECT_EQ(OK, delegate.WaitForClose());
3817 // Send data back and forth; the send and receive windows should
3818 // change appropriately.
3819 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
3820 if (GetParam() < kProtoSPDY31)
3821 return;
3823 const char kStreamUrl[] = "http://www.google.com/";
3825 const int32 msg_data_size = 100;
3826 const std::string msg_data(msg_data_size, 'a');
3828 MockConnect connect_data(SYNCHRONOUS, OK);
3830 scoped_ptr<SpdyFrame> req(
3831 spdy_util_.ConstructSpdyPost(
3832 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3833 scoped_ptr<SpdyFrame> msg(
3834 spdy_util_.ConstructSpdyBodyFrame(
3835 1, msg_data.data(), msg_data_size, false));
3836 MockWrite writes[] = {
3837 CreateMockWrite(*req, 0),
3838 CreateMockWrite(*msg, 2),
3841 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3842 scoped_ptr<SpdyFrame> echo(
3843 spdy_util_.ConstructSpdyBodyFrame(
3844 1, msg_data.data(), msg_data_size, false));
3845 scoped_ptr<SpdyFrame> window_update(
3846 spdy_util_.ConstructSpdyWindowUpdate(
3847 kSessionFlowControlStreamId, msg_data_size));
3848 MockRead reads[] = {
3849 CreateMockRead(*resp, 1),
3850 CreateMockRead(*echo, 3),
3851 CreateMockRead(*window_update, 4),
3852 MockRead(ASYNC, 0, 5) // EOF
3855 // Create SpdySession and SpdyStream and send the request.
3856 DeterministicSocketData data(reads, arraysize(reads),
3857 writes, arraysize(writes));
3858 data.set_connect_data(connect_data);
3859 session_deps_.host_resolver->set_synchronous_mode(true);
3860 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3862 CreateDeterministicNetworkSession();
3864 base::WeakPtr<SpdySession> session =
3865 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3867 GURL url(kStreamUrl);
3868 base::WeakPtr<SpdyStream> stream =
3869 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3870 session, url, MEDIUM, BoundNetLog());
3871 ASSERT_TRUE(stream.get() != NULL);
3872 EXPECT_EQ(0u, stream->stream_id());
3874 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3875 stream->SetDelegate(&delegate);
3877 scoped_ptr<SpdyHeaderBlock> headers(
3878 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3879 EXPECT_EQ(ERR_IO_PENDING,
3880 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3881 EXPECT_TRUE(stream->HasUrlFromHeaders());
3883 const int32 initial_window_size =
3884 SpdySession::GetInitialWindowSize(GetParam());
3885 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3886 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3887 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3889 data.RunFor(1);
3891 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3892 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3893 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3895 data.RunFor(1);
3897 EXPECT_EQ(initial_window_size - msg_data_size,
3898 session->session_send_window_size_);
3899 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3900 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3902 data.RunFor(1);
3904 EXPECT_EQ(initial_window_size - msg_data_size,
3905 session->session_send_window_size_);
3906 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3907 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3909 data.RunFor(1);
3911 EXPECT_EQ(initial_window_size - msg_data_size,
3912 session->session_send_window_size_);
3913 EXPECT_EQ(initial_window_size - msg_data_size,
3914 session->session_recv_window_size_);
3915 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3917 data.RunFor(1);
3919 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3920 EXPECT_EQ(initial_window_size - msg_data_size,
3921 session->session_recv_window_size_);
3922 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3924 EXPECT_TRUE(data.at_write_eof());
3925 EXPECT_TRUE(data.at_read_eof());
3927 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
3929 // Draining the delegate's read queue should increase the session's
3930 // receive window.
3931 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3932 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3933 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3935 stream->Close();
3936 EXPECT_EQ(NULL, stream.get());
3938 EXPECT_EQ(OK, delegate.WaitForClose());
3940 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3941 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3942 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3945 // Given a stall function and an unstall function, runs a test to make
3946 // sure that a stream resumes after unstall.
3947 void SpdySessionTest::RunResumeAfterUnstallTest(
3948 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
3949 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
3950 unstall_function) {
3951 const char kStreamUrl[] = "http://www.google.com/";
3952 GURL url(kStreamUrl);
3954 session_deps_.host_resolver->set_synchronous_mode(true);
3956 scoped_ptr<SpdyFrame> req(
3957 spdy_util_.ConstructSpdyPost(
3958 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3959 scoped_ptr<SpdyFrame> body(
3960 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3961 MockWrite writes[] = {
3962 CreateMockWrite(*req, 0),
3963 CreateMockWrite(*body, 1),
3966 scoped_ptr<SpdyFrame> resp(
3967 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3968 scoped_ptr<SpdyFrame> echo(
3969 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
3970 MockRead reads[] = {
3971 CreateMockRead(*resp, 2),
3972 MockRead(ASYNC, 0, 0, 3), // EOF
3975 DeterministicSocketData data(reads, arraysize(reads),
3976 writes, arraysize(writes));
3977 MockConnect connect_data(SYNCHRONOUS, OK);
3978 data.set_connect_data(connect_data);
3980 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3982 CreateDeterministicNetworkSession();
3983 base::WeakPtr<SpdySession> session =
3984 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3985 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3986 session->flow_control_state());
3988 base::WeakPtr<SpdyStream> stream =
3989 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3990 session, url, LOWEST, BoundNetLog());
3991 ASSERT_TRUE(stream.get() != NULL);
3993 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
3994 stream->SetDelegate(&delegate);
3996 EXPECT_FALSE(stream->HasUrlFromHeaders());
3997 EXPECT_FALSE(stream->send_stalled_by_flow_control());
3999 scoped_ptr<SpdyHeaderBlock> headers(
4000 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4001 EXPECT_EQ(ERR_IO_PENDING,
4002 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4003 EXPECT_TRUE(stream->HasUrlFromHeaders());
4004 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
4006 stall_function.Run(session.get(), stream.get());
4008 data.RunFor(1);
4010 EXPECT_TRUE(stream->send_stalled_by_flow_control());
4012 unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
4014 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4016 data.RunFor(3);
4018 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
4020 EXPECT_TRUE(delegate.send_headers_completed());
4021 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
4022 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
4023 EXPECT_TRUE(data.at_write_eof());
4026 // Run the resume-after-unstall test with all possible stall and
4027 // unstall sequences.
4029 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
4030 if (GetParam() < kProtoSPDY31)
4031 return;
4033 RunResumeAfterUnstallTest(
4034 base::Bind(&SpdySessionTest::StallSessionOnly,
4035 base::Unretained(this)),
4036 base::Bind(&SpdySessionTest::UnstallSessionOnly,
4037 base::Unretained(this)));
4040 // Equivalent to
4041 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4042 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
4043 if (GetParam() < kProtoSPDY31)
4044 return;
4046 RunResumeAfterUnstallTest(
4047 base::Bind(&SpdySessionTest::StallStreamOnly,
4048 base::Unretained(this)),
4049 base::Bind(&SpdySessionTest::UnstallStreamOnly,
4050 base::Unretained(this)));
4053 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4054 if (GetParam() < kProtoSPDY31)
4055 return;
4057 RunResumeAfterUnstallTest(
4058 base::Bind(&SpdySessionTest::StallSessionStream,
4059 base::Unretained(this)),
4060 base::Bind(&SpdySessionTest::UnstallSessionStream,
4061 base::Unretained(this)));
4064 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4065 if (GetParam() < kProtoSPDY31)
4066 return;
4068 RunResumeAfterUnstallTest(
4069 base::Bind(&SpdySessionTest::StallStreamSession,
4070 base::Unretained(this)),
4071 base::Bind(&SpdySessionTest::UnstallSessionStream,
4072 base::Unretained(this)));
4075 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4076 if (GetParam() < kProtoSPDY31)
4077 return;
4079 RunResumeAfterUnstallTest(
4080 base::Bind(&SpdySessionTest::StallStreamSession,
4081 base::Unretained(this)),
4082 base::Bind(&SpdySessionTest::UnstallStreamSession,
4083 base::Unretained(this)));
4086 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4087 if (GetParam() < kProtoSPDY31)
4088 return;
4090 RunResumeAfterUnstallTest(
4091 base::Bind(&SpdySessionTest::StallSessionStream,
4092 base::Unretained(this)),
4093 base::Bind(&SpdySessionTest::UnstallStreamSession,
4094 base::Unretained(this)));
4097 // Cause a stall by reducing the flow control send window to 0. The
4098 // streams should resume in priority order when that window is then
4099 // increased.
4100 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4101 if (GetParam() < kProtoSPDY31)
4102 return;
4104 const char kStreamUrl[] = "http://www.google.com/";
4105 GURL url(kStreamUrl);
4107 session_deps_.host_resolver->set_synchronous_mode(true);
4109 scoped_ptr<SpdyFrame> req1(
4110 spdy_util_.ConstructSpdyPost(
4111 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4112 scoped_ptr<SpdyFrame> req2(
4113 spdy_util_.ConstructSpdyPost(
4114 kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
4115 scoped_ptr<SpdyFrame> body1(
4116 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4117 scoped_ptr<SpdyFrame> body2(
4118 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4119 MockWrite writes[] = {
4120 CreateMockWrite(*req1, 0),
4121 CreateMockWrite(*req2, 1),
4122 CreateMockWrite(*body2, 2),
4123 CreateMockWrite(*body1, 3),
4126 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4127 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4128 MockRead reads[] = {
4129 CreateMockRead(*resp1, 4),
4130 CreateMockRead(*resp2, 5),
4131 MockRead(ASYNC, 0, 0, 6), // EOF
4134 DeterministicSocketData data(reads, arraysize(reads),
4135 writes, arraysize(writes));
4136 MockConnect connect_data(SYNCHRONOUS, OK);
4137 data.set_connect_data(connect_data);
4139 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4141 CreateDeterministicNetworkSession();
4142 base::WeakPtr<SpdySession> session =
4143 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4144 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4145 session->flow_control_state());
4147 base::WeakPtr<SpdyStream> stream1 =
4148 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4149 session, url, LOWEST, BoundNetLog());
4150 ASSERT_TRUE(stream1.get() != NULL);
4152 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4153 stream1->SetDelegate(&delegate1);
4155 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4157 base::WeakPtr<SpdyStream> stream2 =
4158 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4159 session, url, MEDIUM, BoundNetLog());
4160 ASSERT_TRUE(stream2.get() != NULL);
4162 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4163 stream2->SetDelegate(&delegate2);
4165 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4167 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4168 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4170 StallSessionSend(session.get());
4172 scoped_ptr<SpdyHeaderBlock> headers1(
4173 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4174 EXPECT_EQ(ERR_IO_PENDING,
4175 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4176 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4177 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4179 data.RunFor(1);
4180 EXPECT_EQ(1u, stream1->stream_id());
4181 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4183 scoped_ptr<SpdyHeaderBlock> headers2(
4184 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4185 EXPECT_EQ(ERR_IO_PENDING,
4186 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4187 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4188 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4190 data.RunFor(1);
4191 EXPECT_EQ(3u, stream2->stream_id());
4192 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4194 // This should unstall only stream2.
4195 UnstallSessionSend(session.get(), kBodyDataSize);
4197 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4198 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4200 data.RunFor(1);
4202 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4203 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4205 // This should then unstall stream1.
4206 UnstallSessionSend(session.get(), kBodyDataSize);
4208 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4209 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4211 data.RunFor(4);
4213 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4214 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4216 EXPECT_TRUE(delegate1.send_headers_completed());
4217 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4218 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4220 EXPECT_TRUE(delegate2.send_headers_completed());
4221 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4222 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4224 EXPECT_TRUE(data.at_write_eof());
4227 // Delegate that closes a given stream after sending its body.
4228 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4229 public:
4230 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4231 base::StringPiece data)
4232 : StreamDelegateWithBody(stream, data) {}
4234 ~StreamClosingDelegate() override {}
4236 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4237 stream_to_close_ = stream_to_close;
4240 void OnDataSent() override {
4241 test::StreamDelegateWithBody::OnDataSent();
4242 if (stream_to_close_.get()) {
4243 stream_to_close_->Close();
4244 EXPECT_EQ(NULL, stream_to_close_.get());
4248 private:
4249 base::WeakPtr<SpdyStream> stream_to_close_;
4252 // Cause a stall by reducing the flow control send window to
4253 // 0. Unstalling the session should properly handle deleted streams.
4254 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4255 if (GetParam() < kProtoSPDY31)
4256 return;
4258 const char kStreamUrl[] = "http://www.google.com/";
4259 GURL url(kStreamUrl);
4261 session_deps_.host_resolver->set_synchronous_mode(true);
4263 scoped_ptr<SpdyFrame> req1(
4264 spdy_util_.ConstructSpdyPost(
4265 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4266 scoped_ptr<SpdyFrame> req2(
4267 spdy_util_.ConstructSpdyPost(
4268 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4269 scoped_ptr<SpdyFrame> req3(
4270 spdy_util_.ConstructSpdyPost(
4271 kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
4272 scoped_ptr<SpdyFrame> body2(
4273 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4274 MockWrite writes[] = {
4275 CreateMockWrite(*req1, 0),
4276 CreateMockWrite(*req2, 1),
4277 CreateMockWrite(*req3, 2),
4278 CreateMockWrite(*body2, 3),
4281 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4282 MockRead reads[] = {
4283 CreateMockRead(*resp2, 4),
4284 MockRead(ASYNC, 0, 0, 5), // EOF
4287 DeterministicSocketData data(reads, arraysize(reads),
4288 writes, arraysize(writes));
4289 MockConnect connect_data(SYNCHRONOUS, OK);
4290 data.set_connect_data(connect_data);
4292 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4294 CreateDeterministicNetworkSession();
4295 base::WeakPtr<SpdySession> session =
4296 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4297 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4298 session->flow_control_state());
4300 base::WeakPtr<SpdyStream> stream1 =
4301 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4302 session, url, LOWEST, BoundNetLog());
4303 ASSERT_TRUE(stream1.get() != NULL);
4305 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4306 stream1->SetDelegate(&delegate1);
4308 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4310 base::WeakPtr<SpdyStream> stream2 =
4311 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4312 session, url, LOWEST, BoundNetLog());
4313 ASSERT_TRUE(stream2.get() != NULL);
4315 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4316 stream2->SetDelegate(&delegate2);
4318 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4320 base::WeakPtr<SpdyStream> stream3 =
4321 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4322 session, url, LOWEST, BoundNetLog());
4323 ASSERT_TRUE(stream3.get() != NULL);
4325 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4326 stream3->SetDelegate(&delegate3);
4328 EXPECT_FALSE(stream3->HasUrlFromHeaders());
4330 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4331 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4332 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4334 StallSessionSend(session.get());
4336 scoped_ptr<SpdyHeaderBlock> headers1(
4337 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4338 EXPECT_EQ(ERR_IO_PENDING,
4339 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4340 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4341 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4343 data.RunFor(1);
4344 EXPECT_EQ(1u, stream1->stream_id());
4345 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4347 scoped_ptr<SpdyHeaderBlock> headers2(
4348 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4349 EXPECT_EQ(ERR_IO_PENDING,
4350 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4351 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4352 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4354 data.RunFor(1);
4355 EXPECT_EQ(3u, stream2->stream_id());
4356 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4358 scoped_ptr<SpdyHeaderBlock> headers3(
4359 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4360 EXPECT_EQ(ERR_IO_PENDING,
4361 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4362 EXPECT_TRUE(stream3->HasUrlFromHeaders());
4363 EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4365 data.RunFor(1);
4366 EXPECT_EQ(5u, stream3->stream_id());
4367 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4369 SpdyStreamId stream_id1 = stream1->stream_id();
4370 SpdyStreamId stream_id2 = stream2->stream_id();
4371 SpdyStreamId stream_id3 = stream3->stream_id();
4373 // Close stream1 preemptively.
4374 session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4375 EXPECT_EQ(NULL, stream1.get());
4377 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4378 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4379 EXPECT_TRUE(session->IsStreamActive(stream_id3));
4381 // Unstall stream2, which should then close stream3.
4382 delegate2.set_stream_to_close(stream3);
4383 UnstallSessionSend(session.get(), kBodyDataSize);
4385 data.RunFor(1);
4386 EXPECT_EQ(NULL, stream3.get());
4388 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4389 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4390 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4391 EXPECT_FALSE(session->IsStreamActive(stream_id3));
4393 data.RunFor(2);
4394 EXPECT_EQ(NULL, stream2.get());
4396 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4397 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4398 EXPECT_EQ(OK, delegate3.WaitForClose());
4400 EXPECT_TRUE(delegate1.send_headers_completed());
4401 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4403 EXPECT_TRUE(delegate2.send_headers_completed());
4404 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4405 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4407 EXPECT_TRUE(delegate3.send_headers_completed());
4408 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4410 EXPECT_TRUE(data.at_write_eof());
4413 // Cause a stall by reducing the flow control send window to
4414 // 0. Unstalling the session should properly handle the session itself
4415 // being closed.
4416 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4417 if (GetParam() < kProtoSPDY31)
4418 return;
4420 const char kStreamUrl[] = "http://www.google.com/";
4421 GURL url(kStreamUrl);
4423 session_deps_.host_resolver->set_synchronous_mode(true);
4425 scoped_ptr<SpdyFrame> req1(
4426 spdy_util_.ConstructSpdyPost(
4427 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4428 scoped_ptr<SpdyFrame> req2(
4429 spdy_util_.ConstructSpdyPost(
4430 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4431 scoped_ptr<SpdyFrame> body1(
4432 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4433 MockWrite writes[] = {
4434 CreateMockWrite(*req1, 0),
4435 CreateMockWrite(*req2, 1),
4438 MockRead reads[] = {
4439 MockRead(ASYNC, 0, 0, 2), // EOF
4442 DeterministicSocketData data(reads, arraysize(reads),
4443 writes, arraysize(writes));
4444 MockConnect connect_data(SYNCHRONOUS, OK);
4445 data.set_connect_data(connect_data);
4447 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4449 CreateDeterministicNetworkSession();
4450 base::WeakPtr<SpdySession> session =
4451 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4452 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4453 session->flow_control_state());
4455 base::WeakPtr<SpdyStream> stream1 =
4456 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4457 session, url, LOWEST, BoundNetLog());
4458 ASSERT_TRUE(stream1.get() != NULL);
4460 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4461 stream1->SetDelegate(&delegate1);
4463 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4465 base::WeakPtr<SpdyStream> stream2 =
4466 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4467 session, url, LOWEST, BoundNetLog());
4468 ASSERT_TRUE(stream2.get() != NULL);
4470 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4471 stream2->SetDelegate(&delegate2);
4473 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4475 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4476 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4478 StallSessionSend(session.get());
4480 scoped_ptr<SpdyHeaderBlock> headers1(
4481 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4482 EXPECT_EQ(ERR_IO_PENDING,
4483 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4484 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4485 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4487 data.RunFor(1);
4488 EXPECT_EQ(1u, stream1->stream_id());
4489 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4491 scoped_ptr<SpdyHeaderBlock> headers2(
4492 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4493 EXPECT_EQ(ERR_IO_PENDING,
4494 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4495 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4496 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4498 data.RunFor(1);
4499 EXPECT_EQ(3u, stream2->stream_id());
4500 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4502 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4504 // Unstall stream1.
4505 UnstallSessionSend(session.get(), kBodyDataSize);
4507 // Close the session (since we can't do it from within the delegate
4508 // method, since it's in the stream's loop).
4509 session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4510 base::RunLoop().RunUntilIdle();
4511 EXPECT_TRUE(session == NULL);
4513 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4515 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4516 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4518 EXPECT_TRUE(delegate1.send_headers_completed());
4519 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4521 EXPECT_TRUE(delegate2.send_headers_completed());
4522 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4524 EXPECT_TRUE(data.at_write_eof());
4527 TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4528 if (GetParam() < kProtoSPDY31)
4529 return;
4531 MockConnect connect_data(SYNCHRONOUS, OK);
4533 scoped_ptr<SpdyFrame> req(
4534 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4535 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4537 GOAWAY_FLOW_CONTROL_ERROR,
4538 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4539 "the receive window size of 1"));
4540 MockWrite writes[] = {
4541 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
4544 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4545 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4546 MockRead reads[] = {
4547 CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
4550 DeterministicSocketData data(
4551 reads, arraysize(reads), writes, arraysize(writes));
4552 data.set_connect_data(connect_data);
4553 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4555 CreateDeterministicNetworkSession();
4557 base::WeakPtr<SpdySession> session =
4558 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4560 GURL url(kDefaultURL);
4561 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4562 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
4563 ASSERT_TRUE(spdy_stream.get() != NULL);
4564 test::StreamDelegateDoNothing delegate(spdy_stream);
4565 spdy_stream->SetDelegate(&delegate);
4567 scoped_ptr<SpdyHeaderBlock> headers(
4568 spdy_util_.ConstructGetHeaderBlock(url.spec()));
4569 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4571 data.RunFor(1); // Write request.
4573 // Put session on the edge of overflowing it's recv window.
4574 session->session_recv_window_size_ = 1;
4576 // Read response headers & body. Body overflows the session window, and a
4577 // goaway is written.
4578 data.RunFor(3);
4579 base::MessageLoop::current()->RunUntilIdle();
4581 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4582 EXPECT_TRUE(session == NULL);
4585 TEST_P(SpdySessionTest, SplitHeaders) {
4586 GURL kStreamUrl("http://www.google.com/foo.dat");
4587 SpdyHeaderBlock headers;
4588 spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4589 headers["alpha"] = "beta";
4591 SpdyHeaderBlock request_headers;
4592 SpdyHeaderBlock response_headers;
4594 SplitPushedHeadersToRequestAndResponse(
4595 headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4597 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4598 std::string alpha_val =
4599 (it == response_headers.end()) ? std::string() : it->second;
4600 EXPECT_EQ("beta", alpha_val);
4602 GURL request_url =
4603 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4604 EXPECT_EQ(kStreamUrl, request_url);
4607 // Regression. Sorta. Push streams and client streams were sharing a single
4608 // limit for a long time.
4609 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4610 SettingsMap new_settings;
4611 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4612 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4613 scoped_ptr<SpdyFrame> settings_frame(
4614 spdy_util_.ConstructSpdySettings(new_settings));
4615 scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4616 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4617 MockRead reads[] = {
4618 CreateMockRead(*settings_frame), CreateMockRead(*pushed, 3),
4619 MockRead(ASYNC, 0, 4),
4622 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4623 scoped_ptr<SpdyFrame> req(
4624 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4625 MockWrite writes[] = {
4626 CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4629 DeterministicSocketData data(
4630 reads, arraysize(reads), writes, arraysize(writes));
4631 MockConnect connect_data(SYNCHRONOUS, OK);
4632 data.set_connect_data(connect_data);
4633 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4635 CreateDeterministicNetworkSession();
4637 base::WeakPtr<SpdySession> session =
4638 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4640 // Read the settings frame.
4641 data.RunFor(1);
4643 GURL url1(kDefaultURL);
4644 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4645 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4646 ASSERT_TRUE(spdy_stream1.get() != NULL);
4647 EXPECT_EQ(0u, spdy_stream1->stream_id());
4648 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4649 spdy_stream1->SetDelegate(&delegate1);
4651 EXPECT_EQ(0u, session->num_active_streams());
4652 EXPECT_EQ(1u, session->num_created_streams());
4653 EXPECT_EQ(0u, session->num_pushed_streams());
4654 EXPECT_EQ(0u, session->num_active_pushed_streams());
4656 scoped_ptr<SpdyHeaderBlock> headers(
4657 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4658 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4659 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4661 // Run until 1st stream is activated.
4662 EXPECT_EQ(0u, delegate1.stream_id());
4663 data.RunFor(2);
4664 EXPECT_EQ(1u, delegate1.stream_id());
4665 EXPECT_EQ(1u, session->num_active_streams());
4666 EXPECT_EQ(0u, session->num_created_streams());
4667 EXPECT_EQ(0u, session->num_pushed_streams());
4668 EXPECT_EQ(0u, session->num_active_pushed_streams());
4670 // Run until pushed stream is created.
4671 data.RunFor(1);
4672 EXPECT_EQ(2u, session->num_active_streams());
4673 EXPECT_EQ(0u, session->num_created_streams());
4674 EXPECT_EQ(1u, session->num_pushed_streams());
4675 EXPECT_EQ(1u, session->num_active_pushed_streams());
4677 // Second stream should not be stalled, although we have 2 active streams, but
4678 // one of them is push stream and should not be taken into account when we
4679 // create streams on the client.
4680 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4681 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4682 EXPECT_TRUE(spdy_stream2.get() != NULL);
4683 EXPECT_EQ(2u, session->num_active_streams());
4684 EXPECT_EQ(1u, session->num_created_streams());
4685 EXPECT_EQ(1u, session->num_pushed_streams());
4686 EXPECT_EQ(1u, session->num_active_pushed_streams());
4688 // Read EOF.
4689 data.RunFor(1);
4692 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4693 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4694 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4695 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4696 NULL, 0, 4, 1, "http://www.google.com/b.dat"));
4697 MockRead reads[] = {
4698 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4699 MockRead(ASYNC, 0, 4),
4702 scoped_ptr<SpdyFrame> req(
4703 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4704 scoped_ptr<SpdyFrame> rst(
4705 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4706 MockWrite writes[] = {
4707 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4710 DeterministicSocketData data(
4711 reads, arraysize(reads), writes, arraysize(writes));
4712 MockConnect connect_data(SYNCHRONOUS, OK);
4713 data.set_connect_data(connect_data);
4714 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4716 CreateDeterministicNetworkSession();
4718 base::WeakPtr<SpdySession> session =
4719 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4720 session->set_max_concurrent_pushed_streams(1);
4722 GURL url1(kDefaultURL);
4723 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4724 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4725 ASSERT_TRUE(spdy_stream1.get() != NULL);
4726 EXPECT_EQ(0u, spdy_stream1->stream_id());
4727 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4728 spdy_stream1->SetDelegate(&delegate1);
4730 EXPECT_EQ(0u, session->num_active_streams());
4731 EXPECT_EQ(1u, session->num_created_streams());
4732 EXPECT_EQ(0u, session->num_pushed_streams());
4733 EXPECT_EQ(0u, session->num_active_pushed_streams());
4735 scoped_ptr<SpdyHeaderBlock> headers(
4736 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4737 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4738 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4740 // Run until 1st stream is activated.
4741 EXPECT_EQ(0u, delegate1.stream_id());
4742 data.RunFor(1);
4743 EXPECT_EQ(1u, delegate1.stream_id());
4744 EXPECT_EQ(1u, session->num_active_streams());
4745 EXPECT_EQ(0u, session->num_created_streams());
4746 EXPECT_EQ(0u, session->num_pushed_streams());
4747 EXPECT_EQ(0u, session->num_active_pushed_streams());
4749 // Run until pushed stream is created.
4750 data.RunFor(1);
4751 EXPECT_EQ(2u, session->num_active_streams());
4752 EXPECT_EQ(0u, session->num_created_streams());
4753 EXPECT_EQ(1u, session->num_pushed_streams());
4754 EXPECT_EQ(1u, session->num_active_pushed_streams());
4756 // Reset incoming pushed stream.
4757 data.RunFor(2);
4758 EXPECT_EQ(2u, session->num_active_streams());
4759 EXPECT_EQ(0u, session->num_created_streams());
4760 EXPECT_EQ(1u, session->num_pushed_streams());
4761 EXPECT_EQ(1u, session->num_active_pushed_streams());
4763 // Read EOF.
4764 data.RunFor(1);
4767 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4768 // Streams in reserved remote state exist only in SPDY4.
4769 if (spdy_util_.spdy_version() < SPDY4)
4770 return;
4772 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4773 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4774 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4775 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
4776 push_headers.get());
4777 scoped_ptr<SpdyFrame> push_b(
4778 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4779 scoped_ptr<SpdyFrame> headers_b(
4780 spdy_util_.ConstructSpdyPushHeaders(4, NULL, 0));
4781 MockRead reads[] = {
4782 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4783 CreateMockRead(*headers_b, 3), MockRead(ASYNC, 0, 5),
4786 scoped_ptr<SpdyFrame> req(
4787 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4788 scoped_ptr<SpdyFrame> rst(
4789 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4790 MockWrite writes[] = {
4791 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
4794 DeterministicSocketData data(
4795 reads, arraysize(reads), writes, arraysize(writes));
4796 MockConnect connect_data(SYNCHRONOUS, OK);
4797 data.set_connect_data(connect_data);
4798 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4800 CreateDeterministicNetworkSession();
4802 base::WeakPtr<SpdySession> session =
4803 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4804 session->set_max_concurrent_pushed_streams(1);
4806 GURL url1(kDefaultURL);
4807 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4808 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4809 ASSERT_TRUE(spdy_stream1.get() != NULL);
4810 EXPECT_EQ(0u, spdy_stream1->stream_id());
4811 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4812 spdy_stream1->SetDelegate(&delegate1);
4814 EXPECT_EQ(0u, session->num_active_streams());
4815 EXPECT_EQ(1u, session->num_created_streams());
4816 EXPECT_EQ(0u, session->num_pushed_streams());
4817 EXPECT_EQ(0u, session->num_active_pushed_streams());
4819 scoped_ptr<SpdyHeaderBlock> headers(
4820 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4821 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4822 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4824 // Run until 1st stream is activated.
4825 EXPECT_EQ(0u, delegate1.stream_id());
4826 data.RunFor(1);
4827 EXPECT_EQ(1u, delegate1.stream_id());
4828 EXPECT_EQ(1u, session->num_active_streams());
4829 EXPECT_EQ(0u, session->num_created_streams());
4830 EXPECT_EQ(0u, session->num_pushed_streams());
4831 EXPECT_EQ(0u, session->num_active_pushed_streams());
4833 // Run until pushed stream is created.
4834 data.RunFor(1);
4835 EXPECT_EQ(2u, session->num_active_streams());
4836 EXPECT_EQ(0u, session->num_created_streams());
4837 EXPECT_EQ(1u, session->num_pushed_streams());
4838 EXPECT_EQ(1u, session->num_active_pushed_streams());
4840 // Accept promised stream. It should not count towards pushed stream limit.
4841 data.RunFor(1);
4842 EXPECT_EQ(3u, session->num_active_streams());
4843 EXPECT_EQ(0u, session->num_created_streams());
4844 EXPECT_EQ(2u, session->num_pushed_streams());
4845 EXPECT_EQ(1u, session->num_active_pushed_streams());
4847 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4848 // while we accept only one.
4849 data.RunFor(2);
4850 EXPECT_EQ(2u, session->num_active_streams());
4851 EXPECT_EQ(0u, session->num_created_streams());
4852 EXPECT_EQ(1u, session->num_pushed_streams());
4853 EXPECT_EQ(1u, session->num_active_pushed_streams());
4855 // Read EOF.
4856 data.RunFor(1);
4859 TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
4860 // Streams in reserved remote state exist only in SPDY4.
4861 if (spdy_util_.spdy_version() < SPDY4)
4862 return;
4864 const char kPushedUrl[] = "http://www.google.com/a.dat";
4865 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4866 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
4867 scoped_ptr<SpdyFrame> push_promise(
4868 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
4869 scoped_ptr<SpdyFrame> headers_frame(
4870 spdy_util_.ConstructSpdyPushHeaders(2, NULL, 0));
4871 MockRead reads[] = {
4872 CreateMockRead(*push_promise, 1), CreateMockRead(*headers_frame, 2),
4873 MockRead(ASYNC, 0, 4),
4876 scoped_ptr<SpdyFrame> req(
4877 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4878 scoped_ptr<SpdyFrame> rst(
4879 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
4880 MockWrite writes[] = {
4881 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4884 DeterministicSocketData data(
4885 reads, arraysize(reads), writes, arraysize(writes));
4886 MockConnect connect_data(SYNCHRONOUS, OK);
4887 data.set_connect_data(connect_data);
4888 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4890 CreateDeterministicNetworkSession();
4892 base::WeakPtr<SpdySession> session =
4893 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4895 GURL url1(kDefaultURL);
4896 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4897 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4898 ASSERT_TRUE(spdy_stream1.get() != NULL);
4899 EXPECT_EQ(0u, spdy_stream1->stream_id());
4900 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4901 spdy_stream1->SetDelegate(&delegate1);
4903 EXPECT_EQ(0u, session->num_active_streams());
4904 EXPECT_EQ(1u, session->num_created_streams());
4905 EXPECT_EQ(0u, session->num_pushed_streams());
4906 EXPECT_EQ(0u, session->num_active_pushed_streams());
4908 scoped_ptr<SpdyHeaderBlock> headers(
4909 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4910 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4911 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4913 // Run until 1st stream is activated.
4914 EXPECT_EQ(0u, delegate1.stream_id());
4915 data.RunFor(1);
4916 EXPECT_EQ(1u, delegate1.stream_id());
4917 EXPECT_EQ(1u, session->num_active_streams());
4918 EXPECT_EQ(0u, session->num_created_streams());
4919 EXPECT_EQ(0u, session->num_pushed_streams());
4920 EXPECT_EQ(0u, session->num_active_pushed_streams());
4922 // Run until pushed stream is created.
4923 data.RunFor(1);
4924 EXPECT_EQ(2u, session->num_active_streams());
4925 EXPECT_EQ(0u, session->num_created_streams());
4926 EXPECT_EQ(1u, session->num_pushed_streams());
4927 EXPECT_EQ(0u, session->num_active_pushed_streams());
4929 base::WeakPtr<SpdyStream> pushed_stream;
4930 int rv =
4931 session->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
4932 ASSERT_EQ(OK, rv);
4933 ASSERT_TRUE(pushed_stream.get() != NULL);
4934 test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
4935 pushed_stream->SetDelegate(&delegate2);
4937 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4938 // that all our counters are in consistent state.
4939 data.RunFor(1);
4940 EXPECT_EQ(1u, session->num_active_streams());
4941 EXPECT_EQ(0u, session->num_created_streams());
4942 EXPECT_EQ(0u, session->num_pushed_streams());
4943 EXPECT_EQ(0u, session->num_active_pushed_streams());
4945 // Read EOF.
4946 data.RunFor(2);
4949 TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
4950 session_deps_.host_resolver->set_synchronous_mode(true);
4952 MockRead reads[] = {
4953 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
4956 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
4958 MockConnect connect_data(SYNCHRONOUS, OK);
4959 data.set_connect_data(connect_data);
4960 session_deps_.socket_factory->AddSocketDataProvider(&data);
4962 CreateNetworkSession();
4963 base::WeakPtr<SpdySession> session =
4964 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4966 session->stream_hi_water_mark_ = 5;
4967 // Low client (odd) ids are fine.
4968 EXPECT_TRUE(session->OnUnknownFrame(3, 0));
4969 // Client id exceeding watermark.
4970 EXPECT_FALSE(session->OnUnknownFrame(9, 0));
4972 session->last_accepted_push_stream_id_ = 6;
4973 // Low server (even) ids are fine.
4974 EXPECT_TRUE(session->OnUnknownFrame(2, 0));
4975 // Server id exceeding last accepted id.
4976 EXPECT_FALSE(session->OnUnknownFrame(8, 0));
4979 TEST(MapFramerErrorToProtocolError, MapsValues) {
4980 CHECK_EQ(
4981 SPDY_ERROR_INVALID_CONTROL_FRAME,
4982 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4983 CHECK_EQ(
4984 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4985 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4986 CHECK_EQ(
4987 SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
4988 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
4989 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
4990 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
4993 TEST(MapFramerErrorToNetError, MapsValue) {
4994 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
4995 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4996 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4997 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
4998 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4999 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
5000 CHECK_EQ(
5001 ERR_SPDY_FRAME_SIZE_ERROR,
5002 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
5005 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
5006 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
5007 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
5008 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
5009 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
5010 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
5011 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
5012 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY,
5013 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY));
5014 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED,
5015 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED));
5018 TEST(MapNetErrorToGoAwayStatus, MapsValue) {
5019 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
5020 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
5021 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
5022 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
5023 CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
5024 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
5025 CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
5026 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
5027 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
5028 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
5029 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
5032 TEST(CanPoolTest, CanPool) {
5033 // Load a cert that is valid for:
5034 // www.example.org
5035 // mail.example.org
5036 // www.example.com
5038 TransportSecurityState tss;
5039 SSLInfo ssl_info;
5040 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5041 "spdy_pooling.pem");
5043 EXPECT_TRUE(SpdySession::CanPool(
5044 &tss, ssl_info, "www.example.org", "www.example.org"));
5045 EXPECT_TRUE(SpdySession::CanPool(
5046 &tss, ssl_info, "www.example.org", "mail.example.org"));
5047 EXPECT_TRUE(SpdySession::CanPool(
5048 &tss, ssl_info, "www.example.org", "mail.example.com"));
5049 EXPECT_FALSE(SpdySession::CanPool(
5050 &tss, ssl_info, "www.example.org", "mail.google.com"));
5053 TEST(CanPoolTest, CanNotPoolWithCertErrors) {
5054 // Load a cert that is valid for:
5055 // www.example.org
5056 // mail.example.org
5057 // www.example.com
5059 TransportSecurityState tss;
5060 SSLInfo ssl_info;
5061 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5062 "spdy_pooling.pem");
5063 ssl_info.cert_status = CERT_STATUS_REVOKED;
5065 EXPECT_FALSE(SpdySession::CanPool(
5066 &tss, ssl_info, "www.example.org", "mail.example.org"));
5069 TEST(CanPoolTest, CanNotPoolWithClientCerts) {
5070 // Load a cert that is valid for:
5071 // www.example.org
5072 // mail.example.org
5073 // www.example.com
5075 TransportSecurityState tss;
5076 SSLInfo ssl_info;
5077 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5078 "spdy_pooling.pem");
5079 ssl_info.client_cert_sent = true;
5081 EXPECT_FALSE(SpdySession::CanPool(
5082 &tss, ssl_info, "www.example.org", "mail.example.org"));
5085 TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
5086 // Load a cert that is valid for:
5087 // www.example.org
5088 // mail.example.org
5089 // www.example.com
5091 TransportSecurityState tss;
5092 SSLInfo ssl_info;
5093 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5094 "spdy_pooling.pem");
5095 ssl_info.channel_id_sent = true;
5097 EXPECT_TRUE(SpdySession::CanPool(
5098 &tss, ssl_info, "www.example.org", "mail.example.org"));
5099 EXPECT_FALSE(SpdySession::CanPool(
5100 &tss, ssl_info, "www.example.org", "www.example.com"));
5103 TEST(CanPoolTest, CanNotPoolWithBadPins) {
5104 uint8 primary_pin = 1;
5105 uint8 backup_pin = 2;
5106 uint8 bad_pin = 3;
5107 TransportSecurityState tss;
5108 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5110 SSLInfo ssl_info;
5111 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5112 "spdy_pooling.pem");
5113 ssl_info.is_issued_by_known_root = true;
5114 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
5116 EXPECT_FALSE(SpdySession::CanPool(
5117 &tss, ssl_info, "www.example.org", "mail.example.org"));
5120 TEST(CanPoolTest, CanPoolWithAcceptablePins) {
5121 uint8 primary_pin = 1;
5122 uint8 backup_pin = 2;
5123 TransportSecurityState tss;
5124 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5126 SSLInfo ssl_info;
5127 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5128 "spdy_pooling.pem");
5129 ssl_info.is_issued_by_known_root = true;
5130 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
5132 EXPECT_TRUE(SpdySession::CanPool(
5133 &tss, ssl_info, "www.example.org", "mail.example.org"));
5136 } // namespace net