Roll src/third_party/skia 57a48a7:de7665a
[chromium-blink-merge.git] / net / spdy / spdy_session_unittest.cc
blob5b4862ae4dd0ae1303c6d44f78f424a059cf61ab
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(NextProto,
182 SpdySessionTest,
183 testing::Values(kProtoSPDY31,
184 kProtoSPDY4_14,
185 kProtoSPDY4));
187 // Try to create a SPDY session that will fail during
188 // initialization. Nothing should blow up.
189 TEST_P(SpdySessionTest, InitialReadError) {
190 CreateDeterministicNetworkSession();
192 base::WeakPtr<SpdySession> session = TryCreateFakeSpdySessionExpectingFailure(
193 spdy_session_pool_, key_, ERR_CONNECTION_CLOSED);
194 EXPECT_TRUE(session);
195 // Flush the read.
196 base::RunLoop().RunUntilIdle();
197 EXPECT_FALSE(session);
200 namespace {
202 // A helper class that vends a callback that, when fired, destroys a
203 // given SpdyStreamRequest.
204 class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
205 public:
206 StreamRequestDestroyingCallback() {}
208 ~StreamRequestDestroyingCallback() override {}
210 void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) {
211 request_ = request.Pass();
214 CompletionCallback MakeCallback() {
215 return base::Bind(&StreamRequestDestroyingCallback::OnComplete,
216 base::Unretained(this));
219 private:
220 void OnComplete(int result) {
221 request_.reset();
222 SetResult(result);
225 scoped_ptr<SpdyStreamRequest> request_;
228 } // namespace
230 // Request kInitialMaxConcurrentStreams streams. Request two more
231 // streams, but have the callback for one destroy the second stream
232 // request. Close the session. Nothing should blow up. This is a
233 // regression test for http://crbug.com/250841 .
234 TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
235 session_deps_.host_resolver->set_synchronous_mode(true);
237 MockRead reads[] = {MockRead(ASYNC, 0, 0), };
239 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
240 MockConnect connect_data(SYNCHRONOUS, OK);
241 data.set_connect_data(connect_data);
242 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
244 CreateDeterministicNetworkSession();
246 base::WeakPtr<SpdySession> session =
247 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
249 // Create the maximum number of concurrent streams.
250 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
251 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
252 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog());
253 ASSERT_TRUE(spdy_stream != NULL);
256 SpdyStreamRequest request1;
257 scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest);
259 StreamRequestDestroyingCallback callback1;
260 ASSERT_EQ(ERR_IO_PENDING,
261 request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM,
262 session,
263 test_url_,
264 MEDIUM,
265 BoundNetLog(),
266 callback1.MakeCallback()));
268 // |callback2| is never called.
269 TestCompletionCallback callback2;
270 ASSERT_EQ(ERR_IO_PENDING,
271 request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM,
272 session,
273 test_url_,
274 MEDIUM,
275 BoundNetLog(),
276 callback2.callback()));
278 callback1.SetRequestToDestroy(request2.Pass());
280 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
282 EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
285 // A session receiving a GOAWAY frame with no active streams should close.
286 TEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
287 session_deps_.host_resolver->set_synchronous_mode(true);
289 MockConnect connect_data(SYNCHRONOUS, OK);
290 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
291 MockRead reads[] = {
292 CreateMockRead(*goaway, 0),
294 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
295 data.set_connect_data(connect_data);
296 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
298 CreateDeterministicNetworkSession();
300 base::WeakPtr<SpdySession> session =
301 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
303 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
305 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
307 // Read and process the GOAWAY frame.
308 data.RunFor(1);
309 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
310 base::RunLoop().RunUntilIdle();
311 EXPECT_TRUE(session == NULL);
314 // A session receiving a GOAWAY frame immediately with no active
315 // streams should then close.
316 TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
317 session_deps_.host_resolver->set_synchronous_mode(true);
319 MockConnect connect_data(SYNCHRONOUS, OK);
320 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
321 MockRead reads[] = {
322 CreateMockRead(*goaway, 0, SYNCHRONOUS),
324 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
325 data.set_connect_data(connect_data);
326 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
328 CreateDeterministicNetworkSession();
330 data.StopAfter(1);
332 base::WeakPtr<SpdySession> session =
333 TryCreateInsecureSpdySessionExpectingFailure(
334 http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
335 base::RunLoop().RunUntilIdle();
337 EXPECT_FALSE(session);
338 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
341 // A session receiving a GOAWAY frame with active streams should close
342 // when the last active stream is closed.
343 TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
344 session_deps_.host_resolver->set_synchronous_mode(true);
346 MockConnect connect_data(SYNCHRONOUS, OK);
347 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
348 MockRead reads[] = {
349 CreateMockRead(*goaway, 2),
350 MockRead(ASYNC, 0, 3) // EOF
352 scoped_ptr<SpdyFrame> req1(
353 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
354 scoped_ptr<SpdyFrame> req2(
355 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
356 MockWrite writes[] = {
357 CreateMockWrite(*req1, 0),
358 CreateMockWrite(*req2, 1),
360 DeterministicSocketData data(reads, arraysize(reads),
361 writes, arraysize(writes));
362 data.set_connect_data(connect_data);
363 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
365 CreateDeterministicNetworkSession();
367 base::WeakPtr<SpdySession> session =
368 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
370 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
372 GURL url(kDefaultURL);
373 base::WeakPtr<SpdyStream> spdy_stream1 =
374 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
375 session, url, MEDIUM, BoundNetLog());
376 test::StreamDelegateDoNothing delegate1(spdy_stream1);
377 spdy_stream1->SetDelegate(&delegate1);
379 base::WeakPtr<SpdyStream> spdy_stream2 =
380 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
381 session, url, MEDIUM, BoundNetLog());
382 test::StreamDelegateDoNothing delegate2(spdy_stream2);
383 spdy_stream2->SetDelegate(&delegate2);
385 scoped_ptr<SpdyHeaderBlock> headers(
386 spdy_util_.ConstructGetHeaderBlock(url.spec()));
387 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
389 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
390 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
391 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
392 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
394 data.RunFor(2);
396 EXPECT_EQ(1u, spdy_stream1->stream_id());
397 EXPECT_EQ(3u, spdy_stream2->stream_id());
399 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
401 // Read and process the GOAWAY frame.
402 data.RunFor(1);
404 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
406 EXPECT_FALSE(session->IsStreamActive(3));
407 EXPECT_EQ(NULL, spdy_stream2.get());
408 EXPECT_TRUE(session->IsStreamActive(1));
410 EXPECT_TRUE(session->IsGoingAway());
412 // Should close the session.
413 spdy_stream1->Close();
414 EXPECT_EQ(NULL, spdy_stream1.get());
416 base::MessageLoop::current()->RunUntilIdle();
417 EXPECT_TRUE(session == NULL);
420 // Have a session receive two GOAWAY frames, with the last one causing
421 // the last active stream to be closed. The session should then be
422 // closed after the second GOAWAY frame.
423 TEST_P(SpdySessionTest, GoAwayTwice) {
424 session_deps_.host_resolver->set_synchronous_mode(true);
426 MockConnect connect_data(SYNCHRONOUS, OK);
427 scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
428 scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
429 MockRead reads[] = {
430 CreateMockRead(*goaway1, 2),
431 CreateMockRead(*goaway2, 3),
432 MockRead(ASYNC, 0, 4) // EOF
434 scoped_ptr<SpdyFrame> req1(
435 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
436 scoped_ptr<SpdyFrame> req2(
437 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
438 MockWrite writes[] = {
439 CreateMockWrite(*req1, 0),
440 CreateMockWrite(*req2, 1),
442 DeterministicSocketData data(reads, arraysize(reads),
443 writes, arraysize(writes));
444 data.set_connect_data(connect_data);
445 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
447 CreateDeterministicNetworkSession();
449 base::WeakPtr<SpdySession> session =
450 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
452 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
454 GURL url(kDefaultURL);
455 base::WeakPtr<SpdyStream> spdy_stream1 =
456 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
457 session, url, MEDIUM, BoundNetLog());
458 test::StreamDelegateDoNothing delegate1(spdy_stream1);
459 spdy_stream1->SetDelegate(&delegate1);
461 base::WeakPtr<SpdyStream> spdy_stream2 =
462 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
463 session, url, MEDIUM, BoundNetLog());
464 test::StreamDelegateDoNothing delegate2(spdy_stream2);
465 spdy_stream2->SetDelegate(&delegate2);
467 scoped_ptr<SpdyHeaderBlock> headers(
468 spdy_util_.ConstructGetHeaderBlock(url.spec()));
469 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
471 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
472 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
473 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
474 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
476 data.RunFor(2);
478 EXPECT_EQ(1u, spdy_stream1->stream_id());
479 EXPECT_EQ(3u, spdy_stream2->stream_id());
481 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
483 // Read and process the first GOAWAY frame.
484 data.RunFor(1);
486 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
488 EXPECT_FALSE(session->IsStreamActive(3));
489 EXPECT_EQ(NULL, spdy_stream2.get());
490 EXPECT_TRUE(session->IsStreamActive(1));
491 EXPECT_TRUE(session->IsGoingAway());
493 // Read and process the second GOAWAY frame, which should close the
494 // session.
495 data.RunFor(1);
496 base::MessageLoop::current()->RunUntilIdle();
497 EXPECT_TRUE(session == NULL);
500 // Have a session with active streams receive a GOAWAY frame and then
501 // close it. It should handle the close properly (i.e., not try to
502 // make itself unavailable in its pool twice).
503 TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
504 session_deps_.host_resolver->set_synchronous_mode(true);
506 MockConnect connect_data(SYNCHRONOUS, OK);
507 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
508 MockRead reads[] = {
509 CreateMockRead(*goaway, 2),
510 MockRead(ASYNC, 0, 3) // EOF
512 scoped_ptr<SpdyFrame> req1(
513 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
514 scoped_ptr<SpdyFrame> req2(
515 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
516 MockWrite writes[] = {
517 CreateMockWrite(*req1, 0),
518 CreateMockWrite(*req2, 1),
520 DeterministicSocketData data(reads, arraysize(reads),
521 writes, arraysize(writes));
522 data.set_connect_data(connect_data);
523 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
525 CreateDeterministicNetworkSession();
527 base::WeakPtr<SpdySession> session =
528 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
530 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
532 GURL url(kDefaultURL);
533 base::WeakPtr<SpdyStream> spdy_stream1 =
534 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
535 session, url, MEDIUM, BoundNetLog());
536 test::StreamDelegateDoNothing delegate1(spdy_stream1);
537 spdy_stream1->SetDelegate(&delegate1);
539 base::WeakPtr<SpdyStream> spdy_stream2 =
540 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
541 session, url, MEDIUM, BoundNetLog());
542 test::StreamDelegateDoNothing delegate2(spdy_stream2);
543 spdy_stream2->SetDelegate(&delegate2);
545 scoped_ptr<SpdyHeaderBlock> headers(
546 spdy_util_.ConstructGetHeaderBlock(url.spec()));
547 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
549 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
550 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
551 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
552 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
554 data.RunFor(2);
556 EXPECT_EQ(1u, spdy_stream1->stream_id());
557 EXPECT_EQ(3u, spdy_stream2->stream_id());
559 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
561 // Read and process the GOAWAY frame.
562 data.RunFor(1);
564 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
566 EXPECT_FALSE(session->IsStreamActive(3));
567 EXPECT_EQ(NULL, spdy_stream2.get());
568 EXPECT_TRUE(session->IsStreamActive(1));
569 EXPECT_TRUE(session->IsGoingAway());
571 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
572 EXPECT_EQ(NULL, spdy_stream1.get());
574 base::MessageLoop::current()->RunUntilIdle();
575 EXPECT_TRUE(session == NULL);
578 // Process a joint read buffer which causes the session to begin draining, and
579 // then processes a GOAWAY. The session should gracefully drain. Regression test
580 // for crbug.com/379469
581 TEST_P(SpdySessionTest, GoAwayWhileDraining) {
582 session_deps_.host_resolver->set_synchronous_mode(true);
584 scoped_ptr<SpdyFrame> req(
585 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
586 MockWrite writes[] = {
587 CreateMockWrite(*req, 0),
590 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
591 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
592 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
593 size_t joint_size = goaway->size() * 2 + body->size();
595 // Compose interleaved |goaway| and |body| frames into a single read.
596 scoped_ptr<char[]> buffer(new char[joint_size]);
598 size_t out = 0;
599 memcpy(&buffer[out], goaway->data(), goaway->size());
600 out += goaway->size();
601 memcpy(&buffer[out], body->data(), body->size());
602 out += body->size();
603 memcpy(&buffer[out], goaway->data(), goaway->size());
604 out += goaway->size();
605 ASSERT_EQ(out, joint_size);
607 SpdyFrame joint_frames(buffer.get(), joint_size, false);
609 MockRead reads[] = {
610 CreateMockRead(*resp, 1), CreateMockRead(joint_frames, 2),
611 MockRead(ASYNC, 0, 3) // EOF
614 MockConnect connect_data(SYNCHRONOUS, OK);
615 DeterministicSocketData data(
616 reads, arraysize(reads), writes, arraysize(writes));
617 data.set_connect_data(connect_data);
618 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
620 CreateDeterministicNetworkSession();
621 base::WeakPtr<SpdySession> session =
622 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
624 GURL url(kDefaultURL);
625 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
626 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
627 test::StreamDelegateDoNothing delegate(spdy_stream);
628 spdy_stream->SetDelegate(&delegate);
630 scoped_ptr<SpdyHeaderBlock> headers(
631 spdy_util_.ConstructGetHeaderBlock(url.spec()));
632 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
633 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
635 data.RunFor(3);
636 base::MessageLoop::current()->RunUntilIdle();
638 // Stream and session closed gracefully.
639 EXPECT_TRUE(delegate.StreamIsClosed());
640 EXPECT_EQ(OK, delegate.WaitForClose());
641 EXPECT_EQ(kUploadData, delegate.TakeReceivedData());
642 EXPECT_TRUE(session == NULL);
645 // Try to create a stream after receiving a GOAWAY frame. It should
646 // fail.
647 TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
648 session_deps_.host_resolver->set_synchronous_mode(true);
650 MockConnect connect_data(SYNCHRONOUS, OK);
651 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
652 MockRead reads[] = {
653 CreateMockRead(*goaway, 1),
654 MockRead(ASYNC, 0, 2) // EOF
656 scoped_ptr<SpdyFrame> req(
657 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
658 MockWrite writes[] = {
659 CreateMockWrite(*req, 0),
661 DeterministicSocketData data(reads, arraysize(reads),
662 writes, arraysize(writes));
663 data.set_connect_data(connect_data);
664 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
666 CreateDeterministicNetworkSession();
668 base::WeakPtr<SpdySession> session =
669 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
671 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
673 GURL url(kDefaultURL);
674 base::WeakPtr<SpdyStream> spdy_stream =
675 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
676 session, url, MEDIUM, BoundNetLog());
677 test::StreamDelegateDoNothing delegate(spdy_stream);
678 spdy_stream->SetDelegate(&delegate);
680 scoped_ptr<SpdyHeaderBlock> headers(
681 spdy_util_.ConstructGetHeaderBlock(url.spec()));
682 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
683 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
685 data.RunFor(1);
687 EXPECT_EQ(1u, spdy_stream->stream_id());
689 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
691 // Read and process the GOAWAY frame.
692 data.RunFor(1);
694 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
695 EXPECT_TRUE(session->IsStreamActive(1));
697 SpdyStreamRequest stream_request;
698 int rv = stream_request.StartRequest(
699 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog(),
700 CompletionCallback());
701 EXPECT_EQ(ERR_FAILED, rv);
703 // Read and process EOF.
704 data.RunFor(1);
706 EXPECT_TRUE(session == NULL);
709 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
710 // the stream being refused.
711 TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
712 session_deps_.host_resolver->set_synchronous_mode(true);
714 MockConnect connect_data(SYNCHRONOUS, OK);
715 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
716 scoped_ptr<SpdyFrame>
717 push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kDefaultURL));
718 MockRead reads[] = {
719 CreateMockRead(*goaway, 1),
720 CreateMockRead(*push, 2),
721 MockRead(ASYNC, 0, 4) // EOF
723 scoped_ptr<SpdyFrame> req(
724 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
725 scoped_ptr<SpdyFrame> rst(
726 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
727 MockWrite writes[] = {
728 CreateMockWrite(*req, 0),
729 CreateMockWrite(*rst, 3)
731 DeterministicSocketData data(reads, arraysize(reads),
732 writes, arraysize(writes));
733 data.set_connect_data(connect_data);
734 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
736 CreateDeterministicNetworkSession();
738 base::WeakPtr<SpdySession> session =
739 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
741 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
743 GURL url(kDefaultURL);
744 base::WeakPtr<SpdyStream> spdy_stream =
745 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
746 session, url, MEDIUM, BoundNetLog());
747 test::StreamDelegateDoNothing delegate(spdy_stream);
748 spdy_stream->SetDelegate(&delegate);
750 scoped_ptr<SpdyHeaderBlock> headers(
751 spdy_util_.ConstructGetHeaderBlock(url.spec()));
752 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
753 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
755 data.RunFor(1);
757 EXPECT_EQ(1u, spdy_stream->stream_id());
759 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
761 // Read and process the GOAWAY frame.
762 data.RunFor(1);
764 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
765 EXPECT_TRUE(session->IsStreamActive(1));
767 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
768 // and EOF.
769 data.RunFor(3);
770 base::MessageLoop::current()->RunUntilIdle();
771 EXPECT_TRUE(session == NULL);
774 // A session observing a network change with active streams should close
775 // when the last active stream is closed.
776 TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
777 session_deps_.host_resolver->set_synchronous_mode(true);
779 MockConnect connect_data(SYNCHRONOUS, OK);
780 MockRead reads[] = {
781 MockRead(ASYNC, 0, 1) // EOF
783 scoped_ptr<SpdyFrame> req1(
784 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
785 MockWrite writes[] = {
786 CreateMockWrite(*req1, 0),
788 DeterministicSocketData data(reads, arraysize(reads),
789 writes, arraysize(writes));
790 data.set_connect_data(connect_data);
791 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
793 CreateDeterministicNetworkSession();
795 base::WeakPtr<SpdySession> session =
796 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
798 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
800 base::WeakPtr<SpdyStream> spdy_stream =
801 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session,
802 GURL(kDefaultURL), MEDIUM, BoundNetLog());
803 test::StreamDelegateDoNothing delegate(spdy_stream);
804 spdy_stream->SetDelegate(&delegate);
806 scoped_ptr<SpdyHeaderBlock> headers(
807 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
809 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
810 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
812 data.RunFor(1);
814 EXPECT_EQ(1u, spdy_stream->stream_id());
816 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
818 spdy_session_pool_->OnIPAddressChanged();
820 // The SpdySessionPool behavior differs based on how the OSs reacts to
821 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
822 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
823 // For OSs where the TCP connections will close upon relevant network
824 // changes, SpdySessionPool doesn't need to force them to close, so in these
825 // cases verify the session has become unavailable but remains open and the
826 // pre-existing stream is still active.
827 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
829 EXPECT_TRUE(session->IsGoingAway());
831 EXPECT_TRUE(session->IsStreamActive(1));
833 // Should close the session.
834 spdy_stream->Close();
835 #endif
836 EXPECT_EQ(NULL, spdy_stream.get());
838 base::MessageLoop::current()->RunUntilIdle();
839 EXPECT_TRUE(session == NULL);
842 TEST_P(SpdySessionTest, ClientPing) {
843 session_deps_.enable_ping = true;
844 session_deps_.host_resolver->set_synchronous_mode(true);
846 MockConnect connect_data(SYNCHRONOUS, OK);
847 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
848 MockRead reads[] = {
849 CreateMockRead(*read_ping, 1),
850 MockRead(ASYNC, 0, 0, 2) // EOF
852 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
853 MockWrite writes[] = {
854 CreateMockWrite(*write_ping, 0),
856 DeterministicSocketData data(
857 reads, arraysize(reads), writes, arraysize(writes));
858 data.set_connect_data(connect_data);
859 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
861 CreateDeterministicNetworkSession();
863 base::WeakPtr<SpdySession> session =
864 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
866 base::WeakPtr<SpdyStream> spdy_stream1 =
867 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
868 session, test_url_, MEDIUM, BoundNetLog());
869 ASSERT_TRUE(spdy_stream1.get() != NULL);
870 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
871 spdy_stream1->SetDelegate(&delegate);
873 base::TimeTicks before_ping_time = base::TimeTicks::Now();
875 session->set_connection_at_risk_of_loss_time(
876 base::TimeDelta::FromSeconds(-1));
877 session->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
879 session->SendPrefacePingIfNoneInFlight();
881 data.RunFor(2);
883 session->CheckPingStatus(before_ping_time);
885 EXPECT_EQ(0, session->pings_in_flight());
886 EXPECT_GE(session->next_ping_id(), 1U);
887 EXPECT_FALSE(session->check_ping_status_pending());
888 EXPECT_GE(session->last_activity_time(), before_ping_time);
890 data.RunFor(1);
892 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
894 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
895 EXPECT_TRUE(session == NULL);
898 TEST_P(SpdySessionTest, ServerPing) {
899 session_deps_.host_resolver->set_synchronous_mode(true);
901 MockConnect connect_data(SYNCHRONOUS, OK);
902 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
903 MockRead reads[] = {
904 CreateMockRead(*read_ping),
905 MockRead(SYNCHRONOUS, 0, 0) // EOF
907 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
908 MockWrite writes[] = {
909 CreateMockWrite(*write_ping),
911 StaticSocketDataProvider data(
912 reads, arraysize(reads), writes, arraysize(writes));
913 data.set_connect_data(connect_data);
914 session_deps_.socket_factory->AddSocketDataProvider(&data);
916 CreateNetworkSession();
918 base::WeakPtr<SpdySession> session =
919 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
921 base::WeakPtr<SpdyStream> spdy_stream1 =
922 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
923 session, test_url_, MEDIUM, BoundNetLog());
924 ASSERT_TRUE(spdy_stream1.get() != NULL);
925 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
926 spdy_stream1->SetDelegate(&delegate);
928 // Flush the read completion task.
929 base::MessageLoop::current()->RunUntilIdle();
931 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
933 EXPECT_TRUE(session == NULL);
934 EXPECT_EQ(NULL, spdy_stream1.get());
937 // Cause a ping to be sent out while producing a write. The write loop
938 // should handle this properly, i.e. another DoWriteLoop task should
939 // not be posted. This is a regression test for
940 // http://crbug.com/261043 .
941 TEST_P(SpdySessionTest, PingAndWriteLoop) {
942 session_deps_.enable_ping = true;
943 session_deps_.time_func = TheNearFuture;
945 MockConnect connect_data(SYNCHRONOUS, OK);
946 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
947 scoped_ptr<SpdyFrame> req(
948 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
949 MockWrite writes[] = {
950 CreateMockWrite(*req, 0),
951 CreateMockWrite(*write_ping, 1),
954 MockRead reads[] = {
955 MockRead(ASYNC, 0, 2) // EOF
958 session_deps_.host_resolver->set_synchronous_mode(true);
960 DeterministicSocketData data(reads, arraysize(reads),
961 writes, arraysize(writes));
962 data.set_connect_data(connect_data);
963 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
965 CreateDeterministicNetworkSession();
967 base::WeakPtr<SpdySession> session =
968 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
970 GURL url(kDefaultURL);
971 base::WeakPtr<SpdyStream> spdy_stream =
972 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
973 session, url, LOWEST, BoundNetLog());
974 test::StreamDelegateDoNothing delegate(spdy_stream);
975 spdy_stream->SetDelegate(&delegate);
977 scoped_ptr<SpdyHeaderBlock> headers(
978 spdy_util_.ConstructGetHeaderBlock(url.spec()));
979 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
981 // Shift time so that a ping will be sent out.
982 g_time_delta = base::TimeDelta::FromSeconds(11);
984 data.RunFor(2);
986 session->CloseSessionOnError(ERR_ABORTED, "Aborting");
989 TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
990 const SpdyStreamId kLastStreamId = 0x7fffffff;
991 session_deps_.host_resolver->set_synchronous_mode(true);
993 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
994 // fixed to allow for two stream ID assignments, and three concurrent
995 // streams. Four streams are started, and two are activated. Verify the
996 // session goes away, and that the created (but not activated) and
997 // stalled streams are aborted. Also verify the activated streams complete,
998 // at which point the session closes.
1000 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
1001 NULL, 0, false, kLastStreamId - 2, MEDIUM, true));
1002 scoped_ptr<SpdyFrame> req2(
1003 spdy_util_.ConstructSpdyGet(NULL, 0, false, kLastStreamId, MEDIUM, true));
1005 MockWrite writes[] = {
1006 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
1009 scoped_ptr<SpdyFrame> resp1(
1010 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId - 2));
1011 scoped_ptr<SpdyFrame> resp2(
1012 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId));
1014 scoped_ptr<SpdyFrame> body1(
1015 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
1016 scoped_ptr<SpdyFrame> body2(
1017 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
1019 MockRead reads[] = {
1020 CreateMockRead(*resp1, 2), CreateMockRead(*resp2, 3),
1021 CreateMockRead(*body1, 4), CreateMockRead(*body2, 5),
1022 MockRead(ASYNC, 0, 6) // EOF
1025 DeterministicSocketData data(
1026 reads, arraysize(reads), writes, arraysize(writes));
1028 MockConnect connect_data(SYNCHRONOUS, OK);
1029 data.set_connect_data(connect_data);
1030 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1032 CreateDeterministicNetworkSession();
1033 base::WeakPtr<SpdySession> session =
1034 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1036 // Fix stream_hi_water_mark_ to allow for two stream activations.
1037 session->stream_hi_water_mark_ = kLastStreamId - 2;
1038 // Fix max_concurrent_streams to allow for three stream creations.
1039 session->max_concurrent_streams_ = 3;
1041 // Create three streams synchronously, and begin a fourth (which is stalled).
1042 GURL url(kDefaultURL);
1043 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1044 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1045 test::StreamDelegateDoNothing delegate1(stream1);
1046 stream1->SetDelegate(&delegate1);
1048 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
1049 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1050 test::StreamDelegateDoNothing delegate2(stream2);
1051 stream2->SetDelegate(&delegate2);
1053 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1054 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1055 test::StreamDelegateDoNothing delegate3(stream3);
1056 stream3->SetDelegate(&delegate3);
1058 SpdyStreamRequest request4;
1059 TestCompletionCallback callback4;
1060 EXPECT_EQ(ERR_IO_PENDING,
1061 request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1062 session,
1063 url,
1064 MEDIUM,
1065 BoundNetLog(),
1066 callback4.callback()));
1068 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1069 EXPECT_EQ(0u, session->num_active_streams());
1070 EXPECT_EQ(3u, session->num_created_streams());
1071 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1073 // Activate stream 1. One ID remains available.
1074 stream1->SendRequestHeaders(
1075 scoped_ptr<SpdyHeaderBlock>(
1076 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1077 NO_MORE_DATA_TO_SEND);
1078 data.RunFor(1);
1080 EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1081 EXPECT_EQ(1u, session->num_active_streams());
1082 EXPECT_EQ(2u, session->num_created_streams());
1083 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1085 // Activate stream 2. ID space is exhausted.
1086 stream2->SendRequestHeaders(
1087 scoped_ptr<SpdyHeaderBlock>(
1088 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1089 NO_MORE_DATA_TO_SEND);
1090 data.RunFor(1);
1092 // Active streams remain active.
1093 EXPECT_EQ(kLastStreamId, stream2->stream_id());
1094 EXPECT_EQ(2u, session->num_active_streams());
1096 // Session is going away. Created and stalled streams were aborted.
1097 EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session->availability_state_);
1098 EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose());
1099 EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult());
1100 EXPECT_EQ(0u, session->num_created_streams());
1101 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1103 // Read responses on remaining active streams.
1104 data.RunFor(4);
1105 EXPECT_EQ(OK, delegate1.WaitForClose());
1106 EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1107 EXPECT_EQ(OK, delegate2.WaitForClose());
1108 EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1110 // Session was destroyed.
1111 base::MessageLoop::current()->RunUntilIdle();
1112 EXPECT_FALSE(session.get());
1115 // Verifies that an unstalled pending stream creation racing with a new stream
1116 // creation doesn't violate the maximum stream concurrency. Regression test for
1117 // crbug.com/373858.
1118 TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) {
1119 session_deps_.host_resolver->set_synchronous_mode(true);
1121 MockRead reads[] = {
1122 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1125 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1127 MockConnect connect_data(SYNCHRONOUS, OK);
1128 data.set_connect_data(connect_data);
1129 session_deps_.socket_factory->AddSocketDataProvider(&data);
1131 CreateNetworkSession();
1132 base::WeakPtr<SpdySession> session =
1133 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1135 // Fix max_concurrent_streams to allow for one open stream.
1136 session->max_concurrent_streams_ = 1;
1138 // Create two streams: one synchronously, and one which stalls.
1139 GURL url(kDefaultURL);
1140 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1141 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1143 SpdyStreamRequest request2;
1144 TestCompletionCallback callback2;
1145 EXPECT_EQ(ERR_IO_PENDING,
1146 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1147 session,
1148 url,
1149 MEDIUM,
1150 BoundNetLog(),
1151 callback2.callback()));
1153 EXPECT_EQ(1u, session->num_created_streams());
1154 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1156 // Cancel the first stream. A callback to unstall the second stream was
1157 // posted. Don't run it yet.
1158 stream1->Cancel();
1160 EXPECT_EQ(0u, session->num_created_streams());
1161 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1163 // Create a third stream prior to the second stream's callback.
1164 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1165 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1167 EXPECT_EQ(1u, session->num_created_streams());
1168 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1170 // NOW run the message loop. The unstalled stream will re-stall itself.
1171 base::MessageLoop::current()->RunUntilIdle();
1172 EXPECT_EQ(1u, session->num_created_streams());
1173 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1175 // Cancel the third stream and run the message loop. Verify that the second
1176 // stream creation now completes.
1177 stream3->Cancel();
1178 base::MessageLoop::current()->RunUntilIdle();
1180 EXPECT_EQ(1u, session->num_created_streams());
1181 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1182 EXPECT_EQ(OK, callback2.WaitForResult());
1185 TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
1186 session_deps_.host_resolver->set_synchronous_mode(true);
1187 session_deps_.time_func = TheNearFuture;
1189 scoped_ptr<SpdyFrame> req(
1190 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1191 scoped_ptr<SpdyFrame> rst(
1192 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
1194 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
1195 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
1196 scoped_ptr<SpdyFrame> push_a_body(
1197 spdy_util_.ConstructSpdyBodyFrame(2, false));
1198 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1199 // iterators inside. See http://crbug.com/443490
1200 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
1201 NULL, 0, 4, 1, "http://www.google.com/0.dat"));
1202 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)};
1203 MockRead reads[] = {
1204 CreateMockRead(*push_a, 1), CreateMockRead(*push_a_body, 2),
1205 CreateMockRead(*push_b, 3), MockRead(ASYNC, 0, 5), // EOF
1207 DeterministicSocketData data(
1208 reads, arraysize(reads), writes, arraysize(writes));
1210 MockConnect connect_data(SYNCHRONOUS, OK);
1211 data.set_connect_data(connect_data);
1212 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1214 CreateDeterministicNetworkSession();
1215 base::WeakPtr<SpdySession> session =
1216 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1218 // Process the principal request, and the first push stream request & body.
1219 GURL url(kDefaultURL);
1220 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1221 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1222 test::StreamDelegateDoNothing delegate(spdy_stream);
1223 spdy_stream->SetDelegate(&delegate);
1225 scoped_ptr<SpdyHeaderBlock> headers(
1226 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1227 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1229 data.RunFor(3);
1231 // Verify that there is one unclaimed push stream.
1232 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1233 SpdySession::PushedStreamMap::iterator iter =
1234 session->unclaimed_pushed_streams_.find(
1235 GURL("http://www.google.com/a.dat"));
1236 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1238 if (session->flow_control_state_ ==
1239 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1240 // Unclaimed push body consumed bytes from the session window.
1241 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()) - kUploadDataSize,
1242 session->session_recv_window_size_);
1243 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
1246 // Shift time to expire the push stream. Read the second SYN_STREAM,
1247 // and verify a RST_STREAM was written.
1248 g_time_delta = base::TimeDelta::FromSeconds(301);
1249 data.RunFor(2);
1251 // Verify that the second pushed stream evicted the first pushed stream.
1252 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1253 iter = session->unclaimed_pushed_streams_.find(
1254 GURL("http://www.google.com/0.dat"));
1255 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1257 if (session->flow_control_state_ ==
1258 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1259 // Verify that the session window reclaimed the evicted stream body.
1260 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
1261 session->session_recv_window_size_);
1262 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
1265 // Read and process EOF.
1266 data.RunFor(1);
1267 base::MessageLoop::current()->RunUntilIdle();
1268 EXPECT_TRUE(session == NULL);
1271 TEST_P(SpdySessionTest, FailedPing) {
1272 session_deps_.host_resolver->set_synchronous_mode(true);
1274 MockConnect connect_data(SYNCHRONOUS, OK);
1275 MockRead reads[] = {
1276 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1278 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
1279 scoped_ptr<SpdyFrame> goaway(
1280 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping."));
1281 MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)};
1282 StaticSocketDataProvider data(
1283 reads, arraysize(reads), writes, arraysize(writes));
1284 data.set_connect_data(connect_data);
1285 session_deps_.socket_factory->AddSocketDataProvider(&data);
1287 CreateNetworkSession();
1289 base::WeakPtr<SpdySession> session =
1290 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1292 base::WeakPtr<SpdyStream> spdy_stream1 =
1293 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1294 session, test_url_, MEDIUM, BoundNetLog());
1295 ASSERT_TRUE(spdy_stream1.get() != NULL);
1296 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
1297 spdy_stream1->SetDelegate(&delegate);
1299 session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1300 session->set_hung_interval(base::TimeDelta::FromSeconds(0));
1302 // Send a PING frame.
1303 session->WritePingFrame(1, false);
1304 EXPECT_LT(0, session->pings_in_flight());
1305 EXPECT_GE(session->next_ping_id(), 1U);
1306 EXPECT_TRUE(session->check_ping_status_pending());
1308 // Assert session is not closed.
1309 EXPECT_TRUE(session->IsAvailable());
1310 EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams());
1311 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1313 // We set last time we have received any data in 1 sec less than now.
1314 // CheckPingStatus will trigger timeout because hung interval is zero.
1315 base::TimeTicks now = base::TimeTicks::Now();
1316 session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
1317 session->CheckPingStatus(now);
1318 base::MessageLoop::current()->RunUntilIdle();
1320 EXPECT_TRUE(session == NULL);
1321 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1322 EXPECT_EQ(NULL, spdy_stream1.get());
1325 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1326 // settings frame increasing the max concurrent streams by 1. Make
1327 // sure nothing blows up. This is a regression test for
1328 // http://crbug.com/57331 .
1329 TEST_P(SpdySessionTest, OnSettings) {
1330 session_deps_.host_resolver->set_synchronous_mode(true);
1332 const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1334 SettingsMap new_settings;
1335 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1336 new_settings[kSpdySettingsIds] =
1337 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1338 scoped_ptr<SpdyFrame> settings_frame(
1339 spdy_util_.ConstructSpdySettings(new_settings));
1340 MockRead reads[] = {
1341 CreateMockRead(*settings_frame, 0),
1342 MockRead(ASYNC, 0, 1),
1345 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1346 MockWrite writes[] = {
1347 CreateMockWrite(*settings_ack, 2),
1350 DeterministicSocketData data(reads, arraysize(reads),
1351 writes, arraysize(writes));
1352 MockConnect connect_data(SYNCHRONOUS, OK);
1353 data.set_connect_data(connect_data);
1354 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1356 CreateDeterministicNetworkSession();
1358 base::WeakPtr<SpdySession> session =
1359 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1361 // Create the maximum number of concurrent streams.
1362 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1363 base::WeakPtr<SpdyStream> spdy_stream =
1364 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1365 session, test_url_, MEDIUM, BoundNetLog());
1366 ASSERT_TRUE(spdy_stream != NULL);
1369 StreamReleaserCallback stream_releaser;
1370 SpdyStreamRequest request;
1371 ASSERT_EQ(ERR_IO_PENDING,
1372 request.StartRequest(
1373 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1374 BoundNetLog(),
1375 stream_releaser.MakeCallback(&request)));
1377 data.RunFor(1);
1379 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1381 data.RunFor(1);
1382 if (spdy_util_.spdy_version() >= SPDY4) {
1383 // Allow the SETTINGS+ACK to write, so the session finishes draining.
1384 data.RunFor(1);
1386 base::MessageLoop::current()->RunUntilIdle();
1387 EXPECT_TRUE(session == NULL);
1390 // Start with a persisted value for max concurrent streams. Receive a
1391 // settings frame increasing the max concurrent streams by 1 and which
1392 // also clears the persisted data. Verify that persisted data is
1393 // correct.
1394 TEST_P(SpdySessionTest, ClearSettings) {
1395 if (spdy_util_.spdy_version() >= SPDY4) {
1396 // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1397 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4.
1398 return;
1400 session_deps_.host_resolver->set_synchronous_mode(true);
1402 SettingsMap new_settings;
1403 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1404 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1405 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1406 scoped_ptr<SpdyFrame> settings_frame(
1407 spdy_util_.ConstructSpdySettings(new_settings));
1408 uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1409 test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1410 MockRead reads[] = {
1411 CreateMockRead(*settings_frame, 0),
1412 MockRead(ASYNC, 0, 1),
1415 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
1416 MockConnect connect_data(SYNCHRONOUS, OK);
1417 data.set_connect_data(connect_data);
1418 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1420 CreateDeterministicNetworkSession();
1422 // Initialize the SpdySetting with the default.
1423 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1424 test_host_port_pair_,
1425 SETTINGS_MAX_CONCURRENT_STREAMS,
1426 SETTINGS_FLAG_PLEASE_PERSIST,
1427 kInitialMaxConcurrentStreams);
1429 EXPECT_FALSE(
1430 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1431 test_host_port_pair_).empty());
1433 base::WeakPtr<SpdySession> session =
1434 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1436 // Create the maximum number of concurrent streams.
1437 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1438 base::WeakPtr<SpdyStream> spdy_stream =
1439 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1440 session, test_url_, MEDIUM, BoundNetLog());
1441 ASSERT_TRUE(spdy_stream != NULL);
1444 StreamReleaserCallback stream_releaser;
1446 SpdyStreamRequest request;
1447 ASSERT_EQ(ERR_IO_PENDING,
1448 request.StartRequest(
1449 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1450 BoundNetLog(),
1451 stream_releaser.MakeCallback(&request)));
1453 data.RunFor(1);
1455 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1457 // Make sure that persisted data is cleared.
1458 EXPECT_TRUE(
1459 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1460 test_host_port_pair_).empty());
1462 // Make sure session's max_concurrent_streams is correct.
1463 EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1464 session->max_concurrent_streams());
1466 data.RunFor(1);
1467 EXPECT_TRUE(session == NULL);
1470 // Start with max concurrent streams set to 1. Request two streams.
1471 // When the first completes, have the callback close its stream, which
1472 // should trigger the second stream creation. Then cancel that one
1473 // immediately. Don't crash. This is a regression test for
1474 // http://crbug.com/63532 .
1475 TEST_P(SpdySessionTest, CancelPendingCreateStream) {
1476 session_deps_.host_resolver->set_synchronous_mode(true);
1478 MockRead reads[] = {
1479 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1482 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1483 MockConnect connect_data(SYNCHRONOUS, OK);
1485 data.set_connect_data(connect_data);
1486 session_deps_.socket_factory->AddSocketDataProvider(&data);
1488 CreateNetworkSession();
1490 // Initialize the SpdySetting with 1 max concurrent streams.
1491 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1492 test_host_port_pair_,
1493 SETTINGS_MAX_CONCURRENT_STREAMS,
1494 SETTINGS_FLAG_PLEASE_PERSIST,
1497 base::WeakPtr<SpdySession> session =
1498 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1500 // Leave room for only one more stream to be created.
1501 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1502 base::WeakPtr<SpdyStream> spdy_stream =
1503 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1504 session, test_url_, MEDIUM, BoundNetLog());
1505 ASSERT_TRUE(spdy_stream != NULL);
1508 // Create 2 more streams. First will succeed. Second will be pending.
1509 base::WeakPtr<SpdyStream> spdy_stream1 =
1510 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1511 session, test_url_, MEDIUM, BoundNetLog());
1512 ASSERT_TRUE(spdy_stream1.get() != NULL);
1514 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1515 // a valgrind error if the callback is invoked when it's not supposed to be.
1516 scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
1518 SpdyStreamRequest request;
1519 ASSERT_EQ(ERR_IO_PENDING,
1520 request.StartRequest(
1521 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1522 BoundNetLog(),
1523 callback->callback()));
1525 // Release the first one, this will allow the second to be created.
1526 spdy_stream1->Cancel();
1527 EXPECT_EQ(NULL, spdy_stream1.get());
1529 request.CancelRequest();
1530 callback.reset();
1532 // Should not crash when running the pending callback.
1533 base::MessageLoop::current()->RunUntilIdle();
1536 TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
1537 session_deps_.host_resolver->set_synchronous_mode(true);
1539 MockRead reads[] = {
1540 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1543 SettingsMap settings;
1544 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
1545 const SpdySettingsIds kSpdySettingsIds2 = SETTINGS_INITIAL_WINDOW_SIZE;
1546 const uint32 kInitialRecvWindowSize = 10 * 1024 * 1024;
1547 settings[kSpdySettingsIds1] =
1548 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
1549 if (spdy_util_.spdy_version() >= SPDY3) {
1550 settings[kSpdySettingsIds2] =
1551 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialRecvWindowSize);
1553 MockConnect connect_data(SYNCHRONOUS, OK);
1554 scoped_ptr<SpdyFrame> settings_frame(
1555 spdy_util_.ConstructSpdySettings(settings));
1556 scoped_ptr<SpdyFrame> initial_window_update(
1557 spdy_util_.ConstructSpdyWindowUpdate(
1558 kSessionFlowControlStreamId,
1559 kDefaultInitialRecvWindowSize -
1560 SpdySession::GetInitialWindowSize(GetParam())));
1561 std::vector<MockWrite> writes;
1562 if ((GetParam() >= kProtoSPDY4MinimumVersion) &&
1563 (GetParam() <= kProtoSPDY4MaximumVersion)) {
1564 writes.push_back(
1565 MockWrite(ASYNC,
1566 kHttp2ConnectionHeaderPrefix,
1567 kHttp2ConnectionHeaderPrefixSize));
1569 writes.push_back(CreateMockWrite(*settings_frame));
1570 if (GetParam() >= kProtoSPDY31) {
1571 writes.push_back(CreateMockWrite(*initial_window_update));
1574 SettingsMap server_settings;
1575 const uint32 initial_max_concurrent_streams = 1;
1576 server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1577 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1578 initial_max_concurrent_streams);
1579 scoped_ptr<SpdyFrame> server_settings_frame(
1580 spdy_util_.ConstructSpdySettings(server_settings));
1581 if (GetParam() <= kProtoSPDY31) {
1582 writes.push_back(CreateMockWrite(*server_settings_frame));
1585 session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize;
1587 StaticSocketDataProvider data(reads, arraysize(reads),
1588 vector_as_array(&writes), writes.size());
1589 data.set_connect_data(connect_data);
1590 session_deps_.socket_factory->AddSocketDataProvider(&data);
1592 CreateNetworkSession();
1594 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1595 test_host_port_pair_,
1596 SETTINGS_MAX_CONCURRENT_STREAMS,
1597 SETTINGS_FLAG_PLEASE_PERSIST,
1598 initial_max_concurrent_streams);
1600 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1601 pool_peer.SetEnableSendingInitialData(true);
1603 base::WeakPtr<SpdySession> session =
1604 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1606 base::MessageLoop::current()->RunUntilIdle();
1607 EXPECT_TRUE(data.at_write_eof());
1610 TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
1611 CreateNetworkSession();
1613 base::WeakPtr<HttpServerProperties> test_http_server_properties =
1614 spdy_session_pool_->http_server_properties();
1615 SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
1616 test_http_server_properties->SetSpdySetting(
1617 test_host_port_pair_,
1618 SETTINGS_MAX_CONCURRENT_STREAMS,
1619 SETTINGS_FLAG_PLEASE_PERSIST,
1621 EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
1622 test_host_port_pair_).size());
1623 spdy_session_pool_->OnIPAddressChanged();
1624 EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
1625 test_host_port_pair_).size());
1628 TEST_P(SpdySessionTest, Initialize) {
1629 CapturingBoundNetLog log;
1630 session_deps_.net_log = log.bound().net_log();
1631 session_deps_.host_resolver->set_synchronous_mode(true);
1633 MockConnect connect_data(SYNCHRONOUS, OK);
1634 MockRead reads[] = {
1635 MockRead(ASYNC, 0, 0) // EOF
1638 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1639 data.set_connect_data(connect_data);
1640 session_deps_.socket_factory->AddSocketDataProvider(&data);
1642 CreateNetworkSession();
1644 base::WeakPtr<SpdySession> session =
1645 CreateInsecureSpdySession(http_session_, key_, log.bound());
1646 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1648 // Flush the read completion task.
1649 base::MessageLoop::current()->RunUntilIdle();
1651 net::CapturingNetLog::CapturedEntryList entries;
1652 log.GetEntries(&entries);
1653 EXPECT_LT(0u, entries.size());
1655 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1656 int pos = net::ExpectLogContainsSomewhere(
1657 entries, 0, net::NetLog::TYPE_HTTP2_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, net::NetLog::TYPE_HTTP2_SESSION_CLOSE,
1704 net::NetLog::PHASE_NONE);
1706 if (pos < static_cast<int>(entries.size())) {
1707 CapturingNetLog::CapturedEntry entry = entries[pos];
1708 int error_code = 0;
1709 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1710 EXPECT_EQ(OK, error_code);
1711 } else {
1712 ADD_FAILURE();
1716 TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1717 session_deps_.host_resolver->set_synchronous_mode(true);
1719 MockConnect connect_data(SYNCHRONOUS, OK);
1720 MockRead reads[] = {
1721 MockRead(SYNCHRONOUS, 0, 0) // EOF
1724 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1725 data.set_connect_data(connect_data);
1726 session_deps_.socket_factory->AddSocketDataProvider(&data);
1728 CreateNetworkSession();
1730 CapturingBoundNetLog log;
1731 base::WeakPtr<SpdySession> session =
1732 CreateInsecureSpdySession(http_session_, key_, log.bound());
1733 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1735 // Flush the read completion task.
1736 base::MessageLoop::current()->RunUntilIdle();
1738 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1739 EXPECT_TRUE(session == NULL);
1741 // Check that the NetLog was filled reasonably.
1742 net::CapturingNetLog::CapturedEntryList entries;
1743 log.GetEntries(&entries);
1744 EXPECT_LT(0u, entries.size());
1746 // Check that we logged SPDY_SESSION_CLOSE correctly.
1747 int pos = net::ExpectLogContainsSomewhere(
1748 entries, 0, net::NetLog::TYPE_HTTP2_SESSION_CLOSE,
1749 net::NetLog::PHASE_NONE);
1751 if (pos < static_cast<int>(entries.size())) {
1752 CapturingNetLog::CapturedEntry entry = entries[pos];
1753 int error_code = 0;
1754 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1755 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1756 } else {
1757 ADD_FAILURE();
1761 TEST_P(SpdySessionTest, SynCompressionHistograms) {
1762 session_deps_.enable_compression = true;
1764 scoped_ptr<SpdyFrame> req(
1765 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, MEDIUM, true));
1766 MockWrite writes[] = {
1767 CreateMockWrite(*req, 0),
1769 MockRead reads[] = {
1770 MockRead(ASYNC, 0, 1) // EOF
1772 DeterministicSocketData data(reads, arraysize(reads),
1773 writes, arraysize(writes));
1774 MockConnect connect_data(SYNCHRONOUS, OK);
1775 data.set_connect_data(connect_data);
1776 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1778 CreateDeterministicNetworkSession();
1779 base::WeakPtr<SpdySession> session =
1780 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1782 GURL url(kDefaultURL);
1783 base::WeakPtr<SpdyStream> spdy_stream =
1784 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1785 session, url, MEDIUM, BoundNetLog());
1786 test::StreamDelegateDoNothing delegate(spdy_stream);
1787 spdy_stream->SetDelegate(&delegate);
1789 scoped_ptr<SpdyHeaderBlock> headers(
1790 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1791 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1792 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1794 // Write request headers & capture resulting histogram update.
1795 base::HistogramTester histogram_tester;
1797 data.RunFor(1);
1798 // Regression test of compression performance under the request fixture.
1799 switch (spdy_util_.spdy_version()) {
1800 case SPDY3:
1801 histogram_tester.ExpectBucketCount(
1802 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1803 break;
1804 case SPDY4:
1805 histogram_tester.ExpectBucketCount(
1806 "Net.SpdySynStreamCompressionPercentage", 82, 1);
1807 break;
1808 default:
1809 NOTREACHED();
1812 // Read and process EOF.
1813 data.RunFor(1);
1814 base::MessageLoop::current()->RunUntilIdle();
1815 EXPECT_TRUE(session == NULL);
1818 // Queue up a low-priority SYN_STREAM followed by a high-priority
1819 // one. The high priority one should still send first and receive
1820 // first.
1821 TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1822 // Construct the request.
1823 MockConnect connect_data(SYNCHRONOUS, OK);
1824 scoped_ptr<SpdyFrame> req_highest(
1825 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true));
1826 scoped_ptr<SpdyFrame> req_lowest(
1827 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1828 MockWrite writes[] = {
1829 CreateMockWrite(*req_highest, 0),
1830 CreateMockWrite(*req_lowest, 1),
1833 scoped_ptr<SpdyFrame> resp_highest(
1834 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1835 scoped_ptr<SpdyFrame> body_highest(
1836 spdy_util_.ConstructSpdyBodyFrame(1, true));
1837 scoped_ptr<SpdyFrame> resp_lowest(
1838 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1839 scoped_ptr<SpdyFrame> body_lowest(
1840 spdy_util_.ConstructSpdyBodyFrame(3, true));
1841 MockRead reads[] = {
1842 CreateMockRead(*resp_highest, 2),
1843 CreateMockRead(*body_highest, 3),
1844 CreateMockRead(*resp_lowest, 4),
1845 CreateMockRead(*body_lowest, 5),
1846 MockRead(ASYNC, 0, 6) // EOF
1849 session_deps_.host_resolver->set_synchronous_mode(true);
1851 DeterministicSocketData data(reads, arraysize(reads),
1852 writes, arraysize(writes));
1853 data.set_connect_data(connect_data);
1854 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1856 CreateDeterministicNetworkSession();
1858 base::WeakPtr<SpdySession> session =
1859 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1861 GURL url(kDefaultURL);
1863 base::WeakPtr<SpdyStream> spdy_stream_lowest =
1864 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1865 session, url, LOWEST, BoundNetLog());
1866 ASSERT_TRUE(spdy_stream_lowest);
1867 EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1868 test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1869 spdy_stream_lowest->SetDelegate(&delegate_lowest);
1871 base::WeakPtr<SpdyStream> spdy_stream_highest =
1872 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1873 session, url, HIGHEST, BoundNetLog());
1874 ASSERT_TRUE(spdy_stream_highest);
1875 EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1876 test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1877 spdy_stream_highest->SetDelegate(&delegate_highest);
1879 // Queue the lower priority one first.
1881 scoped_ptr<SpdyHeaderBlock> headers_lowest(
1882 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1883 spdy_stream_lowest->SendRequestHeaders(
1884 headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1885 EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1887 scoped_ptr<SpdyHeaderBlock> headers_highest(
1888 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1889 spdy_stream_highest->SendRequestHeaders(
1890 headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1891 EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1893 data.RunFor(7);
1895 EXPECT_FALSE(spdy_stream_lowest);
1896 EXPECT_FALSE(spdy_stream_highest);
1897 EXPECT_EQ(3u, delegate_lowest.stream_id());
1898 EXPECT_EQ(1u, delegate_highest.stream_id());
1901 TEST_P(SpdySessionTest, CancelStream) {
1902 MockConnect connect_data(SYNCHRONOUS, OK);
1903 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1904 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1905 scoped_ptr<SpdyFrame> req2(
1906 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1907 MockWrite writes[] = {
1908 CreateMockWrite(*req2, 0),
1911 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1912 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1913 MockRead reads[] = {
1914 CreateMockRead(*resp2, 1),
1915 CreateMockRead(*body2, 2),
1916 MockRead(ASYNC, 0, 3) // EOF
1919 session_deps_.host_resolver->set_synchronous_mode(true);
1921 DeterministicSocketData data(reads, arraysize(reads),
1922 writes, arraysize(writes));
1923 data.set_connect_data(connect_data);
1924 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1926 CreateDeterministicNetworkSession();
1928 base::WeakPtr<SpdySession> session =
1929 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1931 GURL url1(kDefaultURL);
1932 base::WeakPtr<SpdyStream> spdy_stream1 =
1933 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1934 session, url1, HIGHEST, BoundNetLog());
1935 ASSERT_TRUE(spdy_stream1.get() != NULL);
1936 EXPECT_EQ(0u, spdy_stream1->stream_id());
1937 test::StreamDelegateDoNothing delegate1(spdy_stream1);
1938 spdy_stream1->SetDelegate(&delegate1);
1940 GURL url2(kDefaultURL);
1941 base::WeakPtr<SpdyStream> spdy_stream2 =
1942 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1943 session, url2, LOWEST, BoundNetLog());
1944 ASSERT_TRUE(spdy_stream2.get() != NULL);
1945 EXPECT_EQ(0u, spdy_stream2->stream_id());
1946 test::StreamDelegateDoNothing delegate2(spdy_stream2);
1947 spdy_stream2->SetDelegate(&delegate2);
1949 scoped_ptr<SpdyHeaderBlock> headers(
1950 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1951 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1952 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1954 scoped_ptr<SpdyHeaderBlock> headers2(
1955 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1956 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1957 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1959 EXPECT_EQ(0u, spdy_stream1->stream_id());
1961 spdy_stream1->Cancel();
1962 EXPECT_EQ(NULL, spdy_stream1.get());
1964 EXPECT_EQ(0u, delegate1.stream_id());
1966 data.RunFor(1);
1968 EXPECT_EQ(0u, delegate1.stream_id());
1969 EXPECT_EQ(1u, delegate2.stream_id());
1971 spdy_stream2->Cancel();
1972 EXPECT_EQ(NULL, spdy_stream2.get());
1975 // Create two streams that are set to re-close themselves on close,
1976 // and then close the session. Nothing should blow up. Also a
1977 // regression test for http://crbug.com/139518 .
1978 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1979 session_deps_.host_resolver->set_synchronous_mode(true);
1981 MockConnect connect_data(SYNCHRONOUS, OK);
1983 // No actual data will be sent.
1984 MockWrite writes[] = {
1985 MockWrite(ASYNC, 0, 1) // EOF
1988 MockRead reads[] = {
1989 MockRead(ASYNC, 0, 0) // EOF
1991 DeterministicSocketData data(reads, arraysize(reads),
1992 writes, arraysize(writes));
1993 data.set_connect_data(connect_data);
1994 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1996 CreateDeterministicNetworkSession();
1998 base::WeakPtr<SpdySession> session =
1999 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2001 GURL url1(kDefaultURL);
2002 base::WeakPtr<SpdyStream> spdy_stream1 =
2003 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2004 session, url1, HIGHEST, BoundNetLog());
2005 ASSERT_TRUE(spdy_stream1.get() != NULL);
2006 EXPECT_EQ(0u, spdy_stream1->stream_id());
2008 GURL url2(kDefaultURL);
2009 base::WeakPtr<SpdyStream> spdy_stream2 =
2010 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2011 session, url2, LOWEST, BoundNetLog());
2012 ASSERT_TRUE(spdy_stream2.get() != NULL);
2013 EXPECT_EQ(0u, spdy_stream2->stream_id());
2015 test::ClosingDelegate delegate1(spdy_stream1);
2016 spdy_stream1->SetDelegate(&delegate1);
2018 test::ClosingDelegate delegate2(spdy_stream2);
2019 spdy_stream2->SetDelegate(&delegate2);
2021 scoped_ptr<SpdyHeaderBlock> headers(
2022 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2023 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2024 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2026 scoped_ptr<SpdyHeaderBlock> headers2(
2027 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2028 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2029 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2031 // Ensure that the streams have not yet been activated and assigned an id.
2032 EXPECT_EQ(0u, spdy_stream1->stream_id());
2033 EXPECT_EQ(0u, spdy_stream2->stream_id());
2035 // Ensure we don't crash while closing the session.
2036 session->CloseSessionOnError(ERR_ABORTED, std::string());
2038 EXPECT_EQ(NULL, spdy_stream1.get());
2039 EXPECT_EQ(NULL, spdy_stream2.get());
2041 EXPECT_TRUE(delegate1.StreamIsClosed());
2042 EXPECT_TRUE(delegate2.StreamIsClosed());
2044 base::MessageLoop::current()->RunUntilIdle();
2045 EXPECT_TRUE(session == NULL);
2048 // Create two streams that are set to close each other on close, and
2049 // then close the session. Nothing should blow up.
2050 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
2051 session_deps_.host_resolver->set_synchronous_mode(true);
2053 MockConnect connect_data(SYNCHRONOUS, OK);
2055 // No actual data will be sent.
2056 MockWrite writes[] = {
2057 MockWrite(ASYNC, 0, 1) // EOF
2060 MockRead reads[] = {
2061 MockRead(ASYNC, 0, 0) // EOF
2063 DeterministicSocketData data(reads, arraysize(reads),
2064 writes, arraysize(writes));
2065 data.set_connect_data(connect_data);
2066 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2068 CreateDeterministicNetworkSession();
2070 base::WeakPtr<SpdySession> session =
2071 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2073 GURL url1(kDefaultURL);
2074 base::WeakPtr<SpdyStream> spdy_stream1 =
2075 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2076 session, url1, HIGHEST, BoundNetLog());
2077 ASSERT_TRUE(spdy_stream1.get() != NULL);
2078 EXPECT_EQ(0u, spdy_stream1->stream_id());
2080 GURL url2(kDefaultURL);
2081 base::WeakPtr<SpdyStream> spdy_stream2 =
2082 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2083 session, url2, LOWEST, BoundNetLog());
2084 ASSERT_TRUE(spdy_stream2.get() != NULL);
2085 EXPECT_EQ(0u, spdy_stream2->stream_id());
2087 // Make |spdy_stream1| close |spdy_stream2|.
2088 test::ClosingDelegate delegate1(spdy_stream2);
2089 spdy_stream1->SetDelegate(&delegate1);
2091 // Make |spdy_stream2| close |spdy_stream1|.
2092 test::ClosingDelegate delegate2(spdy_stream1);
2093 spdy_stream2->SetDelegate(&delegate2);
2095 scoped_ptr<SpdyHeaderBlock> headers(
2096 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2097 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2098 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2100 scoped_ptr<SpdyHeaderBlock> headers2(
2101 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2102 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2103 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2105 // Ensure that the streams have not yet been activated and assigned an id.
2106 EXPECT_EQ(0u, spdy_stream1->stream_id());
2107 EXPECT_EQ(0u, spdy_stream2->stream_id());
2109 // Ensure we don't crash while closing the session.
2110 session->CloseSessionOnError(ERR_ABORTED, std::string());
2112 EXPECT_EQ(NULL, spdy_stream1.get());
2113 EXPECT_EQ(NULL, spdy_stream2.get());
2115 EXPECT_TRUE(delegate1.StreamIsClosed());
2116 EXPECT_TRUE(delegate2.StreamIsClosed());
2118 base::MessageLoop::current()->RunUntilIdle();
2119 EXPECT_TRUE(session == NULL);
2122 // Create two streams that are set to re-close themselves on close,
2123 // activate them, and then close the session. Nothing should blow up.
2124 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
2125 session_deps_.host_resolver->set_synchronous_mode(true);
2127 MockConnect connect_data(SYNCHRONOUS, OK);
2129 scoped_ptr<SpdyFrame> req1(
2130 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2131 scoped_ptr<SpdyFrame> req2(
2132 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2133 MockWrite writes[] = {
2134 CreateMockWrite(*req1, 0),
2135 CreateMockWrite(*req2, 1),
2138 MockRead reads[] = {
2139 MockRead(ASYNC, 0, 2) // EOF
2142 DeterministicSocketData data(reads, arraysize(reads),
2143 writes, arraysize(writes));
2144 data.set_connect_data(connect_data);
2145 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2147 CreateDeterministicNetworkSession();
2149 base::WeakPtr<SpdySession> session =
2150 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2152 GURL url1(kDefaultURL);
2153 base::WeakPtr<SpdyStream> spdy_stream1 =
2154 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2155 session, url1, MEDIUM, BoundNetLog());
2156 ASSERT_TRUE(spdy_stream1.get() != NULL);
2157 EXPECT_EQ(0u, spdy_stream1->stream_id());
2159 GURL url2(kDefaultURL);
2160 base::WeakPtr<SpdyStream> spdy_stream2 =
2161 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2162 session, url2, MEDIUM, BoundNetLog());
2163 ASSERT_TRUE(spdy_stream2.get() != NULL);
2164 EXPECT_EQ(0u, spdy_stream2->stream_id());
2166 test::ClosingDelegate delegate1(spdy_stream1);
2167 spdy_stream1->SetDelegate(&delegate1);
2169 test::ClosingDelegate delegate2(spdy_stream2);
2170 spdy_stream2->SetDelegate(&delegate2);
2172 scoped_ptr<SpdyHeaderBlock> headers(
2173 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2174 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2175 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2177 scoped_ptr<SpdyHeaderBlock> headers2(
2178 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2179 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2180 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2182 // Ensure that the streams have not yet been activated and assigned an id.
2183 EXPECT_EQ(0u, spdy_stream1->stream_id());
2184 EXPECT_EQ(0u, spdy_stream2->stream_id());
2186 data.RunFor(2);
2188 EXPECT_EQ(1u, spdy_stream1->stream_id());
2189 EXPECT_EQ(3u, spdy_stream2->stream_id());
2191 // Ensure we don't crash while closing the session.
2192 session->CloseSessionOnError(ERR_ABORTED, std::string());
2194 EXPECT_EQ(NULL, spdy_stream1.get());
2195 EXPECT_EQ(NULL, spdy_stream2.get());
2197 EXPECT_TRUE(delegate1.StreamIsClosed());
2198 EXPECT_TRUE(delegate2.StreamIsClosed());
2200 base::MessageLoop::current()->RunUntilIdle();
2201 EXPECT_TRUE(session == NULL);
2204 // Create two streams that are set to close each other on close,
2205 // activate them, and then close the session. Nothing should blow up.
2206 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2207 session_deps_.host_resolver->set_synchronous_mode(true);
2209 MockConnect connect_data(SYNCHRONOUS, OK);
2211 scoped_ptr<SpdyFrame> req1(
2212 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2213 scoped_ptr<SpdyFrame> req2(
2214 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2215 MockWrite writes[] = {
2216 CreateMockWrite(*req1, 0),
2217 CreateMockWrite(*req2, 1),
2220 MockRead reads[] = {
2221 MockRead(ASYNC, 0, 2) // EOF
2224 DeterministicSocketData data(reads, arraysize(reads),
2225 writes, arraysize(writes));
2226 data.set_connect_data(connect_data);
2227 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2229 CreateDeterministicNetworkSession();
2231 base::WeakPtr<SpdySession> session =
2232 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2234 GURL url1(kDefaultURL);
2235 base::WeakPtr<SpdyStream> spdy_stream1 =
2236 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2237 session, url1, MEDIUM, BoundNetLog());
2238 ASSERT_TRUE(spdy_stream1.get() != NULL);
2239 EXPECT_EQ(0u, spdy_stream1->stream_id());
2241 GURL url2(kDefaultURL);
2242 base::WeakPtr<SpdyStream> spdy_stream2 =
2243 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2244 session, url2, MEDIUM, BoundNetLog());
2245 ASSERT_TRUE(spdy_stream2.get() != NULL);
2246 EXPECT_EQ(0u, spdy_stream2->stream_id());
2248 // Make |spdy_stream1| close |spdy_stream2|.
2249 test::ClosingDelegate delegate1(spdy_stream2);
2250 spdy_stream1->SetDelegate(&delegate1);
2252 // Make |spdy_stream2| close |spdy_stream1|.
2253 test::ClosingDelegate delegate2(spdy_stream1);
2254 spdy_stream2->SetDelegate(&delegate2);
2256 scoped_ptr<SpdyHeaderBlock> headers(
2257 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2258 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2259 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2261 scoped_ptr<SpdyHeaderBlock> headers2(
2262 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2263 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2264 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2266 // Ensure that the streams have not yet been activated and assigned an id.
2267 EXPECT_EQ(0u, spdy_stream1->stream_id());
2268 EXPECT_EQ(0u, spdy_stream2->stream_id());
2270 data.RunFor(2);
2272 EXPECT_EQ(1u, spdy_stream1->stream_id());
2273 EXPECT_EQ(3u, spdy_stream2->stream_id());
2275 // Ensure we don't crash while closing the session.
2276 session->CloseSessionOnError(ERR_ABORTED, std::string());
2278 EXPECT_EQ(NULL, spdy_stream1.get());
2279 EXPECT_EQ(NULL, spdy_stream2.get());
2281 EXPECT_TRUE(delegate1.StreamIsClosed());
2282 EXPECT_TRUE(delegate2.StreamIsClosed());
2284 base::MessageLoop::current()->RunUntilIdle();
2285 EXPECT_TRUE(session == NULL);
2288 // Delegate that closes a given session when the stream is closed.
2289 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2290 public:
2291 SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2292 const base::WeakPtr<SpdySession>& session_to_close)
2293 : StreamDelegateDoNothing(stream),
2294 session_to_close_(session_to_close) {}
2296 ~SessionClosingDelegate() override {}
2298 void OnClose(int status) override {
2299 session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2302 private:
2303 base::WeakPtr<SpdySession> session_to_close_;
2306 // Close an activated stream that closes its session. Nothing should
2307 // blow up. This is a regression test for http://crbug.com/263691 .
2308 TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2309 session_deps_.host_resolver->set_synchronous_mode(true);
2311 MockConnect connect_data(SYNCHRONOUS, OK);
2313 scoped_ptr<SpdyFrame> req(
2314 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2315 scoped_ptr<SpdyFrame> rst(
2316 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2317 scoped_ptr<SpdyFrame> goaway(
2318 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2319 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2320 // despite being queued second.
2321 MockWrite writes[] = {
2322 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 1),
2323 CreateMockWrite(*rst, 2),
2326 MockRead reads[] = {
2327 MockRead(ASYNC, 0, 3) // EOF
2329 DeterministicSocketData data(reads, arraysize(reads),
2330 writes, arraysize(writes));
2331 data.set_connect_data(connect_data);
2332 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2334 CreateDeterministicNetworkSession();
2336 base::WeakPtr<SpdySession> session =
2337 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2339 GURL url(kDefaultURL);
2340 base::WeakPtr<SpdyStream> spdy_stream =
2341 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2342 session, url, MEDIUM, BoundNetLog());
2343 ASSERT_TRUE(spdy_stream.get() != NULL);
2344 EXPECT_EQ(0u, spdy_stream->stream_id());
2346 SessionClosingDelegate delegate(spdy_stream, session);
2347 spdy_stream->SetDelegate(&delegate);
2349 scoped_ptr<SpdyHeaderBlock> headers(
2350 spdy_util_.ConstructGetHeaderBlock(url.spec()));
2351 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2352 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2354 EXPECT_EQ(0u, spdy_stream->stream_id());
2356 data.RunFor(1);
2358 EXPECT_EQ(1u, spdy_stream->stream_id());
2360 // Ensure we don't crash while closing the stream (which closes the
2361 // session).
2362 spdy_stream->Cancel();
2364 EXPECT_EQ(NULL, spdy_stream.get());
2365 EXPECT_TRUE(delegate.StreamIsClosed());
2367 data.RunFor(2); // Write the RST_STREAM & GOAWAY.
2368 base::MessageLoop::current()->RunUntilIdle();
2369 EXPECT_TRUE(session == NULL);
2372 TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2373 session_deps_.host_resolver->set_synchronous_mode(true);
2375 MockConnect connect_data(SYNCHRONOUS, OK);
2377 // No actual data will be sent.
2378 MockWrite writes[] = {
2379 MockWrite(ASYNC, 0, 1) // EOF
2382 MockRead reads[] = {
2383 MockRead(ASYNC, 0, 0) // EOF
2385 DeterministicSocketData data(reads, arraysize(reads),
2386 writes, arraysize(writes));
2387 data.set_connect_data(connect_data);
2388 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2390 // Load a cert that is valid for:
2391 // www.example.org
2392 // mail.example.org
2393 // www.example.com
2394 base::FilePath certs_dir = GetTestCertsDirectory();
2395 scoped_refptr<X509Certificate> test_cert(
2396 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2397 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2399 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2400 ssl.cert = test_cert;
2401 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2403 CreateDeterministicNetworkSession();
2405 base::WeakPtr<SpdySession> session =
2406 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2408 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2409 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2410 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
2411 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2414 TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2415 session_deps_.host_resolver->set_synchronous_mode(true);
2417 MockConnect connect_data(SYNCHRONOUS, OK);
2419 // No actual data will be sent.
2420 MockWrite writes[] = {
2421 MockWrite(ASYNC, 0, 1) // EOF
2424 MockRead reads[] = {
2425 MockRead(ASYNC, 0, 0) // EOF
2427 DeterministicSocketData data(reads, arraysize(reads),
2428 writes, arraysize(writes));
2429 data.set_connect_data(connect_data);
2430 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2432 // Load a cert that is valid for:
2433 // www.example.org
2434 // mail.example.org
2435 // www.example.com
2436 base::FilePath certs_dir = GetTestCertsDirectory();
2437 scoped_refptr<X509Certificate> test_cert(
2438 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2439 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2441 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2442 ssl.channel_id_sent = true;
2443 ssl.cert = test_cert;
2444 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2446 CreateDeterministicNetworkSession();
2448 base::WeakPtr<SpdySession> session =
2449 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2451 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2452 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2453 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2454 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2457 TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2458 // TODO(rtenneti): Define a helper class/methods and move the common code in
2459 // this file.
2460 MockConnect connect_data(SYNCHRONOUS, OK);
2462 SettingsMap new_settings;
2463 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2464 const uint32 max_concurrent_streams = 1;
2465 new_settings[kSpdySettingsIds1] =
2466 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2468 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
2469 scoped_ptr<SpdyFrame> req1(
2470 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2471 scoped_ptr<SpdyFrame> req2(
2472 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
2473 scoped_ptr<SpdyFrame> req3(
2474 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
2475 MockWrite writes[] = {
2476 CreateMockWrite(*settings_ack, 1),
2477 CreateMockWrite(*req1, 2),
2478 CreateMockWrite(*req2, 5),
2479 CreateMockWrite(*req3, 8),
2482 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2483 // streams to 1.
2484 scoped_ptr<SpdyFrame> settings_frame(
2485 spdy_util_.ConstructSpdySettings(new_settings));
2487 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2488 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2490 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2491 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2493 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
2494 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2496 MockRead reads[] = {
2497 CreateMockRead(*settings_frame),
2498 CreateMockRead(*resp1, 3),
2499 CreateMockRead(*body1, 4),
2500 CreateMockRead(*resp2, 6),
2501 CreateMockRead(*body2, 7),
2502 CreateMockRead(*resp3, 9),
2503 CreateMockRead(*body3, 10),
2504 MockRead(ASYNC, 0, 11) // EOF
2507 DeterministicSocketData data(reads, arraysize(reads),
2508 writes, arraysize(writes));
2509 data.set_connect_data(connect_data);
2510 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2512 CreateDeterministicNetworkSession();
2514 base::WeakPtr<SpdySession> session =
2515 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2517 // Read the settings frame.
2518 data.RunFor(1);
2520 GURL url1(kDefaultURL);
2521 base::WeakPtr<SpdyStream> spdy_stream1 =
2522 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2523 session, url1, LOWEST, BoundNetLog());
2524 ASSERT_TRUE(spdy_stream1.get() != NULL);
2525 EXPECT_EQ(0u, spdy_stream1->stream_id());
2526 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2527 spdy_stream1->SetDelegate(&delegate1);
2529 TestCompletionCallback callback2;
2530 GURL url2(kDefaultURL);
2531 SpdyStreamRequest request2;
2532 ASSERT_EQ(ERR_IO_PENDING,
2533 request2.StartRequest(
2534 SPDY_REQUEST_RESPONSE_STREAM,
2535 session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2537 TestCompletionCallback callback3;
2538 GURL url3(kDefaultURL);
2539 SpdyStreamRequest request3;
2540 ASSERT_EQ(ERR_IO_PENDING,
2541 request3.StartRequest(
2542 SPDY_REQUEST_RESPONSE_STREAM,
2543 session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2545 EXPECT_EQ(0u, session->num_active_streams());
2546 EXPECT_EQ(1u, session->num_created_streams());
2547 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2549 scoped_ptr<SpdyHeaderBlock> headers(
2550 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2551 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2552 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2554 // Run until 1st stream is activated and then closed.
2555 EXPECT_EQ(0u, delegate1.stream_id());
2556 data.RunFor(4);
2557 EXPECT_EQ(NULL, spdy_stream1.get());
2558 EXPECT_EQ(1u, delegate1.stream_id());
2560 EXPECT_EQ(0u, session->num_active_streams());
2561 EXPECT_EQ(0u, session->num_created_streams());
2562 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2564 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2565 // create the 2nd stream.
2566 base::MessageLoop::current()->RunUntilIdle();
2568 EXPECT_EQ(0u, session->num_active_streams());
2569 EXPECT_EQ(1u, session->num_created_streams());
2570 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2572 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2573 test::StreamDelegateDoNothing delegate2(stream2);
2574 stream2->SetDelegate(&delegate2);
2575 scoped_ptr<SpdyHeaderBlock> headers2(
2576 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2577 stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2578 EXPECT_TRUE(stream2->HasUrlFromHeaders());
2580 // Run until 2nd stream is activated and then closed.
2581 EXPECT_EQ(0u, delegate2.stream_id());
2582 data.RunFor(3);
2583 EXPECT_EQ(NULL, stream2.get());
2584 EXPECT_EQ(3u, delegate2.stream_id());
2586 EXPECT_EQ(0u, session->num_active_streams());
2587 EXPECT_EQ(0u, session->num_created_streams());
2588 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2590 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2591 // create the 3rd stream.
2592 base::MessageLoop::current()->RunUntilIdle();
2594 EXPECT_EQ(0u, session->num_active_streams());
2595 EXPECT_EQ(1u, session->num_created_streams());
2596 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2598 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2599 test::StreamDelegateDoNothing delegate3(stream3);
2600 stream3->SetDelegate(&delegate3);
2601 scoped_ptr<SpdyHeaderBlock> headers3(
2602 spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2603 stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2604 EXPECT_TRUE(stream3->HasUrlFromHeaders());
2606 // Run until 2nd stream is activated and then closed.
2607 EXPECT_EQ(0u, delegate3.stream_id());
2608 data.RunFor(3);
2609 EXPECT_EQ(NULL, stream3.get());
2610 EXPECT_EQ(5u, delegate3.stream_id());
2612 EXPECT_EQ(0u, session->num_active_streams());
2613 EXPECT_EQ(0u, session->num_created_streams());
2614 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2616 data.RunFor(1);
2619 TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2620 session_deps_.host_resolver->set_synchronous_mode(true);
2622 MockRead reads[] = {
2623 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2626 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2627 MockConnect connect_data(SYNCHRONOUS, OK);
2629 data.set_connect_data(connect_data);
2630 session_deps_.socket_factory->AddSocketDataProvider(&data);
2632 CreateNetworkSession();
2634 base::WeakPtr<SpdySession> session =
2635 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2637 // Leave room for only one more stream to be created.
2638 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2639 base::WeakPtr<SpdyStream> spdy_stream =
2640 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2641 session, test_url_, MEDIUM, BoundNetLog());
2642 ASSERT_TRUE(spdy_stream != NULL);
2645 GURL url1(kDefaultURL);
2646 base::WeakPtr<SpdyStream> spdy_stream1 =
2647 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2648 session, url1, LOWEST, BoundNetLog());
2649 ASSERT_TRUE(spdy_stream1.get() != NULL);
2650 EXPECT_EQ(0u, spdy_stream1->stream_id());
2652 TestCompletionCallback callback2;
2653 GURL url2(kDefaultURL);
2654 SpdyStreamRequest request2;
2655 ASSERT_EQ(ERR_IO_PENDING,
2656 request2.StartRequest(
2657 SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2658 callback2.callback()));
2660 TestCompletionCallback callback3;
2661 GURL url3(kDefaultURL);
2662 SpdyStreamRequest request3;
2663 ASSERT_EQ(ERR_IO_PENDING,
2664 request3.StartRequest(
2665 SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2666 callback3.callback()));
2668 EXPECT_EQ(0u, session->num_active_streams());
2669 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2670 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2672 // Cancel the first stream; this will allow the second stream to be created.
2673 EXPECT_TRUE(spdy_stream1.get() != NULL);
2674 spdy_stream1->Cancel();
2675 EXPECT_EQ(NULL, spdy_stream1.get());
2677 EXPECT_EQ(OK, callback2.WaitForResult());
2678 EXPECT_EQ(0u, session->num_active_streams());
2679 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2680 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2682 // Cancel the second stream; this will allow the third stream to be created.
2683 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2684 spdy_stream2->Cancel();
2685 EXPECT_EQ(NULL, spdy_stream2.get());
2687 EXPECT_EQ(OK, callback3.WaitForResult());
2688 EXPECT_EQ(0u, session->num_active_streams());
2689 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2690 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2692 // Cancel the third stream.
2693 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2694 spdy_stream3->Cancel();
2695 EXPECT_EQ(NULL, spdy_stream3.get());
2696 EXPECT_EQ(0u, session->num_active_streams());
2697 EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
2698 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2701 // Test that SpdySession::DoReadLoop reads data from the socket
2702 // without yielding. This test makes 32k - 1 bytes of data available
2703 // on the socket for reading. It then verifies that it has read all
2704 // the available data without yielding.
2705 TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2706 MockConnect connect_data(SYNCHRONOUS, OK);
2707 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2709 scoped_ptr<SpdyFrame> req1(
2710 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2711 MockWrite writes[] = {
2712 CreateMockWrite(*req1, 0),
2715 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2716 // (-spdy_data_frame_size).
2717 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2718 const int kPayloadSize =
2719 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2720 TestDataStream test_stream;
2721 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2722 char* payload_data = payload->data();
2723 test_stream.GetBytes(payload_data, kPayloadSize);
2725 scoped_ptr<SpdyFrame> partial_data_frame(
2726 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2727 scoped_ptr<SpdyFrame> finish_data_frame(
2728 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2730 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2732 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2733 // bytes.
2734 MockRead reads[] = {
2735 CreateMockRead(*resp1, 1),
2736 CreateMockRead(*partial_data_frame, 2),
2737 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2738 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2739 CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2740 MockRead(ASYNC, 0, 6) // EOF
2743 // Create SpdySession and SpdyStream and send the request.
2744 DeterministicSocketData data(reads, arraysize(reads),
2745 writes, arraysize(writes));
2746 data.set_connect_data(connect_data);
2747 session_deps_.host_resolver->set_synchronous_mode(true);
2748 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2750 CreateDeterministicNetworkSession();
2752 base::WeakPtr<SpdySession> session =
2753 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2755 GURL url1(kDefaultURL);
2756 base::WeakPtr<SpdyStream> spdy_stream1 =
2757 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2758 session, url1, MEDIUM, BoundNetLog());
2759 ASSERT_TRUE(spdy_stream1.get() != NULL);
2760 EXPECT_EQ(0u, spdy_stream1->stream_id());
2761 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2762 spdy_stream1->SetDelegate(&delegate1);
2764 scoped_ptr<SpdyHeaderBlock> headers1(
2765 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2766 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2767 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2769 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2770 // post a task.
2771 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2773 // Run until 1st read.
2774 EXPECT_EQ(0u, delegate1.stream_id());
2775 data.RunFor(2);
2776 EXPECT_EQ(1u, delegate1.stream_id());
2777 EXPECT_EQ(0u, observer.executed_count());
2779 // Read all the data and verify SpdySession::DoReadLoop has not
2780 // posted a task.
2781 data.RunFor(4);
2782 EXPECT_EQ(NULL, spdy_stream1.get());
2784 // Verify task observer's executed_count is zero, which indicates DoRead read
2785 // all the available data.
2786 EXPECT_EQ(0u, observer.executed_count());
2787 EXPECT_TRUE(data.at_write_eof());
2788 EXPECT_TRUE(data.at_read_eof());
2791 // Test that SpdySession::DoReadLoop yields while reading the
2792 // data. This test makes 32k + 1 bytes of data available on the socket
2793 // for reading. It then verifies that DoRead has yielded even though
2794 // there is data available for it to read (i.e, socket()->Read didn't
2795 // return ERR_IO_PENDING during socket reads).
2796 TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2797 MockConnect connect_data(SYNCHRONOUS, OK);
2798 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2800 scoped_ptr<SpdyFrame> req1(
2801 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2802 MockWrite writes[] = {
2803 CreateMockWrite(*req1, 0),
2806 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2807 // (-spdy_data_frame_size).
2808 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2809 const int kPayloadSize =
2810 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2811 TestDataStream test_stream;
2812 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2813 char* payload_data = payload->data();
2814 test_stream.GetBytes(payload_data, kPayloadSize);
2816 scoped_ptr<SpdyFrame> partial_data_frame(
2817 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2818 scoped_ptr<SpdyFrame> finish_data_frame(
2819 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2821 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2823 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2824 MockRead reads[] = {
2825 CreateMockRead(*resp1, 1),
2826 CreateMockRead(*partial_data_frame, 2),
2827 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2828 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2829 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2830 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2831 MockRead(ASYNC, 0, 7) // EOF
2834 // Create SpdySession and SpdyStream and send the request.
2835 DeterministicSocketData data(reads, arraysize(reads),
2836 writes, arraysize(writes));
2837 data.set_connect_data(connect_data);
2838 session_deps_.host_resolver->set_synchronous_mode(true);
2839 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2841 CreateDeterministicNetworkSession();
2843 base::WeakPtr<SpdySession> session =
2844 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2846 GURL url1(kDefaultURL);
2847 base::WeakPtr<SpdyStream> spdy_stream1 =
2848 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2849 session, url1, MEDIUM, BoundNetLog());
2850 ASSERT_TRUE(spdy_stream1.get() != NULL);
2851 EXPECT_EQ(0u, spdy_stream1->stream_id());
2852 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2853 spdy_stream1->SetDelegate(&delegate1);
2855 scoped_ptr<SpdyHeaderBlock> headers1(
2856 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2857 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2858 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2860 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2861 // task.
2862 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2864 // Run until 1st read.
2865 EXPECT_EQ(0u, delegate1.stream_id());
2866 data.RunFor(2);
2867 EXPECT_EQ(1u, delegate1.stream_id());
2868 EXPECT_EQ(0u, observer.executed_count());
2870 // Read all the data and verify SpdySession::DoReadLoop has posted a
2871 // task.
2872 data.RunFor(6);
2873 EXPECT_EQ(NULL, spdy_stream1.get());
2875 // Verify task observer's executed_count is 1, which indicates DoRead has
2876 // posted only one task and thus yielded though there is data available for it
2877 // to read.
2878 EXPECT_EQ(1u, observer.executed_count());
2879 EXPECT_TRUE(data.at_write_eof());
2880 EXPECT_TRUE(data.at_read_eof());
2883 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2884 // + async, by doing the following MockReads.
2886 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2887 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2889 // The above reads 26K synchronously. Since that is less that 32K, we
2890 // will attempt to read again. However, that DoRead() will return
2891 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2892 // yield. When we come back, DoRead() will read the results from the
2893 // async read, and rest of the data synchronously.
2894 TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2895 MockConnect connect_data(SYNCHRONOUS, OK);
2896 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2898 scoped_ptr<SpdyFrame> req1(
2899 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2900 MockWrite writes[] = {
2901 CreateMockWrite(*req1, 0),
2904 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2905 // (-spdy_data_frame_size).
2906 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2907 TestDataStream test_stream;
2908 const int kEightKPayloadSize =
2909 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2910 scoped_refptr<net::IOBuffer> eightk_payload(
2911 new net::IOBuffer(kEightKPayloadSize));
2912 char* eightk_payload_data = eightk_payload->data();
2913 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2915 // Build buffer of 2k size.
2916 TestDataStream test_stream2;
2917 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2918 scoped_refptr<net::IOBuffer> twok_payload(
2919 new net::IOBuffer(kTwoKPayloadSize));
2920 char* twok_payload_data = twok_payload->data();
2921 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2923 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2924 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2925 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2926 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2927 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2928 1, "h", 1, DATA_FLAG_FIN));
2930 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2932 MockRead reads[] = {
2933 CreateMockRead(*resp1, 1),
2934 CreateMockRead(*eightk_data_frame, 2),
2935 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
2936 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2937 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
2938 CreateMockRead(*eightk_data_frame, 6, ASYNC),
2939 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
2940 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2941 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2942 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
2943 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
2944 MockRead(ASYNC, 0, 12) // EOF
2947 // Create SpdySession and SpdyStream and send the request.
2948 DeterministicSocketData data(reads, arraysize(reads),
2949 writes, arraysize(writes));
2950 data.set_connect_data(connect_data);
2951 session_deps_.host_resolver->set_synchronous_mode(true);
2952 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2954 CreateDeterministicNetworkSession();
2956 base::WeakPtr<SpdySession> session =
2957 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2959 GURL url1(kDefaultURL);
2960 base::WeakPtr<SpdyStream> spdy_stream1 =
2961 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2962 session, url1, MEDIUM, BoundNetLog());
2963 ASSERT_TRUE(spdy_stream1.get() != NULL);
2964 EXPECT_EQ(0u, spdy_stream1->stream_id());
2965 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2966 spdy_stream1->SetDelegate(&delegate1);
2968 scoped_ptr<SpdyHeaderBlock> headers1(
2969 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2970 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2971 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2973 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2974 // posting of tasks.
2975 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2977 // Run until 1st read.
2978 EXPECT_EQ(0u, delegate1.stream_id());
2979 data.RunFor(2);
2980 EXPECT_EQ(1u, delegate1.stream_id());
2981 EXPECT_EQ(0u, observer.executed_count());
2983 // Read all the data and verify SpdySession::DoReadLoop has posted a
2984 // task.
2985 data.RunFor(12);
2986 EXPECT_EQ(NULL, spdy_stream1.get());
2988 // Verify task observer's executed_count is 1, which indicates DoRead has
2989 // posted only one task and thus yielded though there is data available for
2990 // it to read.
2991 EXPECT_EQ(1u, observer.executed_count());
2992 EXPECT_TRUE(data.at_write_eof());
2993 EXPECT_TRUE(data.at_read_eof());
2996 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2997 // nothing blows up.
2998 TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
2999 MockConnect connect_data(SYNCHRONOUS, OK);
3000 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3002 scoped_ptr<SpdyFrame> req1(
3003 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3004 MockWrite writes[] = {
3005 CreateMockWrite(*req1, 0),
3008 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3009 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
3010 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
3012 MockRead reads[] = {
3013 CreateMockRead(*resp1, 1),
3014 CreateMockRead(*body1, 2),
3015 CreateMockRead(*goaway, 3),
3018 // Create SpdySession and SpdyStream and send the request.
3019 DeterministicSocketData data(reads, arraysize(reads),
3020 writes, arraysize(writes));
3021 data.set_connect_data(connect_data);
3022 session_deps_.host_resolver->set_synchronous_mode(true);
3023 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3025 CreateDeterministicNetworkSession();
3027 base::WeakPtr<SpdySession> session =
3028 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3030 GURL url1(kDefaultURL);
3031 base::WeakPtr<SpdyStream> spdy_stream1 =
3032 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3033 session, url1, MEDIUM, BoundNetLog());
3034 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3035 spdy_stream1->SetDelegate(&delegate1);
3036 ASSERT_TRUE(spdy_stream1.get() != NULL);
3037 EXPECT_EQ(0u, spdy_stream1->stream_id());
3039 scoped_ptr<SpdyHeaderBlock> headers1(
3040 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3041 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
3042 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3044 // Run until 1st read.
3045 EXPECT_EQ(0u, spdy_stream1->stream_id());
3046 data.RunFor(1);
3047 EXPECT_EQ(1u, spdy_stream1->stream_id());
3049 // Run until GoAway.
3050 data.RunFor(3);
3051 EXPECT_EQ(NULL, spdy_stream1.get());
3052 EXPECT_TRUE(data.at_write_eof());
3053 EXPECT_TRUE(data.at_read_eof());
3054 EXPECT_TRUE(session == NULL);
3057 // Within this framework, a SpdySession should be initialized with
3058 // flow control disabled for protocol version 2, with flow control
3059 // enabled only for streams for protocol version 3, and with flow
3060 // control enabled for streams and sessions for higher versions.
3061 TEST_P(SpdySessionTest, ProtocolNegotiation) {
3062 session_deps_.host_resolver->set_synchronous_mode(true);
3064 MockConnect connect_data(SYNCHRONOUS, OK);
3065 MockRead reads[] = {
3066 MockRead(SYNCHRONOUS, 0, 0) // EOF
3068 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3069 data.set_connect_data(connect_data);
3070 session_deps_.socket_factory->AddSocketDataProvider(&data);
3072 CreateNetworkSession();
3073 base::WeakPtr<SpdySession> session =
3074 CreateFakeSpdySession(spdy_session_pool_, key_);
3076 EXPECT_EQ(spdy_util_.spdy_version(),
3077 session->buffered_spdy_framer_->protocol_version());
3078 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3079 session->flow_control_state());
3080 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3081 session->session_send_window_size_);
3082 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3083 session->session_recv_window_size_);
3084 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3087 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3088 // pointers to the idle session are currently held.
3089 TEST_P(SpdySessionTest, CloseOneIdleConnection) {
3090 ClientSocketPoolManager::set_max_sockets_per_group(
3091 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3092 ClientSocketPoolManager::set_max_sockets_per_pool(
3093 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3095 MockConnect connect_data(SYNCHRONOUS, OK);
3096 MockRead reads[] = {
3097 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3099 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3100 data.set_connect_data(connect_data);
3101 session_deps_.socket_factory->AddSocketDataProvider(&data);
3102 session_deps_.socket_factory->AddSocketDataProvider(&data);
3104 CreateNetworkSession();
3106 TransportClientSocketPool* pool =
3107 http_session_->GetTransportSocketPool(
3108 HttpNetworkSession::NORMAL_SOCKET_POOL);
3110 // Create an idle SPDY session.
3111 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3112 PRIVACY_MODE_DISABLED);
3113 base::WeakPtr<SpdySession> session1 =
3114 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3115 EXPECT_FALSE(pool->IsStalled());
3117 // Trying to create a new connection should cause the pool to be stalled, and
3118 // post a task asynchronously to try and close the session.
3119 TestCompletionCallback callback2;
3120 HostPortPair host_port2("2.com", 80);
3121 scoped_refptr<TransportSocketParams> params2(
3122 new TransportSocketParams(
3123 host_port2, false, false, OnHostResolutionCallback(),
3124 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3125 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3126 EXPECT_EQ(ERR_IO_PENDING,
3127 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3128 callback2.callback(), pool, BoundNetLog()));
3129 EXPECT_TRUE(pool->IsStalled());
3131 // The socket pool should close the connection asynchronously and establish a
3132 // new connection.
3133 EXPECT_EQ(OK, callback2.WaitForResult());
3134 EXPECT_FALSE(pool->IsStalled());
3135 EXPECT_TRUE(session1 == NULL);
3138 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3139 // pointers to the idle session are currently held, in the case the SPDY session
3140 // has an alias.
3141 TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
3142 ClientSocketPoolManager::set_max_sockets_per_group(
3143 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3144 ClientSocketPoolManager::set_max_sockets_per_pool(
3145 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3147 MockConnect connect_data(SYNCHRONOUS, OK);
3148 MockRead reads[] = {
3149 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3151 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3152 data.set_connect_data(connect_data);
3153 session_deps_.socket_factory->AddSocketDataProvider(&data);
3154 session_deps_.socket_factory->AddSocketDataProvider(&data);
3156 session_deps_.host_resolver->set_synchronous_mode(true);
3157 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3158 "1.com", "192.168.0.2", std::string());
3159 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3160 "2.com", "192.168.0.2", std::string());
3161 // Not strictly needed.
3162 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3163 "3.com", "192.168.0.3", std::string());
3165 CreateNetworkSession();
3167 TransportClientSocketPool* pool =
3168 http_session_->GetTransportSocketPool(
3169 HttpNetworkSession::NORMAL_SOCKET_POOL);
3171 // Create an idle SPDY session.
3172 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3173 PRIVACY_MODE_DISABLED);
3174 base::WeakPtr<SpdySession> session1 =
3175 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3176 EXPECT_FALSE(pool->IsStalled());
3178 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3179 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3180 PRIVACY_MODE_DISABLED);
3181 HostResolver::RequestInfo info(key2.host_port_pair());
3182 AddressList addresses;
3183 // Pre-populate the DNS cache, since a synchronous resolution is required in
3184 // order to create the alias.
3185 session_deps_.host_resolver->Resolve(info,
3186 DEFAULT_PRIORITY,
3187 &addresses,
3188 CompletionCallback(),
3189 NULL,
3190 BoundNetLog());
3191 // Get a session for |key2|, which should return the session created earlier.
3192 base::WeakPtr<SpdySession> session2 =
3193 spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3194 ASSERT_EQ(session1.get(), session2.get());
3195 EXPECT_FALSE(pool->IsStalled());
3197 // Trying to create a new connection should cause the pool to be stalled, and
3198 // post a task asynchronously to try and close the session.
3199 TestCompletionCallback callback3;
3200 HostPortPair host_port3("3.com", 80);
3201 scoped_refptr<TransportSocketParams> params3(
3202 new TransportSocketParams(
3203 host_port3, false, false, OnHostResolutionCallback(),
3204 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3205 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3206 EXPECT_EQ(ERR_IO_PENDING,
3207 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3208 callback3.callback(), pool, BoundNetLog()));
3209 EXPECT_TRUE(pool->IsStalled());
3211 // The socket pool should close the connection asynchronously and establish a
3212 // new connection.
3213 EXPECT_EQ(OK, callback3.WaitForResult());
3214 EXPECT_FALSE(pool->IsStalled());
3215 EXPECT_TRUE(session1 == NULL);
3216 EXPECT_TRUE(session2 == NULL);
3219 // Tests that when a SPDY session becomes idle, it closes itself if there is
3220 // a lower layer pool stalled on the per-pool socket limit.
3221 TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3222 ClientSocketPoolManager::set_max_sockets_per_group(
3223 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3224 ClientSocketPoolManager::set_max_sockets_per_pool(
3225 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3227 MockConnect connect_data(SYNCHRONOUS, OK);
3228 MockRead reads[] = {
3229 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3231 scoped_ptr<SpdyFrame> req1(
3232 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3233 scoped_ptr<SpdyFrame> cancel1(
3234 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3235 MockWrite writes[] = {
3236 CreateMockWrite(*req1, 1),
3237 CreateMockWrite(*cancel1, 1),
3239 StaticSocketDataProvider data(reads, arraysize(reads),
3240 writes, arraysize(writes));
3241 data.set_connect_data(connect_data);
3242 session_deps_.socket_factory->AddSocketDataProvider(&data);
3244 MockRead http_reads[] = {
3245 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3247 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
3248 NULL, 0);
3249 http_data.set_connect_data(connect_data);
3250 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3253 CreateNetworkSession();
3255 TransportClientSocketPool* pool =
3256 http_session_->GetTransportSocketPool(
3257 HttpNetworkSession::NORMAL_SOCKET_POOL);
3259 // Create a SPDY session.
3260 GURL url1(kDefaultURL);
3261 SpdySessionKey key1(HostPortPair(url1.host(), 80),
3262 ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3263 base::WeakPtr<SpdySession> session1 =
3264 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3265 EXPECT_FALSE(pool->IsStalled());
3267 // Create a stream using the session, and send a request.
3269 TestCompletionCallback callback1;
3270 base::WeakPtr<SpdyStream> spdy_stream1 =
3271 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3272 session1, url1, DEFAULT_PRIORITY,
3273 BoundNetLog());
3274 ASSERT_TRUE(spdy_stream1.get());
3275 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3276 spdy_stream1->SetDelegate(&delegate1);
3278 scoped_ptr<SpdyHeaderBlock> headers1(
3279 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3280 EXPECT_EQ(ERR_IO_PENDING,
3281 spdy_stream1->SendRequestHeaders(
3282 headers1.Pass(), NO_MORE_DATA_TO_SEND));
3283 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3285 base::MessageLoop::current()->RunUntilIdle();
3287 // Trying to create a new connection should cause the pool to be stalled, and
3288 // post a task asynchronously to try and close the session.
3289 TestCompletionCallback callback2;
3290 HostPortPair host_port2("2.com", 80);
3291 scoped_refptr<TransportSocketParams> params2(
3292 new TransportSocketParams(
3293 host_port2, false, false, OnHostResolutionCallback(),
3294 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3295 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3296 EXPECT_EQ(ERR_IO_PENDING,
3297 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3298 callback2.callback(), pool, BoundNetLog()));
3299 EXPECT_TRUE(pool->IsStalled());
3301 // Running the message loop should cause the socket pool to ask the SPDY
3302 // session to close an idle socket, but since the socket is in use, nothing
3303 // happens.
3304 base::RunLoop().RunUntilIdle();
3305 EXPECT_TRUE(pool->IsStalled());
3306 EXPECT_FALSE(callback2.have_result());
3308 // Cancelling the request should result in the session's socket being
3309 // closed, since the pool is stalled.
3310 ASSERT_TRUE(spdy_stream1.get());
3311 spdy_stream1->Cancel();
3312 base::RunLoop().RunUntilIdle();
3313 ASSERT_FALSE(pool->IsStalled());
3314 EXPECT_EQ(OK, callback2.WaitForResult());
3317 // Verify that SpdySessionKey and therefore SpdySession is different when
3318 // privacy mode is enabled or disabled.
3319 TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3320 CreateDeterministicNetworkSession();
3322 HostPortPair host_port_pair("www.google.com", 443);
3323 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3324 PRIVACY_MODE_ENABLED);
3325 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3326 PRIVACY_MODE_DISABLED);
3328 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3329 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3331 // Add SpdySession with PrivacyMode Enabled to the pool.
3332 base::WeakPtr<SpdySession> session_privacy_enabled =
3333 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3335 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3336 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3338 // Add SpdySession with PrivacyMode Disabled to the pool.
3339 base::WeakPtr<SpdySession> session_privacy_disabled =
3340 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3342 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3343 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3345 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3346 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3347 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3349 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3350 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3351 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3354 // Delegate that creates another stream when its stream is closed.
3355 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3356 public:
3357 StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3358 const base::WeakPtr<SpdySession>& session)
3359 : StreamDelegateDoNothing(stream),
3360 session_(session) {}
3362 ~StreamCreatingDelegate() override {}
3364 void OnClose(int status) override {
3365 GURL url(kDefaultURL);
3366 ignore_result(
3367 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3368 session_, url, MEDIUM, BoundNetLog()));
3371 private:
3372 const base::WeakPtr<SpdySession> session_;
3375 // Create another stream in response to a stream being reset. Nothing
3376 // should blow up. This is a regression test for
3377 // http://crbug.com/263690 .
3378 TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3379 session_deps_.host_resolver->set_synchronous_mode(true);
3381 MockConnect connect_data(SYNCHRONOUS, OK);
3383 scoped_ptr<SpdyFrame> req(
3384 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3385 MockWrite writes[] = {
3386 CreateMockWrite(*req, 0),
3389 scoped_ptr<SpdyFrame> rst(
3390 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3391 MockRead reads[] = {
3392 CreateMockRead(*rst, 1),
3393 MockRead(ASYNC, 0, 2) // EOF
3395 DeterministicSocketData data(reads, arraysize(reads),
3396 writes, arraysize(writes));
3397 data.set_connect_data(connect_data);
3398 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3400 CreateDeterministicNetworkSession();
3402 base::WeakPtr<SpdySession> session =
3403 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3405 GURL url(kDefaultURL);
3406 base::WeakPtr<SpdyStream> spdy_stream =
3407 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3408 session, url, MEDIUM, BoundNetLog());
3409 ASSERT_TRUE(spdy_stream.get() != NULL);
3410 EXPECT_EQ(0u, spdy_stream->stream_id());
3412 StreamCreatingDelegate delegate(spdy_stream, session);
3413 spdy_stream->SetDelegate(&delegate);
3415 scoped_ptr<SpdyHeaderBlock> headers(
3416 spdy_util_.ConstructGetHeaderBlock(url.spec()));
3417 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3418 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3420 EXPECT_EQ(0u, spdy_stream->stream_id());
3422 data.RunFor(1);
3424 EXPECT_EQ(1u, spdy_stream->stream_id());
3426 // Cause the stream to be reset, which should cause another stream
3427 // to be created.
3428 data.RunFor(1);
3430 EXPECT_EQ(NULL, spdy_stream.get());
3431 EXPECT_TRUE(delegate.StreamIsClosed());
3432 EXPECT_EQ(0u, session->num_active_streams());
3433 EXPECT_EQ(1u, session->num_created_streams());
3436 // The tests below are only for SPDY/3 and above.
3438 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3439 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3440 // gets sent.
3441 SettingsMap new_settings;
3442 int32 window_size = 1;
3443 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3444 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3446 // Set up the socket so we read a SETTINGS frame that sets
3447 // INITIAL_WINDOW_SIZE.
3448 MockConnect connect_data(SYNCHRONOUS, OK);
3449 scoped_ptr<SpdyFrame> settings_frame(
3450 spdy_util_.ConstructSpdySettings(new_settings));
3451 MockRead reads[] = {
3452 CreateMockRead(*settings_frame, 0),
3453 MockRead(ASYNC, 0, 1) // EOF
3456 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3457 MockWrite writes[] = {
3458 CreateMockWrite(*settings_ack, 2),
3461 session_deps_.host_resolver->set_synchronous_mode(true);
3463 DeterministicSocketData data(reads, arraysize(reads),
3464 writes, arraysize(writes));
3465 data.set_connect_data(connect_data);
3466 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3468 CreateDeterministicNetworkSession();
3470 base::WeakPtr<SpdySession> session =
3471 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3472 base::WeakPtr<SpdyStream> spdy_stream1 =
3473 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3474 session, test_url_, MEDIUM, BoundNetLog());
3475 ASSERT_TRUE(spdy_stream1.get() != NULL);
3476 TestCompletionCallback callback1;
3477 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3479 data.RunFor(1); // Process the SETTINGS frame, but not the EOF
3480 base::MessageLoop::current()->RunUntilIdle();
3481 EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3482 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3484 // Release the first one, this will allow the second to be created.
3485 spdy_stream1->Cancel();
3486 EXPECT_EQ(NULL, spdy_stream1.get());
3488 base::WeakPtr<SpdyStream> spdy_stream2 =
3489 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3490 session, test_url_, MEDIUM, BoundNetLog());
3491 ASSERT_TRUE(spdy_stream2.get() != NULL);
3492 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3493 spdy_stream2->Cancel();
3494 EXPECT_EQ(NULL, spdy_stream2.get());
3497 // The tests below are only for SPDY/3.1 and above.
3499 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3500 // adjust the session receive window size for SPDY 3.1 and higher. In
3501 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3502 // sending a WINDOW_UPDATE frame for a large enough delta.
3503 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3504 if (GetParam() < kProtoSPDY31)
3505 return;
3507 session_deps_.host_resolver->set_synchronous_mode(true);
3509 const int32 initial_window_size =
3510 SpdySession::GetInitialWindowSize(GetParam());
3511 const int32 delta_window_size = 100;
3513 MockConnect connect_data(SYNCHRONOUS, OK);
3514 MockRead reads[] = {
3515 MockRead(ASYNC, 0, 1) // EOF
3517 scoped_ptr<SpdyFrame> window_update(spdy_util_.ConstructSpdyWindowUpdate(
3518 kSessionFlowControlStreamId, initial_window_size + delta_window_size));
3519 MockWrite writes[] = {
3520 CreateMockWrite(*window_update, 0),
3522 DeterministicSocketData data(reads, arraysize(reads),
3523 writes, arraysize(writes));
3524 data.set_connect_data(connect_data);
3525 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3527 CreateDeterministicNetworkSession();
3528 base::WeakPtr<SpdySession> session =
3529 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3530 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3531 session->flow_control_state());
3533 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3534 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3536 session->IncreaseRecvWindowSize(delta_window_size);
3537 EXPECT_EQ(initial_window_size + delta_window_size,
3538 session->session_recv_window_size_);
3539 EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3541 // Should trigger sending a WINDOW_UPDATE frame.
3542 session->IncreaseRecvWindowSize(initial_window_size);
3543 EXPECT_EQ(initial_window_size + delta_window_size + initial_window_size,
3544 session->session_recv_window_size_);
3545 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3547 data.RunFor(1);
3549 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3550 session->in_io_loop_ = true;
3551 session->DecreaseRecvWindowSize(initial_window_size + delta_window_size +
3552 initial_window_size);
3553 session->in_io_loop_ = false;
3554 EXPECT_EQ(0, session->session_recv_window_size_);
3555 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3558 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3559 // adjust the session send window size when the "enable_spdy_31" flag
3560 // is set.
3561 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3562 if (GetParam() < kProtoSPDY31)
3563 return;
3565 session_deps_.host_resolver->set_synchronous_mode(true);
3567 MockConnect connect_data(SYNCHRONOUS, OK);
3568 MockRead reads[] = {
3569 MockRead(SYNCHRONOUS, 0, 0) // EOF
3571 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3572 data.set_connect_data(connect_data);
3573 session_deps_.socket_factory->AddSocketDataProvider(&data);
3575 CreateNetworkSession();
3576 base::WeakPtr<SpdySession> session =
3577 CreateFakeSpdySession(spdy_session_pool_, key_);
3578 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3579 session->flow_control_state());
3581 const int32 initial_window_size =
3582 SpdySession::GetInitialWindowSize(GetParam());
3583 const int32 delta_window_size = 100;
3585 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3587 session->IncreaseSendWindowSize(delta_window_size);
3588 EXPECT_EQ(initial_window_size + delta_window_size,
3589 session->session_send_window_size_);
3591 session->DecreaseSendWindowSize(delta_window_size);
3592 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3595 // Incoming data for an inactive stream should not cause the session
3596 // receive window size to decrease, but it should cause the unacked
3597 // bytes to increase.
3598 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3599 if (GetParam() < kProtoSPDY31)
3600 return;
3602 session_deps_.host_resolver->set_synchronous_mode(true);
3604 MockConnect connect_data(SYNCHRONOUS, OK);
3605 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3606 MockRead reads[] = {
3607 CreateMockRead(*resp, 0),
3608 MockRead(ASYNC, 0, 1) // EOF
3610 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3611 data.set_connect_data(connect_data);
3612 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3614 CreateDeterministicNetworkSession();
3615 base::WeakPtr<SpdySession> session =
3616 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3617 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3618 session->flow_control_state());
3620 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3621 session->session_recv_window_size_);
3622 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3624 data.RunFor(1);
3626 EXPECT_EQ(SpdySession::GetInitialWindowSize(GetParam()),
3627 session->session_recv_window_size_);
3628 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3630 data.RunFor(1);
3633 // A delegate that drops any received data.
3634 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3635 public:
3636 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3637 base::StringPiece data)
3638 : StreamDelegateSendImmediate(stream, data) {}
3640 ~DropReceivedDataDelegate() override {}
3642 // Drop any received data.
3643 void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override {}
3646 // Send data back and forth but use a delegate that drops its received
3647 // data. The receive window should still increase to its original
3648 // value, i.e. we shouldn't "leak" receive window bytes.
3649 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3650 if (GetParam() < kProtoSPDY31)
3651 return;
3653 const char kStreamUrl[] = "http://www.google.com/";
3655 const int32 msg_data_size = 100;
3656 const std::string msg_data(msg_data_size, 'a');
3658 MockConnect connect_data(SYNCHRONOUS, OK);
3660 scoped_ptr<SpdyFrame> req(
3661 spdy_util_.ConstructSpdyPost(
3662 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3663 scoped_ptr<SpdyFrame> msg(
3664 spdy_util_.ConstructSpdyBodyFrame(
3665 1, msg_data.data(), msg_data_size, false));
3666 MockWrite writes[] = {
3667 CreateMockWrite(*req, 0),
3668 CreateMockWrite(*msg, 2),
3671 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3672 scoped_ptr<SpdyFrame> echo(
3673 spdy_util_.ConstructSpdyBodyFrame(
3674 1, msg_data.data(), msg_data_size, false));
3675 scoped_ptr<SpdyFrame> window_update(
3676 spdy_util_.ConstructSpdyWindowUpdate(
3677 kSessionFlowControlStreamId, msg_data_size));
3678 MockRead reads[] = {
3679 CreateMockRead(*resp, 1),
3680 CreateMockRead(*echo, 3),
3681 MockRead(ASYNC, 0, 4) // EOF
3684 // Create SpdySession and SpdyStream and send the request.
3685 DeterministicSocketData data(reads, arraysize(reads),
3686 writes, arraysize(writes));
3687 data.set_connect_data(connect_data);
3688 session_deps_.host_resolver->set_synchronous_mode(true);
3689 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3691 CreateDeterministicNetworkSession();
3693 base::WeakPtr<SpdySession> session =
3694 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3696 GURL url(kStreamUrl);
3697 base::WeakPtr<SpdyStream> stream =
3698 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3699 session, url, MEDIUM, BoundNetLog());
3700 ASSERT_TRUE(stream.get() != NULL);
3701 EXPECT_EQ(0u, stream->stream_id());
3703 DropReceivedDataDelegate delegate(stream, msg_data);
3704 stream->SetDelegate(&delegate);
3706 scoped_ptr<SpdyHeaderBlock> headers(
3707 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3708 EXPECT_EQ(ERR_IO_PENDING,
3709 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3710 EXPECT_TRUE(stream->HasUrlFromHeaders());
3712 const int32 initial_window_size =
3713 SpdySession::GetInitialWindowSize(GetParam());
3714 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3715 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3717 data.RunFor(4);
3719 EXPECT_TRUE(data.at_write_eof());
3720 EXPECT_TRUE(data.at_read_eof());
3722 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3723 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3725 stream->Close();
3726 EXPECT_EQ(NULL, stream.get());
3728 EXPECT_EQ(OK, delegate.WaitForClose());
3730 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3731 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3734 // Send data back and forth but close the stream before its data frame
3735 // can be written to the socket. The send window should then increase
3736 // to its original value, i.e. we shouldn't "leak" send window bytes.
3737 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3738 if (GetParam() < kProtoSPDY31)
3739 return;
3741 const char kStreamUrl[] = "http://www.google.com/";
3743 const int32 msg_data_size = 100;
3744 const std::string msg_data(msg_data_size, 'a');
3746 MockConnect connect_data(SYNCHRONOUS, OK);
3748 scoped_ptr<SpdyFrame> req(
3749 spdy_util_.ConstructSpdyPost(
3750 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3751 MockWrite writes[] = {
3752 CreateMockWrite(*req, 0),
3755 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3756 MockRead reads[] = {
3757 CreateMockRead(*resp, 1),
3758 MockRead(ASYNC, 0, 2) // EOF
3761 // Create SpdySession and SpdyStream and send the request.
3762 DeterministicSocketData data(reads, arraysize(reads),
3763 writes, arraysize(writes));
3764 data.set_connect_data(connect_data);
3765 session_deps_.host_resolver->set_synchronous_mode(true);
3766 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3768 CreateDeterministicNetworkSession();
3770 base::WeakPtr<SpdySession> session =
3771 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3773 GURL url(kStreamUrl);
3774 base::WeakPtr<SpdyStream> stream =
3775 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3776 session, url, MEDIUM, BoundNetLog());
3777 ASSERT_TRUE(stream.get() != NULL);
3778 EXPECT_EQ(0u, stream->stream_id());
3780 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3781 stream->SetDelegate(&delegate);
3783 scoped_ptr<SpdyHeaderBlock> headers(
3784 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3785 EXPECT_EQ(ERR_IO_PENDING,
3786 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3787 EXPECT_TRUE(stream->HasUrlFromHeaders());
3789 const int32 initial_window_size =
3790 SpdySession::GetInitialWindowSize(GetParam());
3791 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3793 data.RunFor(1);
3795 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3797 data.RunFor(1);
3799 EXPECT_TRUE(data.at_write_eof());
3800 EXPECT_TRUE(data.at_read_eof());
3802 EXPECT_EQ(initial_window_size - msg_data_size,
3803 session->session_send_window_size_);
3805 // Closing the stream should increase the session's send window.
3806 stream->Close();
3807 EXPECT_EQ(NULL, stream.get());
3809 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3811 EXPECT_EQ(OK, delegate.WaitForClose());
3814 // Send data back and forth; the send and receive windows should
3815 // change appropriately.
3816 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
3817 if (GetParam() < kProtoSPDY31)
3818 return;
3820 const char kStreamUrl[] = "http://www.google.com/";
3822 const int32 msg_data_size = 100;
3823 const std::string msg_data(msg_data_size, 'a');
3825 MockConnect connect_data(SYNCHRONOUS, OK);
3827 scoped_ptr<SpdyFrame> req(
3828 spdy_util_.ConstructSpdyPost(
3829 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3830 scoped_ptr<SpdyFrame> msg(
3831 spdy_util_.ConstructSpdyBodyFrame(
3832 1, msg_data.data(), msg_data_size, false));
3833 MockWrite writes[] = {
3834 CreateMockWrite(*req, 0),
3835 CreateMockWrite(*msg, 2),
3838 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3839 scoped_ptr<SpdyFrame> echo(
3840 spdy_util_.ConstructSpdyBodyFrame(
3841 1, msg_data.data(), msg_data_size, false));
3842 scoped_ptr<SpdyFrame> window_update(
3843 spdy_util_.ConstructSpdyWindowUpdate(
3844 kSessionFlowControlStreamId, msg_data_size));
3845 MockRead reads[] = {
3846 CreateMockRead(*resp, 1),
3847 CreateMockRead(*echo, 3),
3848 CreateMockRead(*window_update, 4),
3849 MockRead(ASYNC, 0, 5) // EOF
3852 // Create SpdySession and SpdyStream and send the request.
3853 DeterministicSocketData data(reads, arraysize(reads),
3854 writes, arraysize(writes));
3855 data.set_connect_data(connect_data);
3856 session_deps_.host_resolver->set_synchronous_mode(true);
3857 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3859 CreateDeterministicNetworkSession();
3861 base::WeakPtr<SpdySession> session =
3862 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3864 GURL url(kStreamUrl);
3865 base::WeakPtr<SpdyStream> stream =
3866 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3867 session, url, MEDIUM, BoundNetLog());
3868 ASSERT_TRUE(stream.get() != NULL);
3869 EXPECT_EQ(0u, stream->stream_id());
3871 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3872 stream->SetDelegate(&delegate);
3874 scoped_ptr<SpdyHeaderBlock> headers(
3875 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3876 EXPECT_EQ(ERR_IO_PENDING,
3877 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3878 EXPECT_TRUE(stream->HasUrlFromHeaders());
3880 const int32 initial_window_size =
3881 SpdySession::GetInitialWindowSize(GetParam());
3882 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3883 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3884 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3886 data.RunFor(1);
3888 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3889 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3890 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3892 data.RunFor(1);
3894 EXPECT_EQ(initial_window_size - msg_data_size,
3895 session->session_send_window_size_);
3896 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3897 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3899 data.RunFor(1);
3901 EXPECT_EQ(initial_window_size - msg_data_size,
3902 session->session_send_window_size_);
3903 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3904 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3906 data.RunFor(1);
3908 EXPECT_EQ(initial_window_size - msg_data_size,
3909 session->session_send_window_size_);
3910 EXPECT_EQ(initial_window_size - msg_data_size,
3911 session->session_recv_window_size_);
3912 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3914 data.RunFor(1);
3916 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3917 EXPECT_EQ(initial_window_size - msg_data_size,
3918 session->session_recv_window_size_);
3919 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3921 EXPECT_TRUE(data.at_write_eof());
3922 EXPECT_TRUE(data.at_read_eof());
3924 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
3926 // Draining the delegate's read queue should increase the session's
3927 // receive window.
3928 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3929 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3930 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3932 stream->Close();
3933 EXPECT_EQ(NULL, stream.get());
3935 EXPECT_EQ(OK, delegate.WaitForClose());
3937 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3938 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3939 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3942 // Given a stall function and an unstall function, runs a test to make
3943 // sure that a stream resumes after unstall.
3944 void SpdySessionTest::RunResumeAfterUnstallTest(
3945 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
3946 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
3947 unstall_function) {
3948 const char kStreamUrl[] = "http://www.google.com/";
3949 GURL url(kStreamUrl);
3951 session_deps_.host_resolver->set_synchronous_mode(true);
3953 scoped_ptr<SpdyFrame> req(
3954 spdy_util_.ConstructSpdyPost(
3955 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3956 scoped_ptr<SpdyFrame> body(
3957 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3958 MockWrite writes[] = {
3959 CreateMockWrite(*req, 0),
3960 CreateMockWrite(*body, 1),
3963 scoped_ptr<SpdyFrame> resp(
3964 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3965 scoped_ptr<SpdyFrame> echo(
3966 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
3967 MockRead reads[] = {
3968 CreateMockRead(*resp, 2),
3969 MockRead(ASYNC, 0, 0, 3), // EOF
3972 DeterministicSocketData data(reads, arraysize(reads),
3973 writes, arraysize(writes));
3974 MockConnect connect_data(SYNCHRONOUS, OK);
3975 data.set_connect_data(connect_data);
3977 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3979 CreateDeterministicNetworkSession();
3980 base::WeakPtr<SpdySession> session =
3981 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3982 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3983 session->flow_control_state());
3985 base::WeakPtr<SpdyStream> stream =
3986 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3987 session, url, LOWEST, BoundNetLog());
3988 ASSERT_TRUE(stream.get() != NULL);
3990 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
3991 stream->SetDelegate(&delegate);
3993 EXPECT_FALSE(stream->HasUrlFromHeaders());
3994 EXPECT_FALSE(stream->send_stalled_by_flow_control());
3996 scoped_ptr<SpdyHeaderBlock> headers(
3997 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3998 EXPECT_EQ(ERR_IO_PENDING,
3999 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4000 EXPECT_TRUE(stream->HasUrlFromHeaders());
4001 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
4003 stall_function.Run(session.get(), stream.get());
4005 data.RunFor(1);
4007 EXPECT_TRUE(stream->send_stalled_by_flow_control());
4009 unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
4011 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4013 data.RunFor(3);
4015 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
4017 EXPECT_TRUE(delegate.send_headers_completed());
4018 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
4019 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
4020 EXPECT_TRUE(data.at_write_eof());
4023 // Run the resume-after-unstall test with all possible stall and
4024 // unstall sequences.
4026 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
4027 if (GetParam() < kProtoSPDY31)
4028 return;
4030 RunResumeAfterUnstallTest(
4031 base::Bind(&SpdySessionTest::StallSessionOnly,
4032 base::Unretained(this)),
4033 base::Bind(&SpdySessionTest::UnstallSessionOnly,
4034 base::Unretained(this)));
4037 // Equivalent to
4038 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4039 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
4040 if (GetParam() < kProtoSPDY31)
4041 return;
4043 RunResumeAfterUnstallTest(
4044 base::Bind(&SpdySessionTest::StallStreamOnly,
4045 base::Unretained(this)),
4046 base::Bind(&SpdySessionTest::UnstallStreamOnly,
4047 base::Unretained(this)));
4050 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4051 if (GetParam() < kProtoSPDY31)
4052 return;
4054 RunResumeAfterUnstallTest(
4055 base::Bind(&SpdySessionTest::StallSessionStream,
4056 base::Unretained(this)),
4057 base::Bind(&SpdySessionTest::UnstallSessionStream,
4058 base::Unretained(this)));
4061 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4062 if (GetParam() < kProtoSPDY31)
4063 return;
4065 RunResumeAfterUnstallTest(
4066 base::Bind(&SpdySessionTest::StallStreamSession,
4067 base::Unretained(this)),
4068 base::Bind(&SpdySessionTest::UnstallSessionStream,
4069 base::Unretained(this)));
4072 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4073 if (GetParam() < kProtoSPDY31)
4074 return;
4076 RunResumeAfterUnstallTest(
4077 base::Bind(&SpdySessionTest::StallStreamSession,
4078 base::Unretained(this)),
4079 base::Bind(&SpdySessionTest::UnstallStreamSession,
4080 base::Unretained(this)));
4083 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4084 if (GetParam() < kProtoSPDY31)
4085 return;
4087 RunResumeAfterUnstallTest(
4088 base::Bind(&SpdySessionTest::StallSessionStream,
4089 base::Unretained(this)),
4090 base::Bind(&SpdySessionTest::UnstallStreamSession,
4091 base::Unretained(this)));
4094 // Cause a stall by reducing the flow control send window to 0. The
4095 // streams should resume in priority order when that window is then
4096 // increased.
4097 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4098 if (GetParam() < kProtoSPDY31)
4099 return;
4101 const char kStreamUrl[] = "http://www.google.com/";
4102 GURL url(kStreamUrl);
4104 session_deps_.host_resolver->set_synchronous_mode(true);
4106 scoped_ptr<SpdyFrame> req1(
4107 spdy_util_.ConstructSpdyPost(
4108 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4109 scoped_ptr<SpdyFrame> req2(
4110 spdy_util_.ConstructSpdyPost(
4111 kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
4112 scoped_ptr<SpdyFrame> body1(
4113 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4114 scoped_ptr<SpdyFrame> body2(
4115 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4116 MockWrite writes[] = {
4117 CreateMockWrite(*req1, 0),
4118 CreateMockWrite(*req2, 1),
4119 CreateMockWrite(*body2, 2),
4120 CreateMockWrite(*body1, 3),
4123 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4124 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4125 MockRead reads[] = {
4126 CreateMockRead(*resp1, 4),
4127 CreateMockRead(*resp2, 5),
4128 MockRead(ASYNC, 0, 0, 6), // EOF
4131 DeterministicSocketData data(reads, arraysize(reads),
4132 writes, arraysize(writes));
4133 MockConnect connect_data(SYNCHRONOUS, OK);
4134 data.set_connect_data(connect_data);
4136 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4138 CreateDeterministicNetworkSession();
4139 base::WeakPtr<SpdySession> session =
4140 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4141 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4142 session->flow_control_state());
4144 base::WeakPtr<SpdyStream> stream1 =
4145 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4146 session, url, LOWEST, BoundNetLog());
4147 ASSERT_TRUE(stream1.get() != NULL);
4149 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4150 stream1->SetDelegate(&delegate1);
4152 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4154 base::WeakPtr<SpdyStream> stream2 =
4155 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4156 session, url, MEDIUM, BoundNetLog());
4157 ASSERT_TRUE(stream2.get() != NULL);
4159 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4160 stream2->SetDelegate(&delegate2);
4162 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4164 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4165 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4167 StallSessionSend(session.get());
4169 scoped_ptr<SpdyHeaderBlock> headers1(
4170 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4171 EXPECT_EQ(ERR_IO_PENDING,
4172 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4173 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4174 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4176 data.RunFor(1);
4177 EXPECT_EQ(1u, stream1->stream_id());
4178 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4180 scoped_ptr<SpdyHeaderBlock> headers2(
4181 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4182 EXPECT_EQ(ERR_IO_PENDING,
4183 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4184 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4185 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4187 data.RunFor(1);
4188 EXPECT_EQ(3u, stream2->stream_id());
4189 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4191 // This should unstall only stream2.
4192 UnstallSessionSend(session.get(), kBodyDataSize);
4194 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4195 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4197 data.RunFor(1);
4199 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4200 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4202 // This should then unstall stream1.
4203 UnstallSessionSend(session.get(), kBodyDataSize);
4205 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4206 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4208 data.RunFor(4);
4210 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4211 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4213 EXPECT_TRUE(delegate1.send_headers_completed());
4214 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4215 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4217 EXPECT_TRUE(delegate2.send_headers_completed());
4218 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4219 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4221 EXPECT_TRUE(data.at_write_eof());
4224 // Delegate that closes a given stream after sending its body.
4225 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4226 public:
4227 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4228 base::StringPiece data)
4229 : StreamDelegateWithBody(stream, data) {}
4231 ~StreamClosingDelegate() override {}
4233 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4234 stream_to_close_ = stream_to_close;
4237 void OnDataSent() override {
4238 test::StreamDelegateWithBody::OnDataSent();
4239 if (stream_to_close_.get()) {
4240 stream_to_close_->Close();
4241 EXPECT_EQ(NULL, stream_to_close_.get());
4245 private:
4246 base::WeakPtr<SpdyStream> stream_to_close_;
4249 // Cause a stall by reducing the flow control send window to
4250 // 0. Unstalling the session should properly handle deleted streams.
4251 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4252 if (GetParam() < kProtoSPDY31)
4253 return;
4255 const char kStreamUrl[] = "http://www.google.com/";
4256 GURL url(kStreamUrl);
4258 session_deps_.host_resolver->set_synchronous_mode(true);
4260 scoped_ptr<SpdyFrame> req1(
4261 spdy_util_.ConstructSpdyPost(
4262 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4263 scoped_ptr<SpdyFrame> req2(
4264 spdy_util_.ConstructSpdyPost(
4265 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4266 scoped_ptr<SpdyFrame> req3(
4267 spdy_util_.ConstructSpdyPost(
4268 kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
4269 scoped_ptr<SpdyFrame> body2(
4270 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4271 MockWrite writes[] = {
4272 CreateMockWrite(*req1, 0),
4273 CreateMockWrite(*req2, 1),
4274 CreateMockWrite(*req3, 2),
4275 CreateMockWrite(*body2, 3),
4278 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4279 MockRead reads[] = {
4280 CreateMockRead(*resp2, 4),
4281 MockRead(ASYNC, 0, 0, 5), // EOF
4284 DeterministicSocketData data(reads, arraysize(reads),
4285 writes, arraysize(writes));
4286 MockConnect connect_data(SYNCHRONOUS, OK);
4287 data.set_connect_data(connect_data);
4289 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4291 CreateDeterministicNetworkSession();
4292 base::WeakPtr<SpdySession> session =
4293 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4294 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4295 session->flow_control_state());
4297 base::WeakPtr<SpdyStream> stream1 =
4298 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4299 session, url, LOWEST, BoundNetLog());
4300 ASSERT_TRUE(stream1.get() != NULL);
4302 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4303 stream1->SetDelegate(&delegate1);
4305 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4307 base::WeakPtr<SpdyStream> stream2 =
4308 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4309 session, url, LOWEST, BoundNetLog());
4310 ASSERT_TRUE(stream2.get() != NULL);
4312 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4313 stream2->SetDelegate(&delegate2);
4315 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4317 base::WeakPtr<SpdyStream> stream3 =
4318 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4319 session, url, LOWEST, BoundNetLog());
4320 ASSERT_TRUE(stream3.get() != NULL);
4322 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4323 stream3->SetDelegate(&delegate3);
4325 EXPECT_FALSE(stream3->HasUrlFromHeaders());
4327 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4328 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4329 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4331 StallSessionSend(session.get());
4333 scoped_ptr<SpdyHeaderBlock> headers1(
4334 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4335 EXPECT_EQ(ERR_IO_PENDING,
4336 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4337 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4338 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4340 data.RunFor(1);
4341 EXPECT_EQ(1u, stream1->stream_id());
4342 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4344 scoped_ptr<SpdyHeaderBlock> headers2(
4345 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4346 EXPECT_EQ(ERR_IO_PENDING,
4347 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4348 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4349 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4351 data.RunFor(1);
4352 EXPECT_EQ(3u, stream2->stream_id());
4353 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4355 scoped_ptr<SpdyHeaderBlock> headers3(
4356 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4357 EXPECT_EQ(ERR_IO_PENDING,
4358 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4359 EXPECT_TRUE(stream3->HasUrlFromHeaders());
4360 EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4362 data.RunFor(1);
4363 EXPECT_EQ(5u, stream3->stream_id());
4364 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4366 SpdyStreamId stream_id1 = stream1->stream_id();
4367 SpdyStreamId stream_id2 = stream2->stream_id();
4368 SpdyStreamId stream_id3 = stream3->stream_id();
4370 // Close stream1 preemptively.
4371 session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4372 EXPECT_EQ(NULL, stream1.get());
4374 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4375 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4376 EXPECT_TRUE(session->IsStreamActive(stream_id3));
4378 // Unstall stream2, which should then close stream3.
4379 delegate2.set_stream_to_close(stream3);
4380 UnstallSessionSend(session.get(), kBodyDataSize);
4382 data.RunFor(1);
4383 EXPECT_EQ(NULL, stream3.get());
4385 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4386 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4387 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4388 EXPECT_FALSE(session->IsStreamActive(stream_id3));
4390 data.RunFor(2);
4391 EXPECT_EQ(NULL, stream2.get());
4393 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4394 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4395 EXPECT_EQ(OK, delegate3.WaitForClose());
4397 EXPECT_TRUE(delegate1.send_headers_completed());
4398 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4400 EXPECT_TRUE(delegate2.send_headers_completed());
4401 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4402 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4404 EXPECT_TRUE(delegate3.send_headers_completed());
4405 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4407 EXPECT_TRUE(data.at_write_eof());
4410 // Cause a stall by reducing the flow control send window to
4411 // 0. Unstalling the session should properly handle the session itself
4412 // being closed.
4413 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4414 if (GetParam() < kProtoSPDY31)
4415 return;
4417 const char kStreamUrl[] = "http://www.google.com/";
4418 GURL url(kStreamUrl);
4420 session_deps_.host_resolver->set_synchronous_mode(true);
4422 scoped_ptr<SpdyFrame> req1(
4423 spdy_util_.ConstructSpdyPost(
4424 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4425 scoped_ptr<SpdyFrame> req2(
4426 spdy_util_.ConstructSpdyPost(
4427 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4428 scoped_ptr<SpdyFrame> body1(
4429 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4430 MockWrite writes[] = {
4431 CreateMockWrite(*req1, 0),
4432 CreateMockWrite(*req2, 1),
4435 MockRead reads[] = {
4436 MockRead(ASYNC, 0, 0, 2), // EOF
4439 DeterministicSocketData data(reads, arraysize(reads),
4440 writes, arraysize(writes));
4441 MockConnect connect_data(SYNCHRONOUS, OK);
4442 data.set_connect_data(connect_data);
4444 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4446 CreateDeterministicNetworkSession();
4447 base::WeakPtr<SpdySession> session =
4448 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4449 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4450 session->flow_control_state());
4452 base::WeakPtr<SpdyStream> stream1 =
4453 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4454 session, url, LOWEST, BoundNetLog());
4455 ASSERT_TRUE(stream1.get() != NULL);
4457 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4458 stream1->SetDelegate(&delegate1);
4460 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4462 base::WeakPtr<SpdyStream> stream2 =
4463 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4464 session, url, LOWEST, BoundNetLog());
4465 ASSERT_TRUE(stream2.get() != NULL);
4467 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4468 stream2->SetDelegate(&delegate2);
4470 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4472 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4473 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4475 StallSessionSend(session.get());
4477 scoped_ptr<SpdyHeaderBlock> headers1(
4478 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4479 EXPECT_EQ(ERR_IO_PENDING,
4480 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4481 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4482 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4484 data.RunFor(1);
4485 EXPECT_EQ(1u, stream1->stream_id());
4486 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4488 scoped_ptr<SpdyHeaderBlock> headers2(
4489 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4490 EXPECT_EQ(ERR_IO_PENDING,
4491 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4492 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4493 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4495 data.RunFor(1);
4496 EXPECT_EQ(3u, stream2->stream_id());
4497 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4499 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4501 // Unstall stream1.
4502 UnstallSessionSend(session.get(), kBodyDataSize);
4504 // Close the session (since we can't do it from within the delegate
4505 // method, since it's in the stream's loop).
4506 session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4507 base::RunLoop().RunUntilIdle();
4508 EXPECT_TRUE(session == NULL);
4510 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4512 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4513 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4515 EXPECT_TRUE(delegate1.send_headers_completed());
4516 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4518 EXPECT_TRUE(delegate2.send_headers_completed());
4519 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4521 EXPECT_TRUE(data.at_write_eof());
4524 TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4525 if (GetParam() < kProtoSPDY31)
4526 return;
4528 MockConnect connect_data(SYNCHRONOUS, OK);
4530 scoped_ptr<SpdyFrame> req(
4531 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4532 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4534 GOAWAY_FLOW_CONTROL_ERROR,
4535 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4536 "the receive window size of 1"));
4537 MockWrite writes[] = {
4538 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
4541 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4542 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4543 MockRead reads[] = {
4544 CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
4547 DeterministicSocketData data(
4548 reads, arraysize(reads), writes, arraysize(writes));
4549 data.set_connect_data(connect_data);
4550 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4552 CreateDeterministicNetworkSession();
4554 base::WeakPtr<SpdySession> session =
4555 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4557 GURL url(kDefaultURL);
4558 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4559 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
4560 ASSERT_TRUE(spdy_stream.get() != NULL);
4561 test::StreamDelegateDoNothing delegate(spdy_stream);
4562 spdy_stream->SetDelegate(&delegate);
4564 scoped_ptr<SpdyHeaderBlock> headers(
4565 spdy_util_.ConstructGetHeaderBlock(url.spec()));
4566 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4568 data.RunFor(1); // Write request.
4570 // Put session on the edge of overflowing it's recv window.
4571 session->session_recv_window_size_ = 1;
4573 // Read response headers & body. Body overflows the session window, and a
4574 // goaway is written.
4575 data.RunFor(3);
4576 base::MessageLoop::current()->RunUntilIdle();
4578 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4579 EXPECT_TRUE(session == NULL);
4582 TEST_P(SpdySessionTest, SplitHeaders) {
4583 GURL kStreamUrl("http://www.google.com/foo.dat");
4584 SpdyHeaderBlock headers;
4585 spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4586 headers["alpha"] = "beta";
4588 SpdyHeaderBlock request_headers;
4589 SpdyHeaderBlock response_headers;
4591 SplitPushedHeadersToRequestAndResponse(
4592 headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4594 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4595 std::string alpha_val =
4596 (it == response_headers.end()) ? std::string() : it->second;
4597 EXPECT_EQ("beta", alpha_val);
4599 GURL request_url =
4600 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4601 EXPECT_EQ(kStreamUrl, request_url);
4604 // Regression. Sorta. Push streams and client streams were sharing a single
4605 // limit for a long time.
4606 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4607 SettingsMap new_settings;
4608 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4609 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4610 scoped_ptr<SpdyFrame> settings_frame(
4611 spdy_util_.ConstructSpdySettings(new_settings));
4612 scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4613 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4614 MockRead reads[] = {
4615 CreateMockRead(*settings_frame), CreateMockRead(*pushed, 3),
4616 MockRead(ASYNC, 0, 4),
4619 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4620 scoped_ptr<SpdyFrame> req(
4621 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4622 MockWrite writes[] = {
4623 CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4626 DeterministicSocketData data(
4627 reads, arraysize(reads), writes, arraysize(writes));
4628 MockConnect connect_data(SYNCHRONOUS, OK);
4629 data.set_connect_data(connect_data);
4630 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4632 CreateDeterministicNetworkSession();
4634 base::WeakPtr<SpdySession> session =
4635 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4637 // Read the settings frame.
4638 data.RunFor(1);
4640 GURL url1(kDefaultURL);
4641 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4642 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4643 ASSERT_TRUE(spdy_stream1.get() != NULL);
4644 EXPECT_EQ(0u, spdy_stream1->stream_id());
4645 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4646 spdy_stream1->SetDelegate(&delegate1);
4648 EXPECT_EQ(0u, session->num_active_streams());
4649 EXPECT_EQ(1u, session->num_created_streams());
4650 EXPECT_EQ(0u, session->num_pushed_streams());
4651 EXPECT_EQ(0u, session->num_active_pushed_streams());
4653 scoped_ptr<SpdyHeaderBlock> headers(
4654 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4655 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4656 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4658 // Run until 1st stream is activated.
4659 EXPECT_EQ(0u, delegate1.stream_id());
4660 data.RunFor(2);
4661 EXPECT_EQ(1u, delegate1.stream_id());
4662 EXPECT_EQ(1u, session->num_active_streams());
4663 EXPECT_EQ(0u, session->num_created_streams());
4664 EXPECT_EQ(0u, session->num_pushed_streams());
4665 EXPECT_EQ(0u, session->num_active_pushed_streams());
4667 // Run until pushed stream is created.
4668 data.RunFor(1);
4669 EXPECT_EQ(2u, session->num_active_streams());
4670 EXPECT_EQ(0u, session->num_created_streams());
4671 EXPECT_EQ(1u, session->num_pushed_streams());
4672 EXPECT_EQ(1u, session->num_active_pushed_streams());
4674 // Second stream should not be stalled, although we have 2 active streams, but
4675 // one of them is push stream and should not be taken into account when we
4676 // create streams on the client.
4677 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4678 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4679 EXPECT_TRUE(spdy_stream2.get() != NULL);
4680 EXPECT_EQ(2u, session->num_active_streams());
4681 EXPECT_EQ(1u, session->num_created_streams());
4682 EXPECT_EQ(1u, session->num_pushed_streams());
4683 EXPECT_EQ(1u, session->num_active_pushed_streams());
4685 // Read EOF.
4686 data.RunFor(1);
4689 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4690 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4691 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4692 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4693 NULL, 0, 4, 1, "http://www.google.com/b.dat"));
4694 MockRead reads[] = {
4695 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4696 MockRead(ASYNC, 0, 4),
4699 scoped_ptr<SpdyFrame> req(
4700 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4701 scoped_ptr<SpdyFrame> rst(
4702 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4703 MockWrite writes[] = {
4704 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4707 DeterministicSocketData data(
4708 reads, arraysize(reads), writes, arraysize(writes));
4709 MockConnect connect_data(SYNCHRONOUS, OK);
4710 data.set_connect_data(connect_data);
4711 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4713 CreateDeterministicNetworkSession();
4715 base::WeakPtr<SpdySession> session =
4716 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4717 session->set_max_concurrent_pushed_streams(1);
4719 GURL url1(kDefaultURL);
4720 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4721 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4722 ASSERT_TRUE(spdy_stream1.get() != NULL);
4723 EXPECT_EQ(0u, spdy_stream1->stream_id());
4724 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4725 spdy_stream1->SetDelegate(&delegate1);
4727 EXPECT_EQ(0u, session->num_active_streams());
4728 EXPECT_EQ(1u, session->num_created_streams());
4729 EXPECT_EQ(0u, session->num_pushed_streams());
4730 EXPECT_EQ(0u, session->num_active_pushed_streams());
4732 scoped_ptr<SpdyHeaderBlock> headers(
4733 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4734 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4735 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4737 // Run until 1st stream is activated.
4738 EXPECT_EQ(0u, delegate1.stream_id());
4739 data.RunFor(1);
4740 EXPECT_EQ(1u, delegate1.stream_id());
4741 EXPECT_EQ(1u, session->num_active_streams());
4742 EXPECT_EQ(0u, session->num_created_streams());
4743 EXPECT_EQ(0u, session->num_pushed_streams());
4744 EXPECT_EQ(0u, session->num_active_pushed_streams());
4746 // Run until pushed stream is created.
4747 data.RunFor(1);
4748 EXPECT_EQ(2u, session->num_active_streams());
4749 EXPECT_EQ(0u, session->num_created_streams());
4750 EXPECT_EQ(1u, session->num_pushed_streams());
4751 EXPECT_EQ(1u, session->num_active_pushed_streams());
4753 // Reset incoming pushed stream.
4754 data.RunFor(2);
4755 EXPECT_EQ(2u, session->num_active_streams());
4756 EXPECT_EQ(0u, session->num_created_streams());
4757 EXPECT_EQ(1u, session->num_pushed_streams());
4758 EXPECT_EQ(1u, session->num_active_pushed_streams());
4760 // Read EOF.
4761 data.RunFor(1);
4764 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4765 // Streams in reserved remote state exist only in SPDY4.
4766 if (spdy_util_.spdy_version() < SPDY4)
4767 return;
4769 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4770 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4771 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4772 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
4773 push_headers.get());
4774 scoped_ptr<SpdyFrame> push_b(
4775 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4776 scoped_ptr<SpdyFrame> headers_b(
4777 spdy_util_.ConstructSpdyPushHeaders(4, NULL, 0));
4778 MockRead reads[] = {
4779 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4780 CreateMockRead(*headers_b, 3), MockRead(ASYNC, 0, 5),
4783 scoped_ptr<SpdyFrame> req(
4784 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4785 scoped_ptr<SpdyFrame> rst(
4786 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4787 MockWrite writes[] = {
4788 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
4791 DeterministicSocketData data(
4792 reads, arraysize(reads), writes, arraysize(writes));
4793 MockConnect connect_data(SYNCHRONOUS, OK);
4794 data.set_connect_data(connect_data);
4795 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4797 CreateDeterministicNetworkSession();
4799 base::WeakPtr<SpdySession> session =
4800 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4801 session->set_max_concurrent_pushed_streams(1);
4803 GURL url1(kDefaultURL);
4804 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4805 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4806 ASSERT_TRUE(spdy_stream1.get() != NULL);
4807 EXPECT_EQ(0u, spdy_stream1->stream_id());
4808 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4809 spdy_stream1->SetDelegate(&delegate1);
4811 EXPECT_EQ(0u, session->num_active_streams());
4812 EXPECT_EQ(1u, session->num_created_streams());
4813 EXPECT_EQ(0u, session->num_pushed_streams());
4814 EXPECT_EQ(0u, session->num_active_pushed_streams());
4816 scoped_ptr<SpdyHeaderBlock> headers(
4817 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4818 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4819 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4821 // Run until 1st stream is activated.
4822 EXPECT_EQ(0u, delegate1.stream_id());
4823 data.RunFor(1);
4824 EXPECT_EQ(1u, delegate1.stream_id());
4825 EXPECT_EQ(1u, session->num_active_streams());
4826 EXPECT_EQ(0u, session->num_created_streams());
4827 EXPECT_EQ(0u, session->num_pushed_streams());
4828 EXPECT_EQ(0u, session->num_active_pushed_streams());
4830 // Run until pushed stream is created.
4831 data.RunFor(1);
4832 EXPECT_EQ(2u, session->num_active_streams());
4833 EXPECT_EQ(0u, session->num_created_streams());
4834 EXPECT_EQ(1u, session->num_pushed_streams());
4835 EXPECT_EQ(1u, session->num_active_pushed_streams());
4837 // Accept promised stream. It should not count towards pushed stream limit.
4838 data.RunFor(1);
4839 EXPECT_EQ(3u, session->num_active_streams());
4840 EXPECT_EQ(0u, session->num_created_streams());
4841 EXPECT_EQ(2u, session->num_pushed_streams());
4842 EXPECT_EQ(1u, session->num_active_pushed_streams());
4844 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4845 // while we accept only one.
4846 data.RunFor(2);
4847 EXPECT_EQ(2u, session->num_active_streams());
4848 EXPECT_EQ(0u, session->num_created_streams());
4849 EXPECT_EQ(1u, session->num_pushed_streams());
4850 EXPECT_EQ(1u, session->num_active_pushed_streams());
4852 // Read EOF.
4853 data.RunFor(1);
4856 TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
4857 // Streams in reserved remote state exist only in SPDY4.
4858 if (spdy_util_.spdy_version() < SPDY4)
4859 return;
4861 const char kPushedUrl[] = "http://www.google.com/a.dat";
4862 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4863 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
4864 scoped_ptr<SpdyFrame> push_promise(
4865 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
4866 scoped_ptr<SpdyFrame> headers_frame(
4867 spdy_util_.ConstructSpdyPushHeaders(2, NULL, 0));
4868 MockRead reads[] = {
4869 CreateMockRead(*push_promise, 1), CreateMockRead(*headers_frame, 2),
4870 MockRead(ASYNC, 0, 4),
4873 scoped_ptr<SpdyFrame> req(
4874 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4875 scoped_ptr<SpdyFrame> rst(
4876 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
4877 MockWrite writes[] = {
4878 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4881 DeterministicSocketData data(
4882 reads, arraysize(reads), writes, arraysize(writes));
4883 MockConnect connect_data(SYNCHRONOUS, OK);
4884 data.set_connect_data(connect_data);
4885 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4887 CreateDeterministicNetworkSession();
4889 base::WeakPtr<SpdySession> session =
4890 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4892 GURL url1(kDefaultURL);
4893 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4894 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4895 ASSERT_TRUE(spdy_stream1.get() != NULL);
4896 EXPECT_EQ(0u, spdy_stream1->stream_id());
4897 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4898 spdy_stream1->SetDelegate(&delegate1);
4900 EXPECT_EQ(0u, session->num_active_streams());
4901 EXPECT_EQ(1u, session->num_created_streams());
4902 EXPECT_EQ(0u, session->num_pushed_streams());
4903 EXPECT_EQ(0u, session->num_active_pushed_streams());
4905 scoped_ptr<SpdyHeaderBlock> headers(
4906 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4907 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4908 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4910 // Run until 1st stream is activated.
4911 EXPECT_EQ(0u, delegate1.stream_id());
4912 data.RunFor(1);
4913 EXPECT_EQ(1u, delegate1.stream_id());
4914 EXPECT_EQ(1u, session->num_active_streams());
4915 EXPECT_EQ(0u, session->num_created_streams());
4916 EXPECT_EQ(0u, session->num_pushed_streams());
4917 EXPECT_EQ(0u, session->num_active_pushed_streams());
4919 // Run until pushed stream is created.
4920 data.RunFor(1);
4921 EXPECT_EQ(2u, session->num_active_streams());
4922 EXPECT_EQ(0u, session->num_created_streams());
4923 EXPECT_EQ(1u, session->num_pushed_streams());
4924 EXPECT_EQ(0u, session->num_active_pushed_streams());
4926 base::WeakPtr<SpdyStream> pushed_stream;
4927 int rv =
4928 session->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
4929 ASSERT_EQ(OK, rv);
4930 ASSERT_TRUE(pushed_stream.get() != NULL);
4931 test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
4932 pushed_stream->SetDelegate(&delegate2);
4934 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4935 // that all our counters are in consistent state.
4936 data.RunFor(1);
4937 EXPECT_EQ(1u, session->num_active_streams());
4938 EXPECT_EQ(0u, session->num_created_streams());
4939 EXPECT_EQ(0u, session->num_pushed_streams());
4940 EXPECT_EQ(0u, session->num_active_pushed_streams());
4942 // Read EOF.
4943 data.RunFor(2);
4946 TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
4947 session_deps_.host_resolver->set_synchronous_mode(true);
4949 MockRead reads[] = {
4950 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
4953 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
4955 MockConnect connect_data(SYNCHRONOUS, OK);
4956 data.set_connect_data(connect_data);
4957 session_deps_.socket_factory->AddSocketDataProvider(&data);
4959 CreateNetworkSession();
4960 base::WeakPtr<SpdySession> session =
4961 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4963 session->stream_hi_water_mark_ = 5;
4964 // Low client (odd) ids are fine.
4965 EXPECT_TRUE(session->OnUnknownFrame(3, 0));
4966 // Client id exceeding watermark.
4967 EXPECT_FALSE(session->OnUnknownFrame(9, 0));
4969 session->last_accepted_push_stream_id_ = 6;
4970 // Low server (even) ids are fine.
4971 EXPECT_TRUE(session->OnUnknownFrame(2, 0));
4972 // Server id exceeding last accepted id.
4973 EXPECT_FALSE(session->OnUnknownFrame(8, 0));
4976 TEST(MapFramerErrorToProtocolError, MapsValues) {
4977 CHECK_EQ(
4978 SPDY_ERROR_INVALID_CONTROL_FRAME,
4979 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4980 CHECK_EQ(
4981 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4982 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4983 CHECK_EQ(
4984 SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
4985 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
4986 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
4987 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
4990 TEST(MapFramerErrorToNetError, MapsValue) {
4991 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
4992 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4993 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4994 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
4995 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4996 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4997 CHECK_EQ(
4998 ERR_SPDY_FRAME_SIZE_ERROR,
4999 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
5002 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
5003 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
5004 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
5005 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
5006 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
5007 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
5008 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
5009 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY,
5010 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY));
5011 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED,
5012 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED));
5015 TEST(MapNetErrorToGoAwayStatus, MapsValue) {
5016 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
5017 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
5018 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
5019 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
5020 CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
5021 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
5022 CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
5023 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
5024 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
5025 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
5026 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
5029 TEST(CanPoolTest, CanPool) {
5030 // Load a cert that is valid for:
5031 // www.example.org
5032 // mail.example.org
5033 // www.example.com
5035 TransportSecurityState tss;
5036 SSLInfo ssl_info;
5037 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5038 "spdy_pooling.pem");
5040 EXPECT_TRUE(SpdySession::CanPool(
5041 &tss, ssl_info, "www.example.org", "www.example.org"));
5042 EXPECT_TRUE(SpdySession::CanPool(
5043 &tss, ssl_info, "www.example.org", "mail.example.org"));
5044 EXPECT_TRUE(SpdySession::CanPool(
5045 &tss, ssl_info, "www.example.org", "mail.example.com"));
5046 EXPECT_FALSE(SpdySession::CanPool(
5047 &tss, ssl_info, "www.example.org", "mail.google.com"));
5050 TEST(CanPoolTest, CanNotPoolWithCertErrors) {
5051 // Load a cert that is valid for:
5052 // www.example.org
5053 // mail.example.org
5054 // www.example.com
5056 TransportSecurityState tss;
5057 SSLInfo ssl_info;
5058 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5059 "spdy_pooling.pem");
5060 ssl_info.cert_status = CERT_STATUS_REVOKED;
5062 EXPECT_FALSE(SpdySession::CanPool(
5063 &tss, ssl_info, "www.example.org", "mail.example.org"));
5066 TEST(CanPoolTest, CanNotPoolWithClientCerts) {
5067 // Load a cert that is valid for:
5068 // www.example.org
5069 // mail.example.org
5070 // www.example.com
5072 TransportSecurityState tss;
5073 SSLInfo ssl_info;
5074 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5075 "spdy_pooling.pem");
5076 ssl_info.client_cert_sent = true;
5078 EXPECT_FALSE(SpdySession::CanPool(
5079 &tss, ssl_info, "www.example.org", "mail.example.org"));
5082 TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
5083 // Load a cert that is valid for:
5084 // www.example.org
5085 // mail.example.org
5086 // www.example.com
5088 TransportSecurityState tss;
5089 SSLInfo ssl_info;
5090 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5091 "spdy_pooling.pem");
5092 ssl_info.channel_id_sent = true;
5094 EXPECT_TRUE(SpdySession::CanPool(
5095 &tss, ssl_info, "www.example.org", "mail.example.org"));
5096 EXPECT_FALSE(SpdySession::CanPool(
5097 &tss, ssl_info, "www.example.org", "www.example.com"));
5100 TEST(CanPoolTest, CanNotPoolWithBadPins) {
5101 uint8 primary_pin = 1;
5102 uint8 backup_pin = 2;
5103 uint8 bad_pin = 3;
5104 TransportSecurityState tss;
5105 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5107 SSLInfo ssl_info;
5108 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5109 "spdy_pooling.pem");
5110 ssl_info.is_issued_by_known_root = true;
5111 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
5113 EXPECT_FALSE(SpdySession::CanPool(
5114 &tss, ssl_info, "www.example.org", "mail.example.org"));
5117 TEST(CanPoolTest, CanPoolWithAcceptablePins) {
5118 uint8 primary_pin = 1;
5119 uint8 backup_pin = 2;
5120 TransportSecurityState tss;
5121 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5123 SSLInfo ssl_info;
5124 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5125 "spdy_pooling.pem");
5126 ssl_info.is_issued_by_known_root = true;
5127 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
5129 EXPECT_TRUE(SpdySession::CanPool(
5130 &tss, ssl_info, "www.example.org", "mail.example.org"));
5133 } // namespace net