Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / net / spdy / spdy_session_unittest.cc
blob8e943cae0dffbfdfeed4e1c649f51fd9b5299cdc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/spdy/spdy_session.h"
7 #include "base/base64.h"
8 #include "base/bind.h"
9 #include "base/callback.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/test/histogram_tester.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/ip_endpoint.h"
15 #include "net/base/request_priority.h"
16 #include "net/base/test_data_directory.h"
17 #include "net/base/test_data_stream.h"
18 #include "net/log/net_log_unittest.h"
19 #include "net/socket/client_socket_pool_manager.h"
20 #include "net/socket/next_proto.h"
21 #include "net/socket/socket_test_util.h"
22 #include "net/spdy/spdy_http_utils.h"
23 #include "net/spdy/spdy_session_pool.h"
24 #include "net/spdy/spdy_session_test_util.h"
25 #include "net/spdy/spdy_stream.h"
26 #include "net/spdy/spdy_stream_test_util.h"
27 #include "net/spdy/spdy_test_util_common.h"
28 #include "net/spdy/spdy_test_utils.h"
29 #include "net/test/cert_test_util.h"
30 #include "testing/platform_test.h"
32 namespace net {
34 namespace {
36 static const char kTestUrl[] = "http://www.example.org/";
37 static const char kTestHost[] = "www.example.org";
38 static const int kTestPort = 80;
40 const char kBodyData[] = "Body data";
41 const size_t kBodyDataSize = arraysize(kBodyData);
42 const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize);
44 static base::TimeDelta g_time_delta;
45 base::TimeTicks TheNearFuture() {
46 return base::TimeTicks::Now() + g_time_delta;
49 } // namespace
51 class SpdySessionTest : public PlatformTest,
52 public ::testing::WithParamInterface<NextProto> {
53 public:
54 // Functions used with RunResumeAfterUnstallTest().
56 void StallSessionOnly(SpdySession* session, SpdyStream* stream) {
57 StallSessionSend(session);
60 void StallStreamOnly(SpdySession* session, SpdyStream* stream) {
61 StallStreamSend(stream);
64 void StallSessionStream(SpdySession* session, SpdyStream* stream) {
65 StallSessionSend(session);
66 StallStreamSend(stream);
69 void StallStreamSession(SpdySession* session, SpdyStream* stream) {
70 StallStreamSend(stream);
71 StallSessionSend(session);
74 void UnstallSessionOnly(SpdySession* session,
75 SpdyStream* stream,
76 int32 delta_window_size) {
77 UnstallSessionSend(session, delta_window_size);
80 void UnstallStreamOnly(SpdySession* session,
81 SpdyStream* stream,
82 int32 delta_window_size) {
83 UnstallStreamSend(stream, delta_window_size);
86 void UnstallSessionStream(SpdySession* session,
87 SpdyStream* stream,
88 int32 delta_window_size) {
89 UnstallSessionSend(session, delta_window_size);
90 UnstallStreamSend(stream, delta_window_size);
93 void UnstallStreamSession(SpdySession* session,
94 SpdyStream* stream,
95 int32 delta_window_size) {
96 UnstallStreamSend(stream, delta_window_size);
97 UnstallSessionSend(session, delta_window_size);
100 protected:
101 SpdySessionTest()
102 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
103 HttpNetworkSession::NORMAL_SOCKET_POOL)),
104 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
105 HttpNetworkSession::NORMAL_SOCKET_POOL)),
106 spdy_util_(GetParam()),
107 session_deps_(GetParam()),
108 spdy_session_pool_(NULL),
109 test_url_(kTestUrl),
110 test_host_port_pair_(kTestHost, kTestPort),
111 key_(test_host_port_pair_, ProxyServer::Direct(),
112 PRIVACY_MODE_DISABLED) {
115 virtual ~SpdySessionTest() {
116 // Important to restore the per-pool limit first, since the pool limit must
117 // always be greater than group limit, and the tests reduce both limits.
118 ClientSocketPoolManager::set_max_sockets_per_pool(
119 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
120 ClientSocketPoolManager::set_max_sockets_per_group(
121 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
124 void SetUp() override { g_time_delta = base::TimeDelta(); }
126 void CreateDeterministicNetworkSession() {
127 http_session_ =
128 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
129 spdy_session_pool_ = http_session_->spdy_session_pool();
132 void CreateNetworkSession() {
133 http_session_ =
134 SpdySessionDependencies::SpdyCreateSession(&session_deps_);
135 spdy_session_pool_ = http_session_->spdy_session_pool();
138 void StallSessionSend(SpdySession* session) {
139 // Reduce the send window size to 0 to stall.
140 while (session->session_send_window_size_ > 0) {
141 session->DecreaseSendWindowSize(
142 std::min(kMaxSpdyFrameChunkSize, session->session_send_window_size_));
146 void UnstallSessionSend(SpdySession* session, int32 delta_window_size) {
147 session->IncreaseSendWindowSize(delta_window_size);
150 void StallStreamSend(SpdyStream* stream) {
151 // Reduce the send window size to 0 to stall.
152 while (stream->send_window_size() > 0) {
153 stream->DecreaseSendWindowSize(
154 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
158 void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) {
159 stream->IncreaseSendWindowSize(delta_window_size);
162 void RunResumeAfterUnstallTest(
163 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
164 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
165 unstall_function);
167 // Original socket limits. Some tests set these. Safest to always restore
168 // them once each test has been run.
169 int old_max_group_sockets_;
170 int old_max_pool_sockets_;
172 SpdyTestUtil spdy_util_;
173 SpdySessionDependencies session_deps_;
174 scoped_refptr<HttpNetworkSession> http_session_;
175 SpdySessionPool* spdy_session_pool_;
176 GURL test_url_;
177 HostPortPair test_host_port_pair_;
178 SpdySessionKey key_;
181 INSTANTIATE_TEST_CASE_P(NextProto,
182 SpdySessionTest,
183 testing::Values(kProtoSPDY31,
184 kProtoSPDY4_14,
185 kProtoSPDY4));
187 // Try to create a SPDY session that will fail during
188 // initialization. Nothing should blow up.
189 TEST_P(SpdySessionTest, InitialReadError) {
190 CreateDeterministicNetworkSession();
192 base::WeakPtr<SpdySession> session = TryCreateFakeSpdySessionExpectingFailure(
193 spdy_session_pool_, key_, ERR_CONNECTION_CLOSED);
194 EXPECT_TRUE(session);
195 // Flush the read.
196 base::RunLoop().RunUntilIdle();
197 EXPECT_FALSE(session);
200 namespace {
202 // A helper class that vends a callback that, when fired, destroys a
203 // given SpdyStreamRequest.
204 class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
205 public:
206 StreamRequestDestroyingCallback() {}
208 ~StreamRequestDestroyingCallback() override {}
210 void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) {
211 request_ = request.Pass();
214 CompletionCallback MakeCallback() {
215 return base::Bind(&StreamRequestDestroyingCallback::OnComplete,
216 base::Unretained(this));
219 private:
220 void OnComplete(int result) {
221 request_.reset();
222 SetResult(result);
225 scoped_ptr<SpdyStreamRequest> request_;
228 } // namespace
230 // Request kInitialMaxConcurrentStreams streams. Request two more
231 // streams, but have the callback for one destroy the second stream
232 // request. Close the session. Nothing should blow up. This is a
233 // regression test for http://crbug.com/250841 .
234 TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
235 session_deps_.host_resolver->set_synchronous_mode(true);
237 MockRead reads[] = {MockRead(ASYNC, 0, 0), };
239 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
240 MockConnect connect_data(SYNCHRONOUS, OK);
241 data.set_connect_data(connect_data);
242 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
244 CreateDeterministicNetworkSession();
246 base::WeakPtr<SpdySession> session =
247 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
249 // Create the maximum number of concurrent streams.
250 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
251 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
252 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog());
253 ASSERT_TRUE(spdy_stream != NULL);
256 SpdyStreamRequest request1;
257 scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest);
259 StreamRequestDestroyingCallback callback1;
260 ASSERT_EQ(ERR_IO_PENDING,
261 request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM,
262 session,
263 test_url_,
264 MEDIUM,
265 BoundNetLog(),
266 callback1.MakeCallback()));
268 // |callback2| is never called.
269 TestCompletionCallback callback2;
270 ASSERT_EQ(ERR_IO_PENDING,
271 request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM,
272 session,
273 test_url_,
274 MEDIUM,
275 BoundNetLog(),
276 callback2.callback()));
278 callback1.SetRequestToDestroy(request2.Pass());
280 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
282 EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
285 // A session receiving a GOAWAY frame with no active streams should close.
286 TEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
287 session_deps_.host_resolver->set_synchronous_mode(true);
289 MockConnect connect_data(SYNCHRONOUS, OK);
290 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
291 MockRead reads[] = {
292 CreateMockRead(*goaway, 0),
294 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
295 data.set_connect_data(connect_data);
296 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
298 CreateDeterministicNetworkSession();
300 base::WeakPtr<SpdySession> session =
301 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
303 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
305 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
307 // Read and process the GOAWAY frame.
308 data.RunFor(1);
309 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
310 base::RunLoop().RunUntilIdle();
311 EXPECT_TRUE(session == NULL);
314 // A session receiving a GOAWAY frame immediately with no active
315 // streams should then close.
316 TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
317 session_deps_.host_resolver->set_synchronous_mode(true);
319 MockConnect connect_data(SYNCHRONOUS, OK);
320 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
321 MockRead reads[] = {
322 CreateMockRead(*goaway, 0, SYNCHRONOUS),
324 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
325 data.set_connect_data(connect_data);
326 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
328 CreateDeterministicNetworkSession();
330 data.StopAfter(1);
332 base::WeakPtr<SpdySession> session =
333 TryCreateInsecureSpdySessionExpectingFailure(
334 http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
335 base::RunLoop().RunUntilIdle();
337 EXPECT_FALSE(session);
338 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
341 // A session receiving a GOAWAY frame with active streams should close
342 // when the last active stream is closed.
343 TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
344 session_deps_.host_resolver->set_synchronous_mode(true);
346 MockConnect connect_data(SYNCHRONOUS, OK);
347 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
348 MockRead reads[] = {
349 CreateMockRead(*goaway, 2),
350 MockRead(ASYNC, 0, 3) // EOF
352 scoped_ptr<SpdyFrame> req1(
353 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
354 scoped_ptr<SpdyFrame> req2(
355 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
356 MockWrite writes[] = {
357 CreateMockWrite(*req1, 0),
358 CreateMockWrite(*req2, 1),
360 DeterministicSocketData data(reads, arraysize(reads),
361 writes, arraysize(writes));
362 data.set_connect_data(connect_data);
363 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
365 CreateDeterministicNetworkSession();
367 base::WeakPtr<SpdySession> session =
368 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
370 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
372 GURL url(kDefaultURL);
373 base::WeakPtr<SpdyStream> spdy_stream1 =
374 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
375 session, url, MEDIUM, BoundNetLog());
376 test::StreamDelegateDoNothing delegate1(spdy_stream1);
377 spdy_stream1->SetDelegate(&delegate1);
379 base::WeakPtr<SpdyStream> spdy_stream2 =
380 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
381 session, url, MEDIUM, BoundNetLog());
382 test::StreamDelegateDoNothing delegate2(spdy_stream2);
383 spdy_stream2->SetDelegate(&delegate2);
385 scoped_ptr<SpdyHeaderBlock> headers(
386 spdy_util_.ConstructGetHeaderBlock(url.spec()));
387 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
389 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
390 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
391 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
392 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
394 data.RunFor(2);
396 EXPECT_EQ(1u, spdy_stream1->stream_id());
397 EXPECT_EQ(3u, spdy_stream2->stream_id());
399 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
401 // Read and process the GOAWAY frame.
402 data.RunFor(1);
404 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
406 EXPECT_FALSE(session->IsStreamActive(3));
407 EXPECT_EQ(NULL, spdy_stream2.get());
408 EXPECT_TRUE(session->IsStreamActive(1));
410 EXPECT_TRUE(session->IsGoingAway());
412 // Should close the session.
413 spdy_stream1->Close();
414 EXPECT_EQ(NULL, spdy_stream1.get());
416 base::MessageLoop::current()->RunUntilIdle();
417 EXPECT_TRUE(session == NULL);
420 // Have a session receive two GOAWAY frames, with the last one causing
421 // the last active stream to be closed. The session should then be
422 // closed after the second GOAWAY frame.
423 TEST_P(SpdySessionTest, GoAwayTwice) {
424 session_deps_.host_resolver->set_synchronous_mode(true);
426 MockConnect connect_data(SYNCHRONOUS, OK);
427 scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
428 scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
429 MockRead reads[] = {
430 CreateMockRead(*goaway1, 2),
431 CreateMockRead(*goaway2, 3),
432 MockRead(ASYNC, 0, 4) // EOF
434 scoped_ptr<SpdyFrame> req1(
435 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
436 scoped_ptr<SpdyFrame> req2(
437 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
438 MockWrite writes[] = {
439 CreateMockWrite(*req1, 0),
440 CreateMockWrite(*req2, 1),
442 DeterministicSocketData data(reads, arraysize(reads),
443 writes, arraysize(writes));
444 data.set_connect_data(connect_data);
445 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
447 CreateDeterministicNetworkSession();
449 base::WeakPtr<SpdySession> session =
450 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
452 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
454 GURL url(kDefaultURL);
455 base::WeakPtr<SpdyStream> spdy_stream1 =
456 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
457 session, url, MEDIUM, BoundNetLog());
458 test::StreamDelegateDoNothing delegate1(spdy_stream1);
459 spdy_stream1->SetDelegate(&delegate1);
461 base::WeakPtr<SpdyStream> spdy_stream2 =
462 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
463 session, url, MEDIUM, BoundNetLog());
464 test::StreamDelegateDoNothing delegate2(spdy_stream2);
465 spdy_stream2->SetDelegate(&delegate2);
467 scoped_ptr<SpdyHeaderBlock> headers(
468 spdy_util_.ConstructGetHeaderBlock(url.spec()));
469 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
471 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
472 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
473 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
474 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
476 data.RunFor(2);
478 EXPECT_EQ(1u, spdy_stream1->stream_id());
479 EXPECT_EQ(3u, spdy_stream2->stream_id());
481 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
483 // Read and process the first GOAWAY frame.
484 data.RunFor(1);
486 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
488 EXPECT_FALSE(session->IsStreamActive(3));
489 EXPECT_EQ(NULL, spdy_stream2.get());
490 EXPECT_TRUE(session->IsStreamActive(1));
491 EXPECT_TRUE(session->IsGoingAway());
493 // Read and process the second GOAWAY frame, which should close the
494 // session.
495 data.RunFor(1);
496 base::MessageLoop::current()->RunUntilIdle();
497 EXPECT_TRUE(session == NULL);
500 // Have a session with active streams receive a GOAWAY frame and then
501 // close it. It should handle the close properly (i.e., not try to
502 // make itself unavailable in its pool twice).
503 TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
504 session_deps_.host_resolver->set_synchronous_mode(true);
506 MockConnect connect_data(SYNCHRONOUS, OK);
507 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
508 MockRead reads[] = {
509 CreateMockRead(*goaway, 2),
510 MockRead(ASYNC, 0, 3) // EOF
512 scoped_ptr<SpdyFrame> req1(
513 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
514 scoped_ptr<SpdyFrame> req2(
515 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
516 MockWrite writes[] = {
517 CreateMockWrite(*req1, 0),
518 CreateMockWrite(*req2, 1),
520 DeterministicSocketData data(reads, arraysize(reads),
521 writes, arraysize(writes));
522 data.set_connect_data(connect_data);
523 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
525 CreateDeterministicNetworkSession();
527 base::WeakPtr<SpdySession> session =
528 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
530 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
532 GURL url(kDefaultURL);
533 base::WeakPtr<SpdyStream> spdy_stream1 =
534 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
535 session, url, MEDIUM, BoundNetLog());
536 test::StreamDelegateDoNothing delegate1(spdy_stream1);
537 spdy_stream1->SetDelegate(&delegate1);
539 base::WeakPtr<SpdyStream> spdy_stream2 =
540 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
541 session, url, MEDIUM, BoundNetLog());
542 test::StreamDelegateDoNothing delegate2(spdy_stream2);
543 spdy_stream2->SetDelegate(&delegate2);
545 scoped_ptr<SpdyHeaderBlock> headers(
546 spdy_util_.ConstructGetHeaderBlock(url.spec()));
547 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
549 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
550 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
551 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
552 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
554 data.RunFor(2);
556 EXPECT_EQ(1u, spdy_stream1->stream_id());
557 EXPECT_EQ(3u, spdy_stream2->stream_id());
559 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
561 // Read and process the GOAWAY frame.
562 data.RunFor(1);
564 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
566 EXPECT_FALSE(session->IsStreamActive(3));
567 EXPECT_EQ(NULL, spdy_stream2.get());
568 EXPECT_TRUE(session->IsStreamActive(1));
569 EXPECT_TRUE(session->IsGoingAway());
571 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
572 EXPECT_EQ(NULL, spdy_stream1.get());
574 base::MessageLoop::current()->RunUntilIdle();
575 EXPECT_TRUE(session == NULL);
578 // Process a joint read buffer which causes the session to begin draining, and
579 // then processes a GOAWAY. The session should gracefully drain. Regression test
580 // for crbug.com/379469
581 TEST_P(SpdySessionTest, GoAwayWhileDraining) {
582 session_deps_.host_resolver->set_synchronous_mode(true);
584 scoped_ptr<SpdyFrame> req(
585 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
586 MockWrite writes[] = {
587 CreateMockWrite(*req, 0),
590 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
591 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
592 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
593 size_t joint_size = goaway->size() * 2 + body->size();
595 // Compose interleaved |goaway| and |body| frames into a single read.
596 scoped_ptr<char[]> buffer(new char[joint_size]);
598 size_t out = 0;
599 memcpy(&buffer[out], goaway->data(), goaway->size());
600 out += goaway->size();
601 memcpy(&buffer[out], body->data(), body->size());
602 out += body->size();
603 memcpy(&buffer[out], goaway->data(), goaway->size());
604 out += goaway->size();
605 ASSERT_EQ(out, joint_size);
607 SpdyFrame joint_frames(buffer.get(), joint_size, false);
609 MockRead reads[] = {
610 CreateMockRead(*resp, 1), CreateMockRead(joint_frames, 2),
611 MockRead(ASYNC, 0, 3) // EOF
614 MockConnect connect_data(SYNCHRONOUS, OK);
615 DeterministicSocketData data(
616 reads, arraysize(reads), writes, arraysize(writes));
617 data.set_connect_data(connect_data);
618 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
620 CreateDeterministicNetworkSession();
621 base::WeakPtr<SpdySession> session =
622 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
624 GURL url(kDefaultURL);
625 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
626 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
627 test::StreamDelegateDoNothing delegate(spdy_stream);
628 spdy_stream->SetDelegate(&delegate);
630 scoped_ptr<SpdyHeaderBlock> headers(
631 spdy_util_.ConstructGetHeaderBlock(url.spec()));
632 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
633 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
635 data.RunFor(3);
636 base::MessageLoop::current()->RunUntilIdle();
638 // Stream and session closed gracefully.
639 EXPECT_TRUE(delegate.StreamIsClosed());
640 EXPECT_EQ(OK, delegate.WaitForClose());
641 EXPECT_EQ(kUploadData, delegate.TakeReceivedData());
642 EXPECT_TRUE(session == NULL);
645 // Try to create a stream after receiving a GOAWAY frame. It should
646 // fail.
647 TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
648 session_deps_.host_resolver->set_synchronous_mode(true);
650 MockConnect connect_data(SYNCHRONOUS, OK);
651 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
652 MockRead reads[] = {
653 CreateMockRead(*goaway, 1),
654 MockRead(ASYNC, 0, 2) // EOF
656 scoped_ptr<SpdyFrame> req(
657 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
658 MockWrite writes[] = {
659 CreateMockWrite(*req, 0),
661 DeterministicSocketData data(reads, arraysize(reads),
662 writes, arraysize(writes));
663 data.set_connect_data(connect_data);
664 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
666 CreateDeterministicNetworkSession();
668 base::WeakPtr<SpdySession> session =
669 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
671 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
673 GURL url(kDefaultURL);
674 base::WeakPtr<SpdyStream> spdy_stream =
675 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
676 session, url, MEDIUM, BoundNetLog());
677 test::StreamDelegateDoNothing delegate(spdy_stream);
678 spdy_stream->SetDelegate(&delegate);
680 scoped_ptr<SpdyHeaderBlock> headers(
681 spdy_util_.ConstructGetHeaderBlock(url.spec()));
682 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
683 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
685 data.RunFor(1);
687 EXPECT_EQ(1u, spdy_stream->stream_id());
689 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
691 // Read and process the GOAWAY frame.
692 data.RunFor(1);
694 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
695 EXPECT_TRUE(session->IsStreamActive(1));
697 SpdyStreamRequest stream_request;
698 int rv = stream_request.StartRequest(
699 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog(),
700 CompletionCallback());
701 EXPECT_EQ(ERR_FAILED, rv);
703 // Read and process EOF.
704 data.RunFor(1);
706 EXPECT_TRUE(session == NULL);
709 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
710 // the stream being refused.
711 TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
712 session_deps_.host_resolver->set_synchronous_mode(true);
714 MockConnect connect_data(SYNCHRONOUS, OK);
715 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
716 scoped_ptr<SpdyFrame>
717 push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kDefaultURL));
718 MockRead reads[] = {
719 CreateMockRead(*goaway, 1),
720 CreateMockRead(*push, 2),
721 MockRead(ASYNC, 0, 4) // EOF
723 scoped_ptr<SpdyFrame> req(
724 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
725 scoped_ptr<SpdyFrame> rst(
726 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
727 MockWrite writes[] = {
728 CreateMockWrite(*req, 0),
729 CreateMockWrite(*rst, 3)
731 DeterministicSocketData data(reads, arraysize(reads),
732 writes, arraysize(writes));
733 data.set_connect_data(connect_data);
734 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
736 CreateDeterministicNetworkSession();
738 base::WeakPtr<SpdySession> session =
739 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
741 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
743 GURL url(kDefaultURL);
744 base::WeakPtr<SpdyStream> spdy_stream =
745 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
746 session, url, MEDIUM, BoundNetLog());
747 test::StreamDelegateDoNothing delegate(spdy_stream);
748 spdy_stream->SetDelegate(&delegate);
750 scoped_ptr<SpdyHeaderBlock> headers(
751 spdy_util_.ConstructGetHeaderBlock(url.spec()));
752 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
753 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
755 data.RunFor(1);
757 EXPECT_EQ(1u, spdy_stream->stream_id());
759 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
761 // Read and process the GOAWAY frame.
762 data.RunFor(1);
764 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
765 EXPECT_TRUE(session->IsStreamActive(1));
767 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
768 // and EOF.
769 data.RunFor(3);
770 base::MessageLoop::current()->RunUntilIdle();
771 EXPECT_TRUE(session == NULL);
774 // A session observing a network change with active streams should close
775 // when the last active stream is closed.
776 TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
777 session_deps_.host_resolver->set_synchronous_mode(true);
779 MockConnect connect_data(SYNCHRONOUS, OK);
780 MockRead reads[] = {
781 MockRead(ASYNC, 0, 1) // EOF
783 scoped_ptr<SpdyFrame> req1(
784 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
785 MockWrite writes[] = {
786 CreateMockWrite(*req1, 0),
788 DeterministicSocketData data(reads, arraysize(reads),
789 writes, arraysize(writes));
790 data.set_connect_data(connect_data);
791 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
793 CreateDeterministicNetworkSession();
795 base::WeakPtr<SpdySession> session =
796 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
798 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
800 base::WeakPtr<SpdyStream> spdy_stream =
801 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session,
802 GURL(kDefaultURL), MEDIUM, BoundNetLog());
803 test::StreamDelegateDoNothing delegate(spdy_stream);
804 spdy_stream->SetDelegate(&delegate);
806 scoped_ptr<SpdyHeaderBlock> headers(
807 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
809 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
810 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
812 data.RunFor(1);
814 EXPECT_EQ(1u, spdy_stream->stream_id());
816 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
818 spdy_session_pool_->OnIPAddressChanged();
820 // The SpdySessionPool behavior differs based on how the OSs reacts to
821 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
822 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
823 // For OSs where the TCP connections will close upon relevant network
824 // changes, SpdySessionPool doesn't need to force them to close, so in these
825 // cases verify the session has become unavailable but remains open and the
826 // pre-existing stream is still active.
827 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
829 EXPECT_TRUE(session->IsGoingAway());
831 EXPECT_TRUE(session->IsStreamActive(1));
833 // Should close the session.
834 spdy_stream->Close();
835 #endif
836 EXPECT_EQ(NULL, spdy_stream.get());
838 base::MessageLoop::current()->RunUntilIdle();
839 EXPECT_TRUE(session == NULL);
842 TEST_P(SpdySessionTest, ClientPing) {
843 session_deps_.enable_ping = true;
844 session_deps_.host_resolver->set_synchronous_mode(true);
846 MockConnect connect_data(SYNCHRONOUS, OK);
847 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
848 MockRead reads[] = {
849 CreateMockRead(*read_ping, 1),
850 MockRead(ASYNC, 0, 0, 2) // EOF
852 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
853 MockWrite writes[] = {
854 CreateMockWrite(*write_ping, 0),
856 DeterministicSocketData data(
857 reads, arraysize(reads), writes, arraysize(writes));
858 data.set_connect_data(connect_data);
859 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
861 CreateDeterministicNetworkSession();
863 base::WeakPtr<SpdySession> session =
864 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
866 base::WeakPtr<SpdyStream> spdy_stream1 =
867 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
868 session, test_url_, MEDIUM, BoundNetLog());
869 ASSERT_TRUE(spdy_stream1.get() != NULL);
870 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
871 spdy_stream1->SetDelegate(&delegate);
873 base::TimeTicks before_ping_time = base::TimeTicks::Now();
875 session->set_connection_at_risk_of_loss_time(
876 base::TimeDelta::FromSeconds(-1));
877 session->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
879 session->SendPrefacePingIfNoneInFlight();
881 data.RunFor(2);
883 session->CheckPingStatus(before_ping_time);
885 EXPECT_EQ(0, session->pings_in_flight());
886 EXPECT_GE(session->next_ping_id(), 1U);
887 EXPECT_FALSE(session->check_ping_status_pending());
888 EXPECT_GE(session->last_activity_time(), before_ping_time);
890 data.RunFor(1);
892 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
894 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
895 EXPECT_TRUE(session == NULL);
898 TEST_P(SpdySessionTest, ServerPing) {
899 session_deps_.host_resolver->set_synchronous_mode(true);
901 MockConnect connect_data(SYNCHRONOUS, OK);
902 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
903 MockRead reads[] = {
904 CreateMockRead(*read_ping),
905 MockRead(SYNCHRONOUS, 0, 0) // EOF
907 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
908 MockWrite writes[] = {
909 CreateMockWrite(*write_ping),
911 StaticSocketDataProvider data(
912 reads, arraysize(reads), writes, arraysize(writes));
913 data.set_connect_data(connect_data);
914 session_deps_.socket_factory->AddSocketDataProvider(&data);
916 CreateNetworkSession();
918 base::WeakPtr<SpdySession> session =
919 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
921 base::WeakPtr<SpdyStream> spdy_stream1 =
922 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
923 session, test_url_, MEDIUM, BoundNetLog());
924 ASSERT_TRUE(spdy_stream1.get() != NULL);
925 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
926 spdy_stream1->SetDelegate(&delegate);
928 // Flush the read completion task.
929 base::MessageLoop::current()->RunUntilIdle();
931 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
933 EXPECT_TRUE(session == NULL);
934 EXPECT_EQ(NULL, spdy_stream1.get());
937 // Cause a ping to be sent out while producing a write. The write loop
938 // should handle this properly, i.e. another DoWriteLoop task should
939 // not be posted. This is a regression test for
940 // http://crbug.com/261043 .
941 TEST_P(SpdySessionTest, PingAndWriteLoop) {
942 session_deps_.enable_ping = true;
943 session_deps_.time_func = TheNearFuture;
945 MockConnect connect_data(SYNCHRONOUS, OK);
946 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
947 scoped_ptr<SpdyFrame> req(
948 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
949 MockWrite writes[] = {
950 CreateMockWrite(*req, 0),
951 CreateMockWrite(*write_ping, 1),
954 MockRead reads[] = {
955 MockRead(ASYNC, 0, 2) // EOF
958 session_deps_.host_resolver->set_synchronous_mode(true);
960 DeterministicSocketData data(reads, arraysize(reads),
961 writes, arraysize(writes));
962 data.set_connect_data(connect_data);
963 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
965 CreateDeterministicNetworkSession();
967 base::WeakPtr<SpdySession> session =
968 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
970 GURL url(kDefaultURL);
971 base::WeakPtr<SpdyStream> spdy_stream =
972 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
973 session, url, LOWEST, BoundNetLog());
974 test::StreamDelegateDoNothing delegate(spdy_stream);
975 spdy_stream->SetDelegate(&delegate);
977 scoped_ptr<SpdyHeaderBlock> headers(
978 spdy_util_.ConstructGetHeaderBlock(url.spec()));
979 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
981 // Shift time so that a ping will be sent out.
982 g_time_delta = base::TimeDelta::FromSeconds(11);
984 data.RunFor(2);
986 session->CloseSessionOnError(ERR_ABORTED, "Aborting");
989 TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
990 const SpdyStreamId kLastStreamId = 0x7fffffff;
991 session_deps_.host_resolver->set_synchronous_mode(true);
993 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
994 // fixed to allow for two stream ID assignments, and three concurrent
995 // streams. Four streams are started, and two are activated. Verify the
996 // session goes away, and that the created (but not activated) and
997 // stalled streams are aborted. Also verify the activated streams complete,
998 // at which point the session closes.
1000 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
1001 NULL, 0, false, kLastStreamId - 2, MEDIUM, true));
1002 scoped_ptr<SpdyFrame> req2(
1003 spdy_util_.ConstructSpdyGet(NULL, 0, false, kLastStreamId, MEDIUM, true));
1005 MockWrite writes[] = {
1006 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
1009 scoped_ptr<SpdyFrame> resp1(
1010 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId - 2));
1011 scoped_ptr<SpdyFrame> resp2(
1012 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId));
1014 scoped_ptr<SpdyFrame> body1(
1015 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
1016 scoped_ptr<SpdyFrame> body2(
1017 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
1019 MockRead reads[] = {
1020 CreateMockRead(*resp1, 2), CreateMockRead(*resp2, 3),
1021 CreateMockRead(*body1, 4), CreateMockRead(*body2, 5),
1022 MockRead(ASYNC, 0, 6) // EOF
1025 DeterministicSocketData data(
1026 reads, arraysize(reads), writes, arraysize(writes));
1028 MockConnect connect_data(SYNCHRONOUS, OK);
1029 data.set_connect_data(connect_data);
1030 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1032 CreateDeterministicNetworkSession();
1033 base::WeakPtr<SpdySession> session =
1034 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1036 // Fix stream_hi_water_mark_ to allow for two stream activations.
1037 session->stream_hi_water_mark_ = kLastStreamId - 2;
1038 // Fix max_concurrent_streams to allow for three stream creations.
1039 session->max_concurrent_streams_ = 3;
1041 // Create three streams synchronously, and begin a fourth (which is stalled).
1042 GURL url(kDefaultURL);
1043 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1044 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1045 test::StreamDelegateDoNothing delegate1(stream1);
1046 stream1->SetDelegate(&delegate1);
1048 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
1049 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1050 test::StreamDelegateDoNothing delegate2(stream2);
1051 stream2->SetDelegate(&delegate2);
1053 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1054 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1055 test::StreamDelegateDoNothing delegate3(stream3);
1056 stream3->SetDelegate(&delegate3);
1058 SpdyStreamRequest request4;
1059 TestCompletionCallback callback4;
1060 EXPECT_EQ(ERR_IO_PENDING,
1061 request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1062 session,
1063 url,
1064 MEDIUM,
1065 BoundNetLog(),
1066 callback4.callback()));
1068 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1069 EXPECT_EQ(0u, session->num_active_streams());
1070 EXPECT_EQ(3u, session->num_created_streams());
1071 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1073 // Activate stream 1. One ID remains available.
1074 stream1->SendRequestHeaders(
1075 scoped_ptr<SpdyHeaderBlock>(
1076 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1077 NO_MORE_DATA_TO_SEND);
1078 data.RunFor(1);
1080 EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1081 EXPECT_EQ(1u, session->num_active_streams());
1082 EXPECT_EQ(2u, session->num_created_streams());
1083 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1085 // Activate stream 2. ID space is exhausted.
1086 stream2->SendRequestHeaders(
1087 scoped_ptr<SpdyHeaderBlock>(
1088 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1089 NO_MORE_DATA_TO_SEND);
1090 data.RunFor(1);
1092 // Active streams remain active.
1093 EXPECT_EQ(kLastStreamId, stream2->stream_id());
1094 EXPECT_EQ(2u, session->num_active_streams());
1096 // Session is going away. Created and stalled streams were aborted.
1097 EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session->availability_state_);
1098 EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose());
1099 EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult());
1100 EXPECT_EQ(0u, session->num_created_streams());
1101 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1103 // Read responses on remaining active streams.
1104 data.RunFor(4);
1105 EXPECT_EQ(OK, delegate1.WaitForClose());
1106 EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1107 EXPECT_EQ(OK, delegate2.WaitForClose());
1108 EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1110 // Session was destroyed.
1111 base::MessageLoop::current()->RunUntilIdle();
1112 EXPECT_FALSE(session.get());
1115 // Verifies that an unstalled pending stream creation racing with a new stream
1116 // creation doesn't violate the maximum stream concurrency. Regression test for
1117 // crbug.com/373858.
1118 TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) {
1119 session_deps_.host_resolver->set_synchronous_mode(true);
1121 MockRead reads[] = {
1122 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1125 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1127 MockConnect connect_data(SYNCHRONOUS, OK);
1128 data.set_connect_data(connect_data);
1129 session_deps_.socket_factory->AddSocketDataProvider(&data);
1131 CreateNetworkSession();
1132 base::WeakPtr<SpdySession> session =
1133 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1135 // Fix max_concurrent_streams to allow for one open stream.
1136 session->max_concurrent_streams_ = 1;
1138 // Create two streams: one synchronously, and one which stalls.
1139 GURL url(kDefaultURL);
1140 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1141 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1143 SpdyStreamRequest request2;
1144 TestCompletionCallback callback2;
1145 EXPECT_EQ(ERR_IO_PENDING,
1146 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1147 session,
1148 url,
1149 MEDIUM,
1150 BoundNetLog(),
1151 callback2.callback()));
1153 EXPECT_EQ(1u, session->num_created_streams());
1154 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1156 // Cancel the first stream. A callback to unstall the second stream was
1157 // posted. Don't run it yet.
1158 stream1->Cancel();
1160 EXPECT_EQ(0u, session->num_created_streams());
1161 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1163 // Create a third stream prior to the second stream's callback.
1164 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1165 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1167 EXPECT_EQ(1u, session->num_created_streams());
1168 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1170 // NOW run the message loop. The unstalled stream will re-stall itself.
1171 base::MessageLoop::current()->RunUntilIdle();
1172 EXPECT_EQ(1u, session->num_created_streams());
1173 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1175 // Cancel the third stream and run the message loop. Verify that the second
1176 // stream creation now completes.
1177 stream3->Cancel();
1178 base::MessageLoop::current()->RunUntilIdle();
1180 EXPECT_EQ(1u, session->num_created_streams());
1181 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1182 EXPECT_EQ(OK, callback2.WaitForResult());
1185 TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
1186 session_deps_.host_resolver->set_synchronous_mode(true);
1187 session_deps_.time_func = TheNearFuture;
1189 scoped_ptr<SpdyFrame> req(
1190 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1191 scoped_ptr<SpdyFrame> rst(
1192 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
1194 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
1195 NULL, 0, 2, 1, "http://www.example.org/a.dat"));
1196 scoped_ptr<SpdyFrame> push_a_body(
1197 spdy_util_.ConstructSpdyBodyFrame(2, false));
1198 // In ascii "0" < "a". We use it to verify that we properly handle std::map
1199 // iterators inside. See http://crbug.com/443490
1200 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
1201 NULL, 0, 4, 1, "http://www.example.org/0.dat"));
1202 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)};
1203 MockRead reads[] = {
1204 CreateMockRead(*push_a, 1), CreateMockRead(*push_a_body, 2),
1205 CreateMockRead(*push_b, 3), MockRead(ASYNC, 0, 5), // EOF
1207 DeterministicSocketData data(
1208 reads, arraysize(reads), writes, arraysize(writes));
1210 MockConnect connect_data(SYNCHRONOUS, OK);
1211 data.set_connect_data(connect_data);
1212 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1214 CreateDeterministicNetworkSession();
1215 base::WeakPtr<SpdySession> session =
1216 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1218 // Process the principal request, and the first push stream request & body.
1219 GURL url(kDefaultURL);
1220 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1221 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1222 test::StreamDelegateDoNothing delegate(spdy_stream);
1223 spdy_stream->SetDelegate(&delegate);
1225 scoped_ptr<SpdyHeaderBlock> headers(
1226 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1227 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1229 data.RunFor(3);
1231 // Verify that there is one unclaimed push stream.
1232 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1233 SpdySession::PushedStreamMap::iterator iter =
1234 session->unclaimed_pushed_streams_.find(
1235 GURL("http://www.example.org/a.dat"));
1236 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1238 if (session->flow_control_state_ ==
1239 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1240 // Unclaimed push body consumed bytes from the session window.
1241 EXPECT_EQ(
1242 SpdySession::GetDefaultInitialWindowSize(GetParam()) - kUploadDataSize,
1243 session->session_recv_window_size_);
1244 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
1247 // Shift time to expire the push stream. Read the second SYN_STREAM,
1248 // and verify a RST_STREAM was written.
1249 g_time_delta = base::TimeDelta::FromSeconds(301);
1250 data.RunFor(2);
1252 // Verify that the second pushed stream evicted the first pushed stream.
1253 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1254 iter = session->unclaimed_pushed_streams_.find(
1255 GURL("http://www.example.org/0.dat"));
1256 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1258 if (session->flow_control_state_ ==
1259 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1260 // Verify that the session window reclaimed the evicted stream body.
1261 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
1262 session->session_recv_window_size_);
1263 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
1266 // Read and process EOF.
1267 data.RunFor(1);
1268 base::MessageLoop::current()->RunUntilIdle();
1269 EXPECT_TRUE(session == NULL);
1272 TEST_P(SpdySessionTest, FailedPing) {
1273 session_deps_.host_resolver->set_synchronous_mode(true);
1275 MockConnect connect_data(SYNCHRONOUS, OK);
1276 MockRead reads[] = {
1277 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1279 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
1280 scoped_ptr<SpdyFrame> goaway(
1281 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping."));
1282 MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)};
1283 StaticSocketDataProvider data(
1284 reads, arraysize(reads), writes, arraysize(writes));
1285 data.set_connect_data(connect_data);
1286 session_deps_.socket_factory->AddSocketDataProvider(&data);
1288 CreateNetworkSession();
1290 base::WeakPtr<SpdySession> session =
1291 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1293 base::WeakPtr<SpdyStream> spdy_stream1 =
1294 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1295 session, test_url_, MEDIUM, BoundNetLog());
1296 ASSERT_TRUE(spdy_stream1.get() != NULL);
1297 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
1298 spdy_stream1->SetDelegate(&delegate);
1300 session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1301 session->set_hung_interval(base::TimeDelta::FromSeconds(0));
1303 // Send a PING frame.
1304 session->WritePingFrame(1, false);
1305 EXPECT_LT(0, session->pings_in_flight());
1306 EXPECT_GE(session->next_ping_id(), 1U);
1307 EXPECT_TRUE(session->check_ping_status_pending());
1309 // Assert session is not closed.
1310 EXPECT_TRUE(session->IsAvailable());
1311 EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams());
1312 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1314 // We set last time we have received any data in 1 sec less than now.
1315 // CheckPingStatus will trigger timeout because hung interval is zero.
1316 base::TimeTicks now = base::TimeTicks::Now();
1317 session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
1318 session->CheckPingStatus(now);
1319 base::MessageLoop::current()->RunUntilIdle();
1321 EXPECT_TRUE(session == NULL);
1322 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1323 EXPECT_EQ(NULL, spdy_stream1.get());
1326 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1327 // settings frame increasing the max concurrent streams by 1. Make
1328 // sure nothing blows up. This is a regression test for
1329 // http://crbug.com/57331 .
1330 TEST_P(SpdySessionTest, OnSettings) {
1331 session_deps_.host_resolver->set_synchronous_mode(true);
1333 const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1335 SettingsMap new_settings;
1336 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1337 new_settings[kSpdySettingsIds] =
1338 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1339 scoped_ptr<SpdyFrame> settings_frame(
1340 spdy_util_.ConstructSpdySettings(new_settings));
1341 MockRead reads[] = {
1342 CreateMockRead(*settings_frame, 0),
1343 MockRead(ASYNC, 0, 1),
1346 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1347 MockWrite writes[] = {
1348 CreateMockWrite(*settings_ack, 2),
1351 DeterministicSocketData data(reads, arraysize(reads),
1352 writes, arraysize(writes));
1353 MockConnect connect_data(SYNCHRONOUS, OK);
1354 data.set_connect_data(connect_data);
1355 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1357 CreateDeterministicNetworkSession();
1359 base::WeakPtr<SpdySession> session =
1360 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1362 // Create the maximum number of concurrent streams.
1363 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1364 base::WeakPtr<SpdyStream> spdy_stream =
1365 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1366 session, test_url_, MEDIUM, BoundNetLog());
1367 ASSERT_TRUE(spdy_stream != NULL);
1370 StreamReleaserCallback stream_releaser;
1371 SpdyStreamRequest request;
1372 ASSERT_EQ(ERR_IO_PENDING,
1373 request.StartRequest(
1374 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1375 BoundNetLog(),
1376 stream_releaser.MakeCallback(&request)));
1378 data.RunFor(1);
1380 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1382 data.RunFor(1);
1383 if (spdy_util_.spdy_version() >= SPDY4) {
1384 // Allow the SETTINGS+ACK to write, so the session finishes draining.
1385 data.RunFor(1);
1387 base::MessageLoop::current()->RunUntilIdle();
1388 EXPECT_TRUE(session == NULL);
1391 // Start with a persisted value for max concurrent streams. Receive a
1392 // settings frame increasing the max concurrent streams by 1 and which
1393 // also clears the persisted data. Verify that persisted data is
1394 // correct.
1395 TEST_P(SpdySessionTest, ClearSettings) {
1396 if (spdy_util_.spdy_version() >= SPDY4) {
1397 // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1398 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4.
1399 return;
1401 session_deps_.host_resolver->set_synchronous_mode(true);
1403 SettingsMap new_settings;
1404 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1405 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1406 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1407 scoped_ptr<SpdyFrame> settings_frame(
1408 spdy_util_.ConstructSpdySettings(new_settings));
1409 uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1410 test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1411 MockRead reads[] = {
1412 CreateMockRead(*settings_frame, 0),
1413 MockRead(ASYNC, 0, 1),
1416 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
1417 MockConnect connect_data(SYNCHRONOUS, OK);
1418 data.set_connect_data(connect_data);
1419 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1421 CreateDeterministicNetworkSession();
1423 // Initialize the SpdySetting with the default.
1424 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1425 test_host_port_pair_,
1426 SETTINGS_MAX_CONCURRENT_STREAMS,
1427 SETTINGS_FLAG_PLEASE_PERSIST,
1428 kInitialMaxConcurrentStreams);
1430 EXPECT_FALSE(
1431 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1432 test_host_port_pair_).empty());
1434 base::WeakPtr<SpdySession> session =
1435 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1437 // Create the maximum number of concurrent streams.
1438 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1439 base::WeakPtr<SpdyStream> spdy_stream =
1440 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1441 session, test_url_, MEDIUM, BoundNetLog());
1442 ASSERT_TRUE(spdy_stream != NULL);
1445 StreamReleaserCallback stream_releaser;
1447 SpdyStreamRequest request;
1448 ASSERT_EQ(ERR_IO_PENDING,
1449 request.StartRequest(
1450 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1451 BoundNetLog(),
1452 stream_releaser.MakeCallback(&request)));
1454 data.RunFor(1);
1456 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1458 // Make sure that persisted data is cleared.
1459 EXPECT_TRUE(
1460 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1461 test_host_port_pair_).empty());
1463 // Make sure session's max_concurrent_streams is correct.
1464 EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1465 session->max_concurrent_streams());
1467 data.RunFor(1);
1468 EXPECT_TRUE(session == NULL);
1471 // Start with max concurrent streams set to 1. Request two streams.
1472 // When the first completes, have the callback close its stream, which
1473 // should trigger the second stream creation. Then cancel that one
1474 // immediately. Don't crash. This is a regression test for
1475 // http://crbug.com/63532 .
1476 TEST_P(SpdySessionTest, CancelPendingCreateStream) {
1477 session_deps_.host_resolver->set_synchronous_mode(true);
1479 MockRead reads[] = {
1480 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1483 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1484 MockConnect connect_data(SYNCHRONOUS, OK);
1486 data.set_connect_data(connect_data);
1487 session_deps_.socket_factory->AddSocketDataProvider(&data);
1489 CreateNetworkSession();
1491 // Initialize the SpdySetting with 1 max concurrent streams.
1492 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1493 test_host_port_pair_,
1494 SETTINGS_MAX_CONCURRENT_STREAMS,
1495 SETTINGS_FLAG_PLEASE_PERSIST,
1498 base::WeakPtr<SpdySession> session =
1499 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1501 // Leave room for only one more stream to be created.
1502 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1503 base::WeakPtr<SpdyStream> spdy_stream =
1504 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1505 session, test_url_, MEDIUM, BoundNetLog());
1506 ASSERT_TRUE(spdy_stream != NULL);
1509 // Create 2 more streams. First will succeed. Second will be pending.
1510 base::WeakPtr<SpdyStream> spdy_stream1 =
1511 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1512 session, test_url_, MEDIUM, BoundNetLog());
1513 ASSERT_TRUE(spdy_stream1.get() != NULL);
1515 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1516 // a valgrind error if the callback is invoked when it's not supposed to be.
1517 scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
1519 SpdyStreamRequest request;
1520 ASSERT_EQ(ERR_IO_PENDING,
1521 request.StartRequest(
1522 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1523 BoundNetLog(),
1524 callback->callback()));
1526 // Release the first one, this will allow the second to be created.
1527 spdy_stream1->Cancel();
1528 EXPECT_EQ(NULL, spdy_stream1.get());
1530 request.CancelRequest();
1531 callback.reset();
1533 // Should not crash when running the pending callback.
1534 base::MessageLoop::current()->RunUntilIdle();
1537 TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
1538 session_deps_.host_resolver->set_synchronous_mode(true);
1540 MockRead reads[] = {
1541 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1544 SettingsMap settings;
1545 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1546 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
1547 MockConnect connect_data(SYNCHRONOUS, OK);
1548 scoped_ptr<SpdyFrame> settings_frame(
1549 spdy_util_.ConstructSpdySettings(settings));
1550 std::vector<MockWrite> writes;
1551 if ((GetParam() >= kProtoSPDY4MinimumVersion) &&
1552 (GetParam() <= kProtoSPDY4MaximumVersion)) {
1553 writes.push_back(
1554 MockWrite(ASYNC,
1555 kHttp2ConnectionHeaderPrefix,
1556 kHttp2ConnectionHeaderPrefixSize));
1558 writes.push_back(CreateMockWrite(*settings_frame));
1560 SettingsMap server_settings;
1561 const uint32 initial_max_concurrent_streams = 1;
1562 server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1563 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1564 initial_max_concurrent_streams);
1565 scoped_ptr<SpdyFrame> server_settings_frame(
1566 spdy_util_.ConstructSpdySettings(server_settings));
1567 if (GetParam() <= kProtoSPDY31) {
1568 writes.push_back(CreateMockWrite(*server_settings_frame));
1571 StaticSocketDataProvider data(reads, arraysize(reads),
1572 vector_as_array(&writes), writes.size());
1573 data.set_connect_data(connect_data);
1574 session_deps_.socket_factory->AddSocketDataProvider(&data);
1576 CreateNetworkSession();
1578 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1579 test_host_port_pair_,
1580 SETTINGS_MAX_CONCURRENT_STREAMS,
1581 SETTINGS_FLAG_PLEASE_PERSIST,
1582 initial_max_concurrent_streams);
1584 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1585 pool_peer.SetEnableSendingInitialData(true);
1587 base::WeakPtr<SpdySession> session =
1588 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1590 base::MessageLoop::current()->RunUntilIdle();
1591 EXPECT_TRUE(data.at_write_eof());
1594 TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
1595 CreateNetworkSession();
1597 base::WeakPtr<HttpServerProperties> test_http_server_properties =
1598 spdy_session_pool_->http_server_properties();
1599 SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
1600 test_http_server_properties->SetSpdySetting(
1601 test_host_port_pair_,
1602 SETTINGS_MAX_CONCURRENT_STREAMS,
1603 SETTINGS_FLAG_PLEASE_PERSIST,
1605 EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
1606 test_host_port_pair_).size());
1607 spdy_session_pool_->OnIPAddressChanged();
1608 EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
1609 test_host_port_pair_).size());
1612 TEST_P(SpdySessionTest, Initialize) {
1613 BoundTestNetLog log;
1614 session_deps_.net_log = log.bound().net_log();
1615 session_deps_.host_resolver->set_synchronous_mode(true);
1617 MockConnect connect_data(SYNCHRONOUS, OK);
1618 MockRead reads[] = {
1619 MockRead(ASYNC, 0, 0) // EOF
1622 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1623 data.set_connect_data(connect_data);
1624 session_deps_.socket_factory->AddSocketDataProvider(&data);
1626 CreateNetworkSession();
1628 base::WeakPtr<SpdySession> session =
1629 CreateInsecureSpdySession(http_session_, key_, log.bound());
1630 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1632 // Flush the read completion task.
1633 base::MessageLoop::current()->RunUntilIdle();
1635 TestNetLog::CapturedEntryList entries;
1636 log.GetEntries(&entries);
1637 EXPECT_LT(0u, entries.size());
1639 // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly.
1640 int pos = ExpectLogContainsSomewhere(
1641 entries, 0, NetLog::TYPE_HTTP2_SESSION_INITIALIZED, NetLog::PHASE_NONE);
1642 EXPECT_LT(0, pos);
1644 TestNetLog::CapturedEntry entry = entries[pos];
1645 NetLog::Source socket_source;
1646 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1647 &socket_source));
1648 EXPECT_TRUE(socket_source.IsValid());
1649 EXPECT_NE(log.bound().source().id, socket_source.id);
1652 TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
1653 session_deps_.host_resolver->set_synchronous_mode(true);
1655 MockConnect connect_data(SYNCHRONOUS, OK);
1656 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
1657 MockRead reads[] = {
1658 CreateMockRead(*goaway),
1659 MockRead(SYNCHRONOUS, 0, 0) // EOF
1662 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1663 data.set_connect_data(connect_data);
1664 session_deps_.socket_factory->AddSocketDataProvider(&data);
1666 CreateNetworkSession();
1668 BoundTestNetLog log;
1669 base::WeakPtr<SpdySession> session =
1670 CreateInsecureSpdySession(http_session_, key_, log.bound());
1671 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1673 // Flush the read completion task.
1674 base::MessageLoop::current()->RunUntilIdle();
1676 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1677 EXPECT_TRUE(session == NULL);
1679 // Check that the NetLog was filled reasonably.
1680 TestNetLog::CapturedEntryList entries;
1681 log.GetEntries(&entries);
1682 EXPECT_LT(0u, entries.size());
1684 // Check that we logged SPDY_SESSION_CLOSE correctly.
1685 int pos = ExpectLogContainsSomewhere(
1686 entries, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE, NetLog::PHASE_NONE);
1688 if (pos < static_cast<int>(entries.size())) {
1689 TestNetLog::CapturedEntry entry = entries[pos];
1690 int error_code = 0;
1691 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1692 EXPECT_EQ(OK, error_code);
1693 } else {
1694 ADD_FAILURE();
1698 TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1699 session_deps_.host_resolver->set_synchronous_mode(true);
1701 MockConnect connect_data(SYNCHRONOUS, OK);
1702 MockRead reads[] = {
1703 MockRead(SYNCHRONOUS, 0, 0) // EOF
1706 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1707 data.set_connect_data(connect_data);
1708 session_deps_.socket_factory->AddSocketDataProvider(&data);
1710 CreateNetworkSession();
1712 BoundTestNetLog log;
1713 base::WeakPtr<SpdySession> session =
1714 CreateInsecureSpdySession(http_session_, key_, log.bound());
1715 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1717 // Flush the read completion task.
1718 base::MessageLoop::current()->RunUntilIdle();
1720 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1721 EXPECT_TRUE(session == NULL);
1723 // Check that the NetLog was filled reasonably.
1724 TestNetLog::CapturedEntryList entries;
1725 log.GetEntries(&entries);
1726 EXPECT_LT(0u, entries.size());
1728 // Check that we logged SPDY_SESSION_CLOSE correctly.
1729 int pos = ExpectLogContainsSomewhere(
1730 entries, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE, NetLog::PHASE_NONE);
1732 if (pos < static_cast<int>(entries.size())) {
1733 TestNetLog::CapturedEntry entry = entries[pos];
1734 int error_code = 0;
1735 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1736 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1737 } else {
1738 ADD_FAILURE();
1742 TEST_P(SpdySessionTest, SynCompressionHistograms) {
1743 session_deps_.enable_compression = true;
1745 scoped_ptr<SpdyFrame> req(
1746 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, MEDIUM, true));
1747 MockWrite writes[] = {
1748 CreateMockWrite(*req, 0),
1750 MockRead reads[] = {
1751 MockRead(ASYNC, 0, 1) // EOF
1753 DeterministicSocketData data(reads, arraysize(reads),
1754 writes, arraysize(writes));
1755 MockConnect connect_data(SYNCHRONOUS, OK);
1756 data.set_connect_data(connect_data);
1757 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1759 CreateDeterministicNetworkSession();
1760 base::WeakPtr<SpdySession> session =
1761 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1763 GURL url(kDefaultURL);
1764 base::WeakPtr<SpdyStream> spdy_stream =
1765 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1766 session, url, MEDIUM, BoundNetLog());
1767 test::StreamDelegateDoNothing delegate(spdy_stream);
1768 spdy_stream->SetDelegate(&delegate);
1770 scoped_ptr<SpdyHeaderBlock> headers(
1771 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1772 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1773 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1775 // Write request headers & capture resulting histogram update.
1776 base::HistogramTester histogram_tester;
1778 data.RunFor(1);
1779 // Regression test of compression performance under the request fixture.
1780 switch (spdy_util_.spdy_version()) {
1781 case SPDY3:
1782 histogram_tester.ExpectBucketCount(
1783 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1784 break;
1785 case SPDY4:
1786 histogram_tester.ExpectBucketCount(
1787 "Net.SpdySynStreamCompressionPercentage", 81, 1);
1788 break;
1789 default:
1790 NOTREACHED();
1793 // Read and process EOF.
1794 data.RunFor(1);
1795 base::MessageLoop::current()->RunUntilIdle();
1796 EXPECT_TRUE(session == NULL);
1799 // Queue up a low-priority SYN_STREAM followed by a high-priority
1800 // one. The high priority one should still send first and receive
1801 // first.
1802 TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1803 // Construct the request.
1804 MockConnect connect_data(SYNCHRONOUS, OK);
1805 scoped_ptr<SpdyFrame> req_highest(
1806 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true));
1807 scoped_ptr<SpdyFrame> req_lowest(
1808 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1809 MockWrite writes[] = {
1810 CreateMockWrite(*req_highest, 0),
1811 CreateMockWrite(*req_lowest, 1),
1814 scoped_ptr<SpdyFrame> resp_highest(
1815 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1816 scoped_ptr<SpdyFrame> body_highest(
1817 spdy_util_.ConstructSpdyBodyFrame(1, true));
1818 scoped_ptr<SpdyFrame> resp_lowest(
1819 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1820 scoped_ptr<SpdyFrame> body_lowest(
1821 spdy_util_.ConstructSpdyBodyFrame(3, true));
1822 MockRead reads[] = {
1823 CreateMockRead(*resp_highest, 2),
1824 CreateMockRead(*body_highest, 3),
1825 CreateMockRead(*resp_lowest, 4),
1826 CreateMockRead(*body_lowest, 5),
1827 MockRead(ASYNC, 0, 6) // EOF
1830 session_deps_.host_resolver->set_synchronous_mode(true);
1832 DeterministicSocketData data(reads, arraysize(reads),
1833 writes, arraysize(writes));
1834 data.set_connect_data(connect_data);
1835 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1837 CreateDeterministicNetworkSession();
1839 base::WeakPtr<SpdySession> session =
1840 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1842 GURL url(kDefaultURL);
1844 base::WeakPtr<SpdyStream> spdy_stream_lowest =
1845 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1846 session, url, LOWEST, BoundNetLog());
1847 ASSERT_TRUE(spdy_stream_lowest);
1848 EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1849 test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1850 spdy_stream_lowest->SetDelegate(&delegate_lowest);
1852 base::WeakPtr<SpdyStream> spdy_stream_highest =
1853 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1854 session, url, HIGHEST, BoundNetLog());
1855 ASSERT_TRUE(spdy_stream_highest);
1856 EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1857 test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1858 spdy_stream_highest->SetDelegate(&delegate_highest);
1860 // Queue the lower priority one first.
1862 scoped_ptr<SpdyHeaderBlock> headers_lowest(
1863 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1864 spdy_stream_lowest->SendRequestHeaders(
1865 headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1866 EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1868 scoped_ptr<SpdyHeaderBlock> headers_highest(
1869 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1870 spdy_stream_highest->SendRequestHeaders(
1871 headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1872 EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1874 data.RunFor(7);
1876 EXPECT_FALSE(spdy_stream_lowest);
1877 EXPECT_FALSE(spdy_stream_highest);
1878 EXPECT_EQ(3u, delegate_lowest.stream_id());
1879 EXPECT_EQ(1u, delegate_highest.stream_id());
1882 TEST_P(SpdySessionTest, CancelStream) {
1883 MockConnect connect_data(SYNCHRONOUS, OK);
1884 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1885 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1886 scoped_ptr<SpdyFrame> req2(
1887 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1888 MockWrite writes[] = {
1889 CreateMockWrite(*req2, 0),
1892 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1893 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1894 MockRead reads[] = {
1895 CreateMockRead(*resp2, 1),
1896 CreateMockRead(*body2, 2),
1897 MockRead(ASYNC, 0, 3) // EOF
1900 session_deps_.host_resolver->set_synchronous_mode(true);
1902 DeterministicSocketData data(reads, arraysize(reads),
1903 writes, arraysize(writes));
1904 data.set_connect_data(connect_data);
1905 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1907 CreateDeterministicNetworkSession();
1909 base::WeakPtr<SpdySession> session =
1910 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1912 GURL url1(kDefaultURL);
1913 base::WeakPtr<SpdyStream> spdy_stream1 =
1914 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1915 session, url1, HIGHEST, BoundNetLog());
1916 ASSERT_TRUE(spdy_stream1.get() != NULL);
1917 EXPECT_EQ(0u, spdy_stream1->stream_id());
1918 test::StreamDelegateDoNothing delegate1(spdy_stream1);
1919 spdy_stream1->SetDelegate(&delegate1);
1921 GURL url2(kDefaultURL);
1922 base::WeakPtr<SpdyStream> spdy_stream2 =
1923 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1924 session, url2, LOWEST, BoundNetLog());
1925 ASSERT_TRUE(spdy_stream2.get() != NULL);
1926 EXPECT_EQ(0u, spdy_stream2->stream_id());
1927 test::StreamDelegateDoNothing delegate2(spdy_stream2);
1928 spdy_stream2->SetDelegate(&delegate2);
1930 scoped_ptr<SpdyHeaderBlock> headers(
1931 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1932 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1933 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1935 scoped_ptr<SpdyHeaderBlock> headers2(
1936 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1937 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1938 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1940 EXPECT_EQ(0u, spdy_stream1->stream_id());
1942 spdy_stream1->Cancel();
1943 EXPECT_EQ(NULL, spdy_stream1.get());
1945 EXPECT_EQ(0u, delegate1.stream_id());
1947 data.RunFor(1);
1949 EXPECT_EQ(0u, delegate1.stream_id());
1950 EXPECT_EQ(1u, delegate2.stream_id());
1952 spdy_stream2->Cancel();
1953 EXPECT_EQ(NULL, spdy_stream2.get());
1956 // Create two streams that are set to re-close themselves on close,
1957 // and then close the session. Nothing should blow up. Also a
1958 // regression test for http://crbug.com/139518 .
1959 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1960 session_deps_.host_resolver->set_synchronous_mode(true);
1962 MockConnect connect_data(SYNCHRONOUS, OK);
1964 // No actual data will be sent.
1965 MockWrite writes[] = {
1966 MockWrite(ASYNC, 0, 1) // EOF
1969 MockRead reads[] = {
1970 MockRead(ASYNC, 0, 0) // EOF
1972 DeterministicSocketData data(reads, arraysize(reads),
1973 writes, arraysize(writes));
1974 data.set_connect_data(connect_data);
1975 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1977 CreateDeterministicNetworkSession();
1979 base::WeakPtr<SpdySession> session =
1980 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1982 GURL url1(kDefaultURL);
1983 base::WeakPtr<SpdyStream> spdy_stream1 =
1984 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1985 session, url1, HIGHEST, BoundNetLog());
1986 ASSERT_TRUE(spdy_stream1.get() != NULL);
1987 EXPECT_EQ(0u, spdy_stream1->stream_id());
1989 GURL url2(kDefaultURL);
1990 base::WeakPtr<SpdyStream> spdy_stream2 =
1991 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1992 session, url2, LOWEST, BoundNetLog());
1993 ASSERT_TRUE(spdy_stream2.get() != NULL);
1994 EXPECT_EQ(0u, spdy_stream2->stream_id());
1996 test::ClosingDelegate delegate1(spdy_stream1);
1997 spdy_stream1->SetDelegate(&delegate1);
1999 test::ClosingDelegate delegate2(spdy_stream2);
2000 spdy_stream2->SetDelegate(&delegate2);
2002 scoped_ptr<SpdyHeaderBlock> headers(
2003 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2004 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2005 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2007 scoped_ptr<SpdyHeaderBlock> headers2(
2008 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2009 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2010 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2012 // Ensure that the streams have not yet been activated and assigned an id.
2013 EXPECT_EQ(0u, spdy_stream1->stream_id());
2014 EXPECT_EQ(0u, spdy_stream2->stream_id());
2016 // Ensure we don't crash while closing the session.
2017 session->CloseSessionOnError(ERR_ABORTED, std::string());
2019 EXPECT_EQ(NULL, spdy_stream1.get());
2020 EXPECT_EQ(NULL, spdy_stream2.get());
2022 EXPECT_TRUE(delegate1.StreamIsClosed());
2023 EXPECT_TRUE(delegate2.StreamIsClosed());
2025 base::MessageLoop::current()->RunUntilIdle();
2026 EXPECT_TRUE(session == NULL);
2029 // Create two streams that are set to close each other on close, and
2030 // then close the session. Nothing should blow up.
2031 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
2032 session_deps_.host_resolver->set_synchronous_mode(true);
2034 MockConnect connect_data(SYNCHRONOUS, OK);
2036 // No actual data will be sent.
2037 MockWrite writes[] = {
2038 MockWrite(ASYNC, 0, 1) // EOF
2041 MockRead reads[] = {
2042 MockRead(ASYNC, 0, 0) // EOF
2044 DeterministicSocketData data(reads, arraysize(reads),
2045 writes, arraysize(writes));
2046 data.set_connect_data(connect_data);
2047 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2049 CreateDeterministicNetworkSession();
2051 base::WeakPtr<SpdySession> session =
2052 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2054 GURL url1(kDefaultURL);
2055 base::WeakPtr<SpdyStream> spdy_stream1 =
2056 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2057 session, url1, HIGHEST, BoundNetLog());
2058 ASSERT_TRUE(spdy_stream1.get() != NULL);
2059 EXPECT_EQ(0u, spdy_stream1->stream_id());
2061 GURL url2(kDefaultURL);
2062 base::WeakPtr<SpdyStream> spdy_stream2 =
2063 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2064 session, url2, LOWEST, BoundNetLog());
2065 ASSERT_TRUE(spdy_stream2.get() != NULL);
2066 EXPECT_EQ(0u, spdy_stream2->stream_id());
2068 // Make |spdy_stream1| close |spdy_stream2|.
2069 test::ClosingDelegate delegate1(spdy_stream2);
2070 spdy_stream1->SetDelegate(&delegate1);
2072 // Make |spdy_stream2| close |spdy_stream1|.
2073 test::ClosingDelegate delegate2(spdy_stream1);
2074 spdy_stream2->SetDelegate(&delegate2);
2076 scoped_ptr<SpdyHeaderBlock> headers(
2077 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2078 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2079 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2081 scoped_ptr<SpdyHeaderBlock> headers2(
2082 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2083 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2084 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2086 // Ensure that the streams have not yet been activated and assigned an id.
2087 EXPECT_EQ(0u, spdy_stream1->stream_id());
2088 EXPECT_EQ(0u, spdy_stream2->stream_id());
2090 // Ensure we don't crash while closing the session.
2091 session->CloseSessionOnError(ERR_ABORTED, std::string());
2093 EXPECT_EQ(NULL, spdy_stream1.get());
2094 EXPECT_EQ(NULL, spdy_stream2.get());
2096 EXPECT_TRUE(delegate1.StreamIsClosed());
2097 EXPECT_TRUE(delegate2.StreamIsClosed());
2099 base::MessageLoop::current()->RunUntilIdle();
2100 EXPECT_TRUE(session == NULL);
2103 // Create two streams that are set to re-close themselves on close,
2104 // activate them, and then close the session. Nothing should blow up.
2105 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
2106 session_deps_.host_resolver->set_synchronous_mode(true);
2108 MockConnect connect_data(SYNCHRONOUS, OK);
2110 scoped_ptr<SpdyFrame> req1(
2111 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2112 scoped_ptr<SpdyFrame> req2(
2113 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2114 MockWrite writes[] = {
2115 CreateMockWrite(*req1, 0),
2116 CreateMockWrite(*req2, 1),
2119 MockRead reads[] = {
2120 MockRead(ASYNC, 0, 2) // EOF
2123 DeterministicSocketData data(reads, arraysize(reads),
2124 writes, arraysize(writes));
2125 data.set_connect_data(connect_data);
2126 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2128 CreateDeterministicNetworkSession();
2130 base::WeakPtr<SpdySession> session =
2131 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2133 GURL url1(kDefaultURL);
2134 base::WeakPtr<SpdyStream> spdy_stream1 =
2135 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2136 session, url1, MEDIUM, BoundNetLog());
2137 ASSERT_TRUE(spdy_stream1.get() != NULL);
2138 EXPECT_EQ(0u, spdy_stream1->stream_id());
2140 GURL url2(kDefaultURL);
2141 base::WeakPtr<SpdyStream> spdy_stream2 =
2142 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2143 session, url2, MEDIUM, BoundNetLog());
2144 ASSERT_TRUE(spdy_stream2.get() != NULL);
2145 EXPECT_EQ(0u, spdy_stream2->stream_id());
2147 test::ClosingDelegate delegate1(spdy_stream1);
2148 spdy_stream1->SetDelegate(&delegate1);
2150 test::ClosingDelegate delegate2(spdy_stream2);
2151 spdy_stream2->SetDelegate(&delegate2);
2153 scoped_ptr<SpdyHeaderBlock> headers(
2154 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2155 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2156 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2158 scoped_ptr<SpdyHeaderBlock> headers2(
2159 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2160 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2161 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2163 // Ensure that the streams have not yet been activated and assigned an id.
2164 EXPECT_EQ(0u, spdy_stream1->stream_id());
2165 EXPECT_EQ(0u, spdy_stream2->stream_id());
2167 data.RunFor(2);
2169 EXPECT_EQ(1u, spdy_stream1->stream_id());
2170 EXPECT_EQ(3u, spdy_stream2->stream_id());
2172 // Ensure we don't crash while closing the session.
2173 session->CloseSessionOnError(ERR_ABORTED, std::string());
2175 EXPECT_EQ(NULL, spdy_stream1.get());
2176 EXPECT_EQ(NULL, spdy_stream2.get());
2178 EXPECT_TRUE(delegate1.StreamIsClosed());
2179 EXPECT_TRUE(delegate2.StreamIsClosed());
2181 base::MessageLoop::current()->RunUntilIdle();
2182 EXPECT_TRUE(session == NULL);
2185 // Create two streams that are set to close each other on close,
2186 // activate them, and then close the session. Nothing should blow up.
2187 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2188 session_deps_.host_resolver->set_synchronous_mode(true);
2190 MockConnect connect_data(SYNCHRONOUS, OK);
2192 scoped_ptr<SpdyFrame> req1(
2193 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2194 scoped_ptr<SpdyFrame> req2(
2195 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2196 MockWrite writes[] = {
2197 CreateMockWrite(*req1, 0),
2198 CreateMockWrite(*req2, 1),
2201 MockRead reads[] = {
2202 MockRead(ASYNC, 0, 2) // EOF
2205 DeterministicSocketData data(reads, arraysize(reads),
2206 writes, arraysize(writes));
2207 data.set_connect_data(connect_data);
2208 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2210 CreateDeterministicNetworkSession();
2212 base::WeakPtr<SpdySession> session =
2213 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2215 GURL url1(kDefaultURL);
2216 base::WeakPtr<SpdyStream> spdy_stream1 =
2217 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2218 session, url1, MEDIUM, BoundNetLog());
2219 ASSERT_TRUE(spdy_stream1.get() != NULL);
2220 EXPECT_EQ(0u, spdy_stream1->stream_id());
2222 GURL url2(kDefaultURL);
2223 base::WeakPtr<SpdyStream> spdy_stream2 =
2224 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2225 session, url2, MEDIUM, BoundNetLog());
2226 ASSERT_TRUE(spdy_stream2.get() != NULL);
2227 EXPECT_EQ(0u, spdy_stream2->stream_id());
2229 // Make |spdy_stream1| close |spdy_stream2|.
2230 test::ClosingDelegate delegate1(spdy_stream2);
2231 spdy_stream1->SetDelegate(&delegate1);
2233 // Make |spdy_stream2| close |spdy_stream1|.
2234 test::ClosingDelegate delegate2(spdy_stream1);
2235 spdy_stream2->SetDelegate(&delegate2);
2237 scoped_ptr<SpdyHeaderBlock> headers(
2238 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2239 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2240 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2242 scoped_ptr<SpdyHeaderBlock> headers2(
2243 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2244 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2245 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2247 // Ensure that the streams have not yet been activated and assigned an id.
2248 EXPECT_EQ(0u, spdy_stream1->stream_id());
2249 EXPECT_EQ(0u, spdy_stream2->stream_id());
2251 data.RunFor(2);
2253 EXPECT_EQ(1u, spdy_stream1->stream_id());
2254 EXPECT_EQ(3u, spdy_stream2->stream_id());
2256 // Ensure we don't crash while closing the session.
2257 session->CloseSessionOnError(ERR_ABORTED, std::string());
2259 EXPECT_EQ(NULL, spdy_stream1.get());
2260 EXPECT_EQ(NULL, spdy_stream2.get());
2262 EXPECT_TRUE(delegate1.StreamIsClosed());
2263 EXPECT_TRUE(delegate2.StreamIsClosed());
2265 base::MessageLoop::current()->RunUntilIdle();
2266 EXPECT_TRUE(session == NULL);
2269 // Delegate that closes a given session when the stream is closed.
2270 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2271 public:
2272 SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2273 const base::WeakPtr<SpdySession>& session_to_close)
2274 : StreamDelegateDoNothing(stream),
2275 session_to_close_(session_to_close) {}
2277 ~SessionClosingDelegate() override {}
2279 void OnClose(int status) override {
2280 session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2283 private:
2284 base::WeakPtr<SpdySession> session_to_close_;
2287 // Close an activated stream that closes its session. Nothing should
2288 // blow up. This is a regression test for http://crbug.com/263691 .
2289 TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2290 session_deps_.host_resolver->set_synchronous_mode(true);
2292 MockConnect connect_data(SYNCHRONOUS, OK);
2294 scoped_ptr<SpdyFrame> req(
2295 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2296 scoped_ptr<SpdyFrame> rst(
2297 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2298 scoped_ptr<SpdyFrame> goaway(
2299 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2300 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2301 // despite being queued second.
2302 MockWrite writes[] = {
2303 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 1),
2304 CreateMockWrite(*rst, 2),
2307 MockRead reads[] = {
2308 MockRead(ASYNC, 0, 3) // EOF
2310 DeterministicSocketData data(reads, arraysize(reads),
2311 writes, arraysize(writes));
2312 data.set_connect_data(connect_data);
2313 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2315 CreateDeterministicNetworkSession();
2317 base::WeakPtr<SpdySession> session =
2318 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2320 GURL url(kDefaultURL);
2321 base::WeakPtr<SpdyStream> spdy_stream =
2322 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2323 session, url, MEDIUM, BoundNetLog());
2324 ASSERT_TRUE(spdy_stream.get() != NULL);
2325 EXPECT_EQ(0u, spdy_stream->stream_id());
2327 SessionClosingDelegate delegate(spdy_stream, session);
2328 spdy_stream->SetDelegate(&delegate);
2330 scoped_ptr<SpdyHeaderBlock> headers(
2331 spdy_util_.ConstructGetHeaderBlock(url.spec()));
2332 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2333 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2335 EXPECT_EQ(0u, spdy_stream->stream_id());
2337 data.RunFor(1);
2339 EXPECT_EQ(1u, spdy_stream->stream_id());
2341 // Ensure we don't crash while closing the stream (which closes the
2342 // session).
2343 spdy_stream->Cancel();
2345 EXPECT_EQ(NULL, spdy_stream.get());
2346 EXPECT_TRUE(delegate.StreamIsClosed());
2348 data.RunFor(2); // Write the RST_STREAM & GOAWAY.
2349 base::MessageLoop::current()->RunUntilIdle();
2350 EXPECT_TRUE(session == NULL);
2353 TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2354 session_deps_.host_resolver->set_synchronous_mode(true);
2356 MockConnect connect_data(SYNCHRONOUS, OK);
2358 // No actual data will be sent.
2359 MockWrite writes[] = {
2360 MockWrite(ASYNC, 0, 1) // EOF
2363 MockRead reads[] = {
2364 MockRead(ASYNC, 0, 0) // EOF
2366 DeterministicSocketData data(reads, arraysize(reads),
2367 writes, arraysize(writes));
2368 data.set_connect_data(connect_data);
2369 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2371 // Load a cert that is valid for:
2372 // www.example.org
2373 // mail.example.org
2374 // www.example.com
2375 base::FilePath certs_dir = GetTestCertsDirectory();
2376 scoped_refptr<X509Certificate> test_cert(
2377 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2378 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2380 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2381 ssl.cert = test_cert;
2382 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2384 CreateDeterministicNetworkSession();
2386 base::WeakPtr<SpdySession> session =
2387 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2389 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2390 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2391 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
2392 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2395 TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2396 session_deps_.host_resolver->set_synchronous_mode(true);
2398 MockConnect connect_data(SYNCHRONOUS, OK);
2400 // No actual data will be sent.
2401 MockWrite writes[] = {
2402 MockWrite(ASYNC, 0, 1) // EOF
2405 MockRead reads[] = {
2406 MockRead(ASYNC, 0, 0) // EOF
2408 DeterministicSocketData data(reads, arraysize(reads),
2409 writes, arraysize(writes));
2410 data.set_connect_data(connect_data);
2411 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2413 // Load a cert that is valid for:
2414 // www.example.org
2415 // mail.example.org
2416 // www.example.com
2417 base::FilePath certs_dir = GetTestCertsDirectory();
2418 scoped_refptr<X509Certificate> test_cert(
2419 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2420 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2422 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2423 ssl.channel_id_sent = true;
2424 ssl.cert = test_cert;
2425 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2427 CreateDeterministicNetworkSession();
2429 base::WeakPtr<SpdySession> session =
2430 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2432 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2433 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2434 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2435 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2438 TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2439 // TODO(rtenneti): Define a helper class/methods and move the common code in
2440 // this file.
2441 MockConnect connect_data(SYNCHRONOUS, OK);
2443 SettingsMap new_settings;
2444 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2445 const uint32 max_concurrent_streams = 1;
2446 new_settings[kSpdySettingsIds1] =
2447 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2449 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
2450 scoped_ptr<SpdyFrame> req1(
2451 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2452 scoped_ptr<SpdyFrame> req2(
2453 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
2454 scoped_ptr<SpdyFrame> req3(
2455 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
2456 MockWrite writes[] = {
2457 CreateMockWrite(*settings_ack, 1),
2458 CreateMockWrite(*req1, 2),
2459 CreateMockWrite(*req2, 5),
2460 CreateMockWrite(*req3, 8),
2463 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2464 // streams to 1.
2465 scoped_ptr<SpdyFrame> settings_frame(
2466 spdy_util_.ConstructSpdySettings(new_settings));
2468 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2469 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2471 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2472 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2474 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
2475 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2477 MockRead reads[] = {
2478 CreateMockRead(*settings_frame),
2479 CreateMockRead(*resp1, 3),
2480 CreateMockRead(*body1, 4),
2481 CreateMockRead(*resp2, 6),
2482 CreateMockRead(*body2, 7),
2483 CreateMockRead(*resp3, 9),
2484 CreateMockRead(*body3, 10),
2485 MockRead(ASYNC, 0, 11) // EOF
2488 DeterministicSocketData data(reads, arraysize(reads),
2489 writes, arraysize(writes));
2490 data.set_connect_data(connect_data);
2491 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2493 CreateDeterministicNetworkSession();
2495 base::WeakPtr<SpdySession> session =
2496 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2498 // Read the settings frame.
2499 data.RunFor(1);
2501 GURL url1(kDefaultURL);
2502 base::WeakPtr<SpdyStream> spdy_stream1 =
2503 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2504 session, url1, LOWEST, BoundNetLog());
2505 ASSERT_TRUE(spdy_stream1.get() != NULL);
2506 EXPECT_EQ(0u, spdy_stream1->stream_id());
2507 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2508 spdy_stream1->SetDelegate(&delegate1);
2510 TestCompletionCallback callback2;
2511 GURL url2(kDefaultURL);
2512 SpdyStreamRequest request2;
2513 ASSERT_EQ(ERR_IO_PENDING,
2514 request2.StartRequest(
2515 SPDY_REQUEST_RESPONSE_STREAM,
2516 session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2518 TestCompletionCallback callback3;
2519 GURL url3(kDefaultURL);
2520 SpdyStreamRequest request3;
2521 ASSERT_EQ(ERR_IO_PENDING,
2522 request3.StartRequest(
2523 SPDY_REQUEST_RESPONSE_STREAM,
2524 session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2526 EXPECT_EQ(0u, session->num_active_streams());
2527 EXPECT_EQ(1u, session->num_created_streams());
2528 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2530 scoped_ptr<SpdyHeaderBlock> headers(
2531 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2532 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2533 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2535 // Run until 1st stream is activated and then closed.
2536 EXPECT_EQ(0u, delegate1.stream_id());
2537 data.RunFor(4);
2538 EXPECT_EQ(NULL, spdy_stream1.get());
2539 EXPECT_EQ(1u, delegate1.stream_id());
2541 EXPECT_EQ(0u, session->num_active_streams());
2542 EXPECT_EQ(0u, session->num_created_streams());
2543 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2545 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2546 // create the 2nd stream.
2547 base::MessageLoop::current()->RunUntilIdle();
2549 EXPECT_EQ(0u, session->num_active_streams());
2550 EXPECT_EQ(1u, session->num_created_streams());
2551 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2553 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2554 test::StreamDelegateDoNothing delegate2(stream2);
2555 stream2->SetDelegate(&delegate2);
2556 scoped_ptr<SpdyHeaderBlock> headers2(
2557 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2558 stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2559 EXPECT_TRUE(stream2->HasUrlFromHeaders());
2561 // Run until 2nd stream is activated and then closed.
2562 EXPECT_EQ(0u, delegate2.stream_id());
2563 data.RunFor(3);
2564 EXPECT_EQ(NULL, stream2.get());
2565 EXPECT_EQ(3u, delegate2.stream_id());
2567 EXPECT_EQ(0u, session->num_active_streams());
2568 EXPECT_EQ(0u, session->num_created_streams());
2569 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2571 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2572 // create the 3rd stream.
2573 base::MessageLoop::current()->RunUntilIdle();
2575 EXPECT_EQ(0u, session->num_active_streams());
2576 EXPECT_EQ(1u, session->num_created_streams());
2577 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2579 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2580 test::StreamDelegateDoNothing delegate3(stream3);
2581 stream3->SetDelegate(&delegate3);
2582 scoped_ptr<SpdyHeaderBlock> headers3(
2583 spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2584 stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2585 EXPECT_TRUE(stream3->HasUrlFromHeaders());
2587 // Run until 2nd stream is activated and then closed.
2588 EXPECT_EQ(0u, delegate3.stream_id());
2589 data.RunFor(3);
2590 EXPECT_EQ(NULL, stream3.get());
2591 EXPECT_EQ(5u, delegate3.stream_id());
2593 EXPECT_EQ(0u, session->num_active_streams());
2594 EXPECT_EQ(0u, session->num_created_streams());
2595 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2597 data.RunFor(1);
2600 TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2601 session_deps_.host_resolver->set_synchronous_mode(true);
2603 MockRead reads[] = {
2604 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2607 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2608 MockConnect connect_data(SYNCHRONOUS, OK);
2610 data.set_connect_data(connect_data);
2611 session_deps_.socket_factory->AddSocketDataProvider(&data);
2613 CreateNetworkSession();
2615 base::WeakPtr<SpdySession> session =
2616 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2618 // Leave room for only one more stream to be created.
2619 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2620 base::WeakPtr<SpdyStream> spdy_stream =
2621 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2622 session, test_url_, MEDIUM, BoundNetLog());
2623 ASSERT_TRUE(spdy_stream != NULL);
2626 GURL url1(kDefaultURL);
2627 base::WeakPtr<SpdyStream> spdy_stream1 =
2628 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2629 session, url1, LOWEST, BoundNetLog());
2630 ASSERT_TRUE(spdy_stream1.get() != NULL);
2631 EXPECT_EQ(0u, spdy_stream1->stream_id());
2633 TestCompletionCallback callback2;
2634 GURL url2(kDefaultURL);
2635 SpdyStreamRequest request2;
2636 ASSERT_EQ(ERR_IO_PENDING,
2637 request2.StartRequest(
2638 SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2639 callback2.callback()));
2641 TestCompletionCallback callback3;
2642 GURL url3(kDefaultURL);
2643 SpdyStreamRequest request3;
2644 ASSERT_EQ(ERR_IO_PENDING,
2645 request3.StartRequest(
2646 SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2647 callback3.callback()));
2649 EXPECT_EQ(0u, session->num_active_streams());
2650 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2651 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2653 // Cancel the first stream; this will allow the second stream to be created.
2654 EXPECT_TRUE(spdy_stream1.get() != NULL);
2655 spdy_stream1->Cancel();
2656 EXPECT_EQ(NULL, spdy_stream1.get());
2658 EXPECT_EQ(OK, callback2.WaitForResult());
2659 EXPECT_EQ(0u, session->num_active_streams());
2660 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2661 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2663 // Cancel the second stream; this will allow the third stream to be created.
2664 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2665 spdy_stream2->Cancel();
2666 EXPECT_EQ(NULL, spdy_stream2.get());
2668 EXPECT_EQ(OK, callback3.WaitForResult());
2669 EXPECT_EQ(0u, session->num_active_streams());
2670 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2671 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2673 // Cancel the third stream.
2674 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2675 spdy_stream3->Cancel();
2676 EXPECT_EQ(NULL, spdy_stream3.get());
2677 EXPECT_EQ(0u, session->num_active_streams());
2678 EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
2679 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2682 // Test that SpdySession::DoReadLoop reads data from the socket
2683 // without yielding. This test makes 32k - 1 bytes of data available
2684 // on the socket for reading. It then verifies that it has read all
2685 // the available data without yielding.
2686 TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2687 MockConnect connect_data(SYNCHRONOUS, OK);
2688 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2690 scoped_ptr<SpdyFrame> req1(
2691 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2692 MockWrite writes[] = {
2693 CreateMockWrite(*req1, 0),
2696 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2697 // (-spdy_data_frame_size).
2698 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2699 const int kPayloadSize =
2700 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2701 TestDataStream test_stream;
2702 scoped_refptr<IOBuffer> payload(new IOBuffer(kPayloadSize));
2703 char* payload_data = payload->data();
2704 test_stream.GetBytes(payload_data, kPayloadSize);
2706 scoped_ptr<SpdyFrame> partial_data_frame(
2707 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2708 scoped_ptr<SpdyFrame> finish_data_frame(
2709 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2711 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2713 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2714 // bytes.
2715 MockRead reads[] = {
2716 CreateMockRead(*resp1, 1),
2717 CreateMockRead(*partial_data_frame, 2),
2718 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2719 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2720 CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2721 MockRead(ASYNC, 0, 6) // EOF
2724 // Create SpdySession and SpdyStream and send the request.
2725 DeterministicSocketData data(reads, arraysize(reads),
2726 writes, arraysize(writes));
2727 data.set_connect_data(connect_data);
2728 session_deps_.host_resolver->set_synchronous_mode(true);
2729 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2731 CreateDeterministicNetworkSession();
2733 base::WeakPtr<SpdySession> session =
2734 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2736 GURL url1(kDefaultURL);
2737 base::WeakPtr<SpdyStream> spdy_stream1 =
2738 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2739 session, url1, MEDIUM, BoundNetLog());
2740 ASSERT_TRUE(spdy_stream1.get() != NULL);
2741 EXPECT_EQ(0u, spdy_stream1->stream_id());
2742 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2743 spdy_stream1->SetDelegate(&delegate1);
2745 scoped_ptr<SpdyHeaderBlock> headers1(
2746 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2747 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2748 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2750 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2751 // post a task.
2752 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2754 // Run until 1st read.
2755 EXPECT_EQ(0u, delegate1.stream_id());
2756 data.RunFor(2);
2757 EXPECT_EQ(1u, delegate1.stream_id());
2758 EXPECT_EQ(0u, observer.executed_count());
2760 // Read all the data and verify SpdySession::DoReadLoop has not
2761 // posted a task.
2762 data.RunFor(4);
2763 EXPECT_EQ(NULL, spdy_stream1.get());
2765 // Verify task observer's executed_count is zero, which indicates DoRead read
2766 // all the available data.
2767 EXPECT_EQ(0u, observer.executed_count());
2768 EXPECT_TRUE(data.at_write_eof());
2769 EXPECT_TRUE(data.at_read_eof());
2772 // Test that SpdySession::DoReadLoop yields while reading the
2773 // data. This test makes 32k + 1 bytes of data available on the socket
2774 // for reading. It then verifies that DoRead has yielded even though
2775 // there is data available for it to read (i.e, socket()->Read didn't
2776 // return ERR_IO_PENDING during socket reads).
2777 TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2778 MockConnect connect_data(SYNCHRONOUS, OK);
2779 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2781 scoped_ptr<SpdyFrame> req1(
2782 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2783 MockWrite writes[] = {
2784 CreateMockWrite(*req1, 0),
2787 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2788 // (-spdy_data_frame_size).
2789 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2790 const int kPayloadSize =
2791 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2792 TestDataStream test_stream;
2793 scoped_refptr<IOBuffer> payload(new IOBuffer(kPayloadSize));
2794 char* payload_data = payload->data();
2795 test_stream.GetBytes(payload_data, kPayloadSize);
2797 scoped_ptr<SpdyFrame> partial_data_frame(
2798 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2799 scoped_ptr<SpdyFrame> finish_data_frame(
2800 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2802 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2804 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2805 MockRead reads[] = {
2806 CreateMockRead(*resp1, 1),
2807 CreateMockRead(*partial_data_frame, 2),
2808 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2809 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2810 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2811 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2812 MockRead(ASYNC, 0, 7) // EOF
2815 // Create SpdySession and SpdyStream and send the request.
2816 DeterministicSocketData data(reads, arraysize(reads),
2817 writes, arraysize(writes));
2818 data.set_connect_data(connect_data);
2819 session_deps_.host_resolver->set_synchronous_mode(true);
2820 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2822 CreateDeterministicNetworkSession();
2824 base::WeakPtr<SpdySession> session =
2825 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2827 GURL url1(kDefaultURL);
2828 base::WeakPtr<SpdyStream> spdy_stream1 =
2829 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2830 session, url1, MEDIUM, BoundNetLog());
2831 ASSERT_TRUE(spdy_stream1.get() != NULL);
2832 EXPECT_EQ(0u, spdy_stream1->stream_id());
2833 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2834 spdy_stream1->SetDelegate(&delegate1);
2836 scoped_ptr<SpdyHeaderBlock> headers1(
2837 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2838 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2839 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2841 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2842 // task.
2843 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2845 // Run until 1st read.
2846 EXPECT_EQ(0u, delegate1.stream_id());
2847 data.RunFor(2);
2848 EXPECT_EQ(1u, delegate1.stream_id());
2849 EXPECT_EQ(0u, observer.executed_count());
2851 // Read all the data and verify SpdySession::DoReadLoop has posted a
2852 // task.
2853 data.RunFor(6);
2854 EXPECT_EQ(NULL, spdy_stream1.get());
2856 // Verify task observer's executed_count is 1, which indicates DoRead has
2857 // posted only one task and thus yielded though there is data available for it
2858 // to read.
2859 EXPECT_EQ(1u, observer.executed_count());
2860 EXPECT_TRUE(data.at_write_eof());
2861 EXPECT_TRUE(data.at_read_eof());
2864 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2865 // + async, by doing the following MockReads.
2867 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2868 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2870 // The above reads 26K synchronously. Since that is less that 32K, we
2871 // will attempt to read again. However, that DoRead() will return
2872 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2873 // yield. When we come back, DoRead() will read the results from the
2874 // async read, and rest of the data synchronously.
2875 TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2876 MockConnect connect_data(SYNCHRONOUS, OK);
2877 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2879 scoped_ptr<SpdyFrame> req1(
2880 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2881 MockWrite writes[] = {
2882 CreateMockWrite(*req1, 0),
2885 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2886 // (-spdy_data_frame_size).
2887 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2888 TestDataStream test_stream;
2889 const int kEightKPayloadSize =
2890 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2891 scoped_refptr<IOBuffer> eightk_payload(new IOBuffer(kEightKPayloadSize));
2892 char* eightk_payload_data = eightk_payload->data();
2893 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2895 // Build buffer of 2k size.
2896 TestDataStream test_stream2;
2897 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2898 scoped_refptr<IOBuffer> twok_payload(new IOBuffer(kTwoKPayloadSize));
2899 char* twok_payload_data = twok_payload->data();
2900 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2902 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2903 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2904 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2905 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2906 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2907 1, "h", 1, DATA_FLAG_FIN));
2909 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2911 MockRead reads[] = {
2912 CreateMockRead(*resp1, 1),
2913 CreateMockRead(*eightk_data_frame, 2),
2914 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
2915 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2916 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
2917 CreateMockRead(*eightk_data_frame, 6, ASYNC),
2918 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
2919 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2920 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2921 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
2922 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
2923 MockRead(ASYNC, 0, 12) // EOF
2926 // Create SpdySession and SpdyStream and send the request.
2927 DeterministicSocketData data(reads, arraysize(reads),
2928 writes, arraysize(writes));
2929 data.set_connect_data(connect_data);
2930 session_deps_.host_resolver->set_synchronous_mode(true);
2931 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2933 CreateDeterministicNetworkSession();
2935 base::WeakPtr<SpdySession> session =
2936 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2938 GURL url1(kDefaultURL);
2939 base::WeakPtr<SpdyStream> spdy_stream1 =
2940 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2941 session, url1, MEDIUM, BoundNetLog());
2942 ASSERT_TRUE(spdy_stream1.get() != NULL);
2943 EXPECT_EQ(0u, spdy_stream1->stream_id());
2944 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2945 spdy_stream1->SetDelegate(&delegate1);
2947 scoped_ptr<SpdyHeaderBlock> headers1(
2948 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2949 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2950 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2952 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2953 // posting of tasks.
2954 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2956 // Run until 1st read.
2957 EXPECT_EQ(0u, delegate1.stream_id());
2958 data.RunFor(2);
2959 EXPECT_EQ(1u, delegate1.stream_id());
2960 EXPECT_EQ(0u, observer.executed_count());
2962 // Read all the data and verify SpdySession::DoReadLoop has posted a
2963 // task.
2964 data.RunFor(12);
2965 EXPECT_EQ(NULL, spdy_stream1.get());
2967 // Verify task observer's executed_count is 1, which indicates DoRead has
2968 // posted only one task and thus yielded though there is data available for
2969 // it to read.
2970 EXPECT_EQ(1u, observer.executed_count());
2971 EXPECT_TRUE(data.at_write_eof());
2972 EXPECT_TRUE(data.at_read_eof());
2975 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2976 // nothing blows up.
2977 TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
2978 MockConnect connect_data(SYNCHRONOUS, OK);
2979 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2981 scoped_ptr<SpdyFrame> req1(
2982 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2983 MockWrite writes[] = {
2984 CreateMockWrite(*req1, 0),
2987 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2988 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2989 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
2991 MockRead reads[] = {
2992 CreateMockRead(*resp1, 1),
2993 CreateMockRead(*body1, 2),
2994 CreateMockRead(*goaway, 3),
2997 // Create SpdySession and SpdyStream and send the request.
2998 DeterministicSocketData data(reads, arraysize(reads),
2999 writes, arraysize(writes));
3000 data.set_connect_data(connect_data);
3001 session_deps_.host_resolver->set_synchronous_mode(true);
3002 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3004 CreateDeterministicNetworkSession();
3006 base::WeakPtr<SpdySession> session =
3007 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3009 GURL url1(kDefaultURL);
3010 base::WeakPtr<SpdyStream> spdy_stream1 =
3011 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3012 session, url1, MEDIUM, BoundNetLog());
3013 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3014 spdy_stream1->SetDelegate(&delegate1);
3015 ASSERT_TRUE(spdy_stream1.get() != NULL);
3016 EXPECT_EQ(0u, spdy_stream1->stream_id());
3018 scoped_ptr<SpdyHeaderBlock> headers1(
3019 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3020 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
3021 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3023 // Run until 1st read.
3024 EXPECT_EQ(0u, spdy_stream1->stream_id());
3025 data.RunFor(1);
3026 EXPECT_EQ(1u, spdy_stream1->stream_id());
3028 // Run until GoAway.
3029 data.RunFor(3);
3030 EXPECT_EQ(NULL, spdy_stream1.get());
3031 EXPECT_TRUE(data.at_write_eof());
3032 EXPECT_TRUE(data.at_read_eof());
3033 EXPECT_TRUE(session == NULL);
3036 // Within this framework, a SpdySession should be initialized with
3037 // flow control disabled for protocol version 2, with flow control
3038 // enabled only for streams for protocol version 3, and with flow
3039 // control enabled for streams and sessions for higher versions.
3040 TEST_P(SpdySessionTest, ProtocolNegotiation) {
3041 session_deps_.host_resolver->set_synchronous_mode(true);
3043 MockConnect connect_data(SYNCHRONOUS, OK);
3044 MockRead reads[] = {
3045 MockRead(SYNCHRONOUS, 0, 0) // EOF
3047 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3048 data.set_connect_data(connect_data);
3049 session_deps_.socket_factory->AddSocketDataProvider(&data);
3051 CreateNetworkSession();
3052 base::WeakPtr<SpdySession> session =
3053 CreateFakeSpdySession(spdy_session_pool_, key_);
3055 EXPECT_EQ(spdy_util_.spdy_version(),
3056 session->buffered_spdy_framer_->protocol_version());
3057 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3058 session->flow_control_state());
3059 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3060 session->session_send_window_size_);
3061 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3062 session->session_recv_window_size_);
3063 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3066 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3067 // pointers to the idle session are currently held.
3068 TEST_P(SpdySessionTest, CloseOneIdleConnection) {
3069 ClientSocketPoolManager::set_max_sockets_per_group(
3070 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3071 ClientSocketPoolManager::set_max_sockets_per_pool(
3072 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3074 MockConnect connect_data(SYNCHRONOUS, OK);
3075 MockRead reads[] = {
3076 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3078 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3079 data.set_connect_data(connect_data);
3080 session_deps_.socket_factory->AddSocketDataProvider(&data);
3081 session_deps_.socket_factory->AddSocketDataProvider(&data);
3083 CreateNetworkSession();
3085 TransportClientSocketPool* pool =
3086 http_session_->GetTransportSocketPool(
3087 HttpNetworkSession::NORMAL_SOCKET_POOL);
3089 // Create an idle SPDY session.
3090 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3091 PRIVACY_MODE_DISABLED);
3092 base::WeakPtr<SpdySession> session1 =
3093 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3094 EXPECT_FALSE(pool->IsStalled());
3096 // Trying to create a new connection should cause the pool to be stalled, and
3097 // post a task asynchronously to try and close the session.
3098 TestCompletionCallback callback2;
3099 HostPortPair host_port2("2.com", 80);
3100 scoped_refptr<TransportSocketParams> params2(
3101 new TransportSocketParams(
3102 host_port2, false, false, OnHostResolutionCallback(),
3103 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3104 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3105 EXPECT_EQ(ERR_IO_PENDING,
3106 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3107 callback2.callback(), pool, BoundNetLog()));
3108 EXPECT_TRUE(pool->IsStalled());
3110 // The socket pool should close the connection asynchronously and establish a
3111 // new connection.
3112 EXPECT_EQ(OK, callback2.WaitForResult());
3113 EXPECT_FALSE(pool->IsStalled());
3114 EXPECT_TRUE(session1 == NULL);
3117 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3118 // pointers to the idle session are currently held, in the case the SPDY session
3119 // has an alias.
3120 TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
3121 ClientSocketPoolManager::set_max_sockets_per_group(
3122 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3123 ClientSocketPoolManager::set_max_sockets_per_pool(
3124 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3126 MockConnect connect_data(SYNCHRONOUS, OK);
3127 MockRead reads[] = {
3128 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3130 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3131 data.set_connect_data(connect_data);
3132 session_deps_.socket_factory->AddSocketDataProvider(&data);
3133 session_deps_.socket_factory->AddSocketDataProvider(&data);
3135 session_deps_.host_resolver->set_synchronous_mode(true);
3136 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3137 "1.com", "192.168.0.2", std::string());
3138 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3139 "2.com", "192.168.0.2", std::string());
3140 // Not strictly needed.
3141 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3142 "3.com", "192.168.0.3", std::string());
3144 CreateNetworkSession();
3146 TransportClientSocketPool* pool =
3147 http_session_->GetTransportSocketPool(
3148 HttpNetworkSession::NORMAL_SOCKET_POOL);
3150 // Create an idle SPDY session.
3151 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3152 PRIVACY_MODE_DISABLED);
3153 base::WeakPtr<SpdySession> session1 =
3154 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3155 EXPECT_FALSE(pool->IsStalled());
3157 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3158 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3159 PRIVACY_MODE_DISABLED);
3160 HostResolver::RequestInfo info(key2.host_port_pair());
3161 AddressList addresses;
3162 // Pre-populate the DNS cache, since a synchronous resolution is required in
3163 // order to create the alias.
3164 session_deps_.host_resolver->Resolve(info,
3165 DEFAULT_PRIORITY,
3166 &addresses,
3167 CompletionCallback(),
3168 NULL,
3169 BoundNetLog());
3170 // Get a session for |key2|, which should return the session created earlier.
3171 base::WeakPtr<SpdySession> session2 =
3172 spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3173 ASSERT_EQ(session1.get(), session2.get());
3174 EXPECT_FALSE(pool->IsStalled());
3176 // Trying to create a new connection should cause the pool to be stalled, and
3177 // post a task asynchronously to try and close the session.
3178 TestCompletionCallback callback3;
3179 HostPortPair host_port3("3.com", 80);
3180 scoped_refptr<TransportSocketParams> params3(
3181 new TransportSocketParams(
3182 host_port3, false, false, OnHostResolutionCallback(),
3183 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3184 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3185 EXPECT_EQ(ERR_IO_PENDING,
3186 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3187 callback3.callback(), pool, BoundNetLog()));
3188 EXPECT_TRUE(pool->IsStalled());
3190 // The socket pool should close the connection asynchronously and establish a
3191 // new connection.
3192 EXPECT_EQ(OK, callback3.WaitForResult());
3193 EXPECT_FALSE(pool->IsStalled());
3194 EXPECT_TRUE(session1 == NULL);
3195 EXPECT_TRUE(session2 == NULL);
3198 // Tests that when a SPDY session becomes idle, it closes itself if there is
3199 // a lower layer pool stalled on the per-pool socket limit.
3200 TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3201 ClientSocketPoolManager::set_max_sockets_per_group(
3202 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3203 ClientSocketPoolManager::set_max_sockets_per_pool(
3204 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3206 MockConnect connect_data(SYNCHRONOUS, OK);
3207 MockRead reads[] = {
3208 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3210 scoped_ptr<SpdyFrame> req1(
3211 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3212 scoped_ptr<SpdyFrame> cancel1(
3213 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3214 MockWrite writes[] = {
3215 CreateMockWrite(*req1, 1),
3216 CreateMockWrite(*cancel1, 1),
3218 StaticSocketDataProvider data(reads, arraysize(reads),
3219 writes, arraysize(writes));
3220 data.set_connect_data(connect_data);
3221 session_deps_.socket_factory->AddSocketDataProvider(&data);
3223 MockRead http_reads[] = {
3224 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3226 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
3227 NULL, 0);
3228 http_data.set_connect_data(connect_data);
3229 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3232 CreateNetworkSession();
3234 TransportClientSocketPool* pool =
3235 http_session_->GetTransportSocketPool(
3236 HttpNetworkSession::NORMAL_SOCKET_POOL);
3238 // Create a SPDY session.
3239 GURL url1(kDefaultURL);
3240 SpdySessionKey key1(HostPortPair(url1.host(), 80),
3241 ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3242 base::WeakPtr<SpdySession> session1 =
3243 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3244 EXPECT_FALSE(pool->IsStalled());
3246 // Create a stream using the session, and send a request.
3248 TestCompletionCallback callback1;
3249 base::WeakPtr<SpdyStream> spdy_stream1 =
3250 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3251 session1, url1, DEFAULT_PRIORITY,
3252 BoundNetLog());
3253 ASSERT_TRUE(spdy_stream1.get());
3254 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3255 spdy_stream1->SetDelegate(&delegate1);
3257 scoped_ptr<SpdyHeaderBlock> headers1(
3258 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3259 EXPECT_EQ(ERR_IO_PENDING,
3260 spdy_stream1->SendRequestHeaders(
3261 headers1.Pass(), NO_MORE_DATA_TO_SEND));
3262 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3264 base::MessageLoop::current()->RunUntilIdle();
3266 // Trying to create a new connection should cause the pool to be stalled, and
3267 // post a task asynchronously to try and close the session.
3268 TestCompletionCallback callback2;
3269 HostPortPair host_port2("2.com", 80);
3270 scoped_refptr<TransportSocketParams> params2(
3271 new TransportSocketParams(
3272 host_port2, false, false, OnHostResolutionCallback(),
3273 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3274 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3275 EXPECT_EQ(ERR_IO_PENDING,
3276 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3277 callback2.callback(), pool, BoundNetLog()));
3278 EXPECT_TRUE(pool->IsStalled());
3280 // Running the message loop should cause the socket pool to ask the SPDY
3281 // session to close an idle socket, but since the socket is in use, nothing
3282 // happens.
3283 base::RunLoop().RunUntilIdle();
3284 EXPECT_TRUE(pool->IsStalled());
3285 EXPECT_FALSE(callback2.have_result());
3287 // Cancelling the request should result in the session's socket being
3288 // closed, since the pool is stalled.
3289 ASSERT_TRUE(spdy_stream1.get());
3290 spdy_stream1->Cancel();
3291 base::RunLoop().RunUntilIdle();
3292 ASSERT_FALSE(pool->IsStalled());
3293 EXPECT_EQ(OK, callback2.WaitForResult());
3296 // Verify that SpdySessionKey and therefore SpdySession is different when
3297 // privacy mode is enabled or disabled.
3298 TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3299 CreateDeterministicNetworkSession();
3301 HostPortPair host_port_pair("www.example.org", 443);
3302 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3303 PRIVACY_MODE_ENABLED);
3304 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3305 PRIVACY_MODE_DISABLED);
3307 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3308 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3310 // Add SpdySession with PrivacyMode Enabled to the pool.
3311 base::WeakPtr<SpdySession> session_privacy_enabled =
3312 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3314 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3315 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3317 // Add SpdySession with PrivacyMode Disabled to the pool.
3318 base::WeakPtr<SpdySession> session_privacy_disabled =
3319 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3321 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3322 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3324 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3325 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3326 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3328 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3329 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3330 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3333 // Delegate that creates another stream when its stream is closed.
3334 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3335 public:
3336 StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3337 const base::WeakPtr<SpdySession>& session)
3338 : StreamDelegateDoNothing(stream),
3339 session_(session) {}
3341 ~StreamCreatingDelegate() override {}
3343 void OnClose(int status) override {
3344 GURL url(kDefaultURL);
3345 ignore_result(
3346 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3347 session_, url, MEDIUM, BoundNetLog()));
3350 private:
3351 const base::WeakPtr<SpdySession> session_;
3354 // Create another stream in response to a stream being reset. Nothing
3355 // should blow up. This is a regression test for
3356 // http://crbug.com/263690 .
3357 TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3358 session_deps_.host_resolver->set_synchronous_mode(true);
3360 MockConnect connect_data(SYNCHRONOUS, OK);
3362 scoped_ptr<SpdyFrame> req(
3363 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3364 MockWrite writes[] = {
3365 CreateMockWrite(*req, 0),
3368 scoped_ptr<SpdyFrame> rst(
3369 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3370 MockRead reads[] = {
3371 CreateMockRead(*rst, 1),
3372 MockRead(ASYNC, 0, 2) // EOF
3374 DeterministicSocketData data(reads, arraysize(reads),
3375 writes, arraysize(writes));
3376 data.set_connect_data(connect_data);
3377 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3379 CreateDeterministicNetworkSession();
3381 base::WeakPtr<SpdySession> session =
3382 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3384 GURL url(kDefaultURL);
3385 base::WeakPtr<SpdyStream> spdy_stream =
3386 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3387 session, url, MEDIUM, BoundNetLog());
3388 ASSERT_TRUE(spdy_stream.get() != NULL);
3389 EXPECT_EQ(0u, spdy_stream->stream_id());
3391 StreamCreatingDelegate delegate(spdy_stream, session);
3392 spdy_stream->SetDelegate(&delegate);
3394 scoped_ptr<SpdyHeaderBlock> headers(
3395 spdy_util_.ConstructGetHeaderBlock(url.spec()));
3396 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3397 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3399 EXPECT_EQ(0u, spdy_stream->stream_id());
3401 data.RunFor(1);
3403 EXPECT_EQ(1u, spdy_stream->stream_id());
3405 // Cause the stream to be reset, which should cause another stream
3406 // to be created.
3407 data.RunFor(1);
3409 EXPECT_EQ(NULL, spdy_stream.get());
3410 EXPECT_TRUE(delegate.StreamIsClosed());
3411 EXPECT_EQ(0u, session->num_active_streams());
3412 EXPECT_EQ(1u, session->num_created_streams());
3415 // The tests below are only for SPDY/3 and above.
3417 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3418 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3419 // gets sent.
3420 SettingsMap new_settings;
3421 int32 window_size = 1;
3422 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3423 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3425 // Set up the socket so we read a SETTINGS frame that sets
3426 // INITIAL_WINDOW_SIZE.
3427 MockConnect connect_data(SYNCHRONOUS, OK);
3428 scoped_ptr<SpdyFrame> settings_frame(
3429 spdy_util_.ConstructSpdySettings(new_settings));
3430 MockRead reads[] = {
3431 CreateMockRead(*settings_frame, 0),
3432 MockRead(ASYNC, 0, 1) // EOF
3435 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3436 MockWrite writes[] = {
3437 CreateMockWrite(*settings_ack, 2),
3440 session_deps_.host_resolver->set_synchronous_mode(true);
3442 DeterministicSocketData data(reads, arraysize(reads),
3443 writes, arraysize(writes));
3444 data.set_connect_data(connect_data);
3445 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3447 CreateDeterministicNetworkSession();
3449 base::WeakPtr<SpdySession> session =
3450 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3451 base::WeakPtr<SpdyStream> spdy_stream1 =
3452 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3453 session, test_url_, MEDIUM, BoundNetLog());
3454 ASSERT_TRUE(spdy_stream1.get() != NULL);
3455 TestCompletionCallback callback1;
3456 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3458 data.RunFor(1); // Process the SETTINGS frame, but not the EOF
3459 base::MessageLoop::current()->RunUntilIdle();
3460 EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3461 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3463 // Release the first one, this will allow the second to be created.
3464 spdy_stream1->Cancel();
3465 EXPECT_EQ(NULL, spdy_stream1.get());
3467 base::WeakPtr<SpdyStream> spdy_stream2 =
3468 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3469 session, test_url_, MEDIUM, BoundNetLog());
3470 ASSERT_TRUE(spdy_stream2.get() != NULL);
3471 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3472 spdy_stream2->Cancel();
3473 EXPECT_EQ(NULL, spdy_stream2.get());
3476 // The tests below are only for SPDY/3.1 and above.
3478 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3479 // adjust the session receive window size for SPDY 3.1 and higher. In
3480 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3481 // sending a WINDOW_UPDATE frame for a large enough delta.
3482 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3483 if (GetParam() < kProtoSPDY31)
3484 return;
3486 session_deps_.host_resolver->set_synchronous_mode(true);
3488 const int32 initial_window_size =
3489 SpdySession::GetDefaultInitialWindowSize(GetParam());
3490 const int32 delta_window_size = 100;
3492 MockConnect connect_data(SYNCHRONOUS, OK);
3493 MockRead reads[] = {
3494 MockRead(ASYNC, 0, 1) // EOF
3496 scoped_ptr<SpdyFrame> window_update(spdy_util_.ConstructSpdyWindowUpdate(
3497 kSessionFlowControlStreamId, initial_window_size + delta_window_size));
3498 MockWrite writes[] = {
3499 CreateMockWrite(*window_update, 0),
3501 DeterministicSocketData data(reads, arraysize(reads),
3502 writes, arraysize(writes));
3503 data.set_connect_data(connect_data);
3504 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3506 CreateDeterministicNetworkSession();
3507 base::WeakPtr<SpdySession> session =
3508 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3509 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3510 session->flow_control_state());
3512 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3513 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3515 session->IncreaseRecvWindowSize(delta_window_size);
3516 EXPECT_EQ(initial_window_size + delta_window_size,
3517 session->session_recv_window_size_);
3518 EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3520 // Should trigger sending a WINDOW_UPDATE frame.
3521 session->IncreaseRecvWindowSize(initial_window_size);
3522 EXPECT_EQ(initial_window_size + delta_window_size + initial_window_size,
3523 session->session_recv_window_size_);
3524 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3526 data.RunFor(1);
3528 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3529 session->in_io_loop_ = true;
3530 session->DecreaseRecvWindowSize(initial_window_size + delta_window_size +
3531 initial_window_size);
3532 session->in_io_loop_ = false;
3533 EXPECT_EQ(0, session->session_recv_window_size_);
3534 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3537 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3538 // adjust the session send window size when the "enable_spdy_31" flag
3539 // is set.
3540 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3541 if (GetParam() < kProtoSPDY31)
3542 return;
3544 session_deps_.host_resolver->set_synchronous_mode(true);
3546 MockConnect connect_data(SYNCHRONOUS, OK);
3547 MockRead reads[] = {
3548 MockRead(SYNCHRONOUS, 0, 0) // EOF
3550 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3551 data.set_connect_data(connect_data);
3552 session_deps_.socket_factory->AddSocketDataProvider(&data);
3554 CreateNetworkSession();
3555 base::WeakPtr<SpdySession> session =
3556 CreateFakeSpdySession(spdy_session_pool_, key_);
3557 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3558 session->flow_control_state());
3560 const int32 initial_window_size =
3561 SpdySession::GetDefaultInitialWindowSize(GetParam());
3562 const int32 delta_window_size = 100;
3564 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3566 session->IncreaseSendWindowSize(delta_window_size);
3567 EXPECT_EQ(initial_window_size + delta_window_size,
3568 session->session_send_window_size_);
3570 session->DecreaseSendWindowSize(delta_window_size);
3571 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3574 // Incoming data for an inactive stream should not cause the session
3575 // receive window size to decrease, but it should cause the unacked
3576 // bytes to increase.
3577 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3578 if (GetParam() < kProtoSPDY31)
3579 return;
3581 session_deps_.host_resolver->set_synchronous_mode(true);
3583 MockConnect connect_data(SYNCHRONOUS, OK);
3584 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3585 MockRead reads[] = {
3586 CreateMockRead(*resp, 0),
3587 MockRead(ASYNC, 0, 1) // EOF
3589 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3590 data.set_connect_data(connect_data);
3591 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3593 CreateDeterministicNetworkSession();
3594 base::WeakPtr<SpdySession> session =
3595 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3596 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3597 session->flow_control_state());
3599 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3600 session->session_recv_window_size_);
3601 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3603 data.RunFor(1);
3605 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3606 session->session_recv_window_size_);
3607 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3609 data.RunFor(1);
3612 // The frame header is not included in flow control, but frame payload
3613 // (including optional pad length and padding) is.
3614 TEST_P(SpdySessionTest, SessionFlowControlPadding) {
3615 // Padding only exists in HTTP/2.
3616 if (GetParam() < kProtoSPDY4MinimumVersion)
3617 return;
3619 session_deps_.host_resolver->set_synchronous_mode(true);
3621 const int padding_length = 42;
3622 MockConnect connect_data(SYNCHRONOUS, OK);
3623 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(
3624 1, kUploadData, kUploadDataSize, false, padding_length));
3625 MockRead reads[] = {
3626 CreateMockRead(*resp, 0), MockRead(ASYNC, 0, 1) // EOF
3628 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3629 data.set_connect_data(connect_data);
3630 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3632 CreateDeterministicNetworkSession();
3633 base::WeakPtr<SpdySession> session =
3634 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3635 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3636 session->flow_control_state());
3638 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3639 session->session_recv_window_size_);
3640 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3642 data.RunFor(1);
3644 EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetParam()),
3645 session->session_recv_window_size_);
3646 EXPECT_EQ(kUploadDataSize + padding_length,
3647 session->session_unacked_recv_window_bytes_);
3649 data.RunFor(1);
3652 // Peer sends more data than stream level receiving flow control window.
3653 TEST_P(SpdySessionTest, StreamFlowControlTooMuchData) {
3654 const int32 stream_max_recv_window_size = 1024;
3655 const int32 data_frame_size = 2 * stream_max_recv_window_size;
3657 scoped_ptr<SpdyFrame> req(
3658 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3659 MockWrite writes[] = {
3660 CreateMockWrite(*req, 0),
3663 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3664 const std::string payload(data_frame_size, 'a');
3665 scoped_ptr<SpdyFrame> data_frame(spdy_util_.ConstructSpdyBodyFrame(
3666 1, payload.data(), data_frame_size, false));
3667 MockRead reads[] = {
3668 CreateMockRead(*resp, 1),
3669 CreateMockRead(*data_frame, 2),
3670 MockRead(ASYNC, 0, 3),
3673 DeterministicSocketData data(reads, arraysize(reads), writes,
3674 arraysize(writes));
3675 data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
3676 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3677 CreateDeterministicNetworkSession();
3679 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
3680 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
3681 base::WeakPtr<SpdySession> session =
3682 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3683 EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
3685 GURL url(kDefaultURL);
3686 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
3687 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
3688 EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size());
3690 test::StreamDelegateDoNothing delegate(spdy_stream);
3691 spdy_stream->SetDelegate(&delegate);
3693 scoped_ptr<SpdyHeaderBlock> headers(
3694 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
3695 EXPECT_EQ(ERR_IO_PENDING, spdy_stream->SendRequestHeaders(
3696 headers.Pass(), NO_MORE_DATA_TO_SEND));
3698 // Request and response.
3699 data.RunFor(2);
3700 EXPECT_EQ(1u, spdy_stream->stream_id());
3702 // Too large data frame causes flow control error, should close stream.
3703 data.RunFor(1);
3704 EXPECT_EQ(nullptr, spdy_stream.get());
3707 // A delegate that drops any received data.
3708 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3709 public:
3710 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3711 base::StringPiece data)
3712 : StreamDelegateSendImmediate(stream, data) {}
3714 ~DropReceivedDataDelegate() override {}
3716 // Drop any received data.
3717 void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override {}
3720 // Send data back and forth but use a delegate that drops its received
3721 // data. The receive window should still increase to its original
3722 // value, i.e. we shouldn't "leak" receive window bytes.
3723 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3724 if (GetParam() < kProtoSPDY31)
3725 return;
3727 const char kStreamUrl[] = "http://www.example.org/";
3729 const int32 msg_data_size = 100;
3730 const std::string msg_data(msg_data_size, 'a');
3732 MockConnect connect_data(SYNCHRONOUS, OK);
3734 scoped_ptr<SpdyFrame> req(
3735 spdy_util_.ConstructSpdyPost(
3736 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3737 scoped_ptr<SpdyFrame> msg(
3738 spdy_util_.ConstructSpdyBodyFrame(
3739 1, msg_data.data(), msg_data_size, false));
3740 MockWrite writes[] = {
3741 CreateMockWrite(*req, 0),
3742 CreateMockWrite(*msg, 2),
3745 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3746 scoped_ptr<SpdyFrame> echo(
3747 spdy_util_.ConstructSpdyBodyFrame(
3748 1, msg_data.data(), msg_data_size, false));
3749 scoped_ptr<SpdyFrame> window_update(
3750 spdy_util_.ConstructSpdyWindowUpdate(
3751 kSessionFlowControlStreamId, msg_data_size));
3752 MockRead reads[] = {
3753 CreateMockRead(*resp, 1),
3754 CreateMockRead(*echo, 3),
3755 MockRead(ASYNC, 0, 4) // EOF
3758 // Create SpdySession and SpdyStream and send the request.
3759 DeterministicSocketData data(reads, arraysize(reads),
3760 writes, arraysize(writes));
3761 data.set_connect_data(connect_data);
3762 session_deps_.host_resolver->set_synchronous_mode(true);
3763 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3765 CreateDeterministicNetworkSession();
3767 base::WeakPtr<SpdySession> session =
3768 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3770 GURL url(kStreamUrl);
3771 base::WeakPtr<SpdyStream> stream =
3772 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3773 session, url, MEDIUM, BoundNetLog());
3774 ASSERT_TRUE(stream.get() != NULL);
3775 EXPECT_EQ(0u, stream->stream_id());
3777 DropReceivedDataDelegate delegate(stream, msg_data);
3778 stream->SetDelegate(&delegate);
3780 scoped_ptr<SpdyHeaderBlock> headers(
3781 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3782 EXPECT_EQ(ERR_IO_PENDING,
3783 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3784 EXPECT_TRUE(stream->HasUrlFromHeaders());
3786 const int32 initial_window_size =
3787 SpdySession::GetDefaultInitialWindowSize(GetParam());
3788 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3789 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3791 data.RunFor(4);
3793 EXPECT_TRUE(data.at_write_eof());
3794 EXPECT_TRUE(data.at_read_eof());
3796 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3797 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3799 stream->Close();
3800 EXPECT_EQ(NULL, stream.get());
3802 EXPECT_EQ(OK, delegate.WaitForClose());
3804 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3805 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3808 // Send data back and forth but close the stream before its data frame
3809 // can be written to the socket. The send window should then increase
3810 // to its original value, i.e. we shouldn't "leak" send window bytes.
3811 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3812 if (GetParam() < kProtoSPDY31)
3813 return;
3815 const char kStreamUrl[] = "http://www.example.org/";
3817 const int32 msg_data_size = 100;
3818 const std::string msg_data(msg_data_size, 'a');
3820 MockConnect connect_data(SYNCHRONOUS, OK);
3822 scoped_ptr<SpdyFrame> req(
3823 spdy_util_.ConstructSpdyPost(
3824 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3825 MockWrite writes[] = {
3826 CreateMockWrite(*req, 0),
3829 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3830 MockRead reads[] = {
3831 CreateMockRead(*resp, 1),
3832 MockRead(ASYNC, 0, 2) // EOF
3835 // Create SpdySession and SpdyStream and send the request.
3836 DeterministicSocketData data(reads, arraysize(reads),
3837 writes, arraysize(writes));
3838 data.set_connect_data(connect_data);
3839 session_deps_.host_resolver->set_synchronous_mode(true);
3840 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3842 CreateDeterministicNetworkSession();
3844 base::WeakPtr<SpdySession> session =
3845 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3847 GURL url(kStreamUrl);
3848 base::WeakPtr<SpdyStream> stream =
3849 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3850 session, url, MEDIUM, BoundNetLog());
3851 ASSERT_TRUE(stream.get() != NULL);
3852 EXPECT_EQ(0u, stream->stream_id());
3854 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3855 stream->SetDelegate(&delegate);
3857 scoped_ptr<SpdyHeaderBlock> headers(
3858 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3859 EXPECT_EQ(ERR_IO_PENDING,
3860 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3861 EXPECT_TRUE(stream->HasUrlFromHeaders());
3863 const int32 initial_window_size =
3864 SpdySession::GetDefaultInitialWindowSize(GetParam());
3865 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3867 data.RunFor(1);
3869 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3871 data.RunFor(1);
3873 EXPECT_TRUE(data.at_write_eof());
3874 EXPECT_TRUE(data.at_read_eof());
3876 EXPECT_EQ(initial_window_size - msg_data_size,
3877 session->session_send_window_size_);
3879 // Closing the stream should increase the session's send window.
3880 stream->Close();
3881 EXPECT_EQ(NULL, stream.get());
3883 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3885 EXPECT_EQ(OK, delegate.WaitForClose());
3888 // Send data back and forth; the send and receive windows should
3889 // change appropriately.
3890 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
3891 if (GetParam() < kProtoSPDY31)
3892 return;
3894 const char kStreamUrl[] = "http://www.example.org/";
3896 const int32 msg_data_size = 100;
3897 const std::string msg_data(msg_data_size, 'a');
3899 MockConnect connect_data(SYNCHRONOUS, OK);
3901 scoped_ptr<SpdyFrame> req(
3902 spdy_util_.ConstructSpdyPost(
3903 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3904 scoped_ptr<SpdyFrame> msg(
3905 spdy_util_.ConstructSpdyBodyFrame(
3906 1, msg_data.data(), msg_data_size, false));
3907 MockWrite writes[] = {
3908 CreateMockWrite(*req, 0),
3909 CreateMockWrite(*msg, 2),
3912 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3913 scoped_ptr<SpdyFrame> echo(
3914 spdy_util_.ConstructSpdyBodyFrame(
3915 1, msg_data.data(), msg_data_size, false));
3916 scoped_ptr<SpdyFrame> window_update(
3917 spdy_util_.ConstructSpdyWindowUpdate(
3918 kSessionFlowControlStreamId, msg_data_size));
3919 MockRead reads[] = {
3920 CreateMockRead(*resp, 1),
3921 CreateMockRead(*echo, 3),
3922 CreateMockRead(*window_update, 4),
3923 MockRead(ASYNC, 0, 5) // EOF
3926 // Create SpdySession and SpdyStream and send the request.
3927 DeterministicSocketData data(reads, arraysize(reads),
3928 writes, arraysize(writes));
3929 data.set_connect_data(connect_data);
3930 session_deps_.host_resolver->set_synchronous_mode(true);
3931 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3933 CreateDeterministicNetworkSession();
3935 base::WeakPtr<SpdySession> session =
3936 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3938 GURL url(kStreamUrl);
3939 base::WeakPtr<SpdyStream> stream =
3940 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3941 session, url, MEDIUM, BoundNetLog());
3942 ASSERT_TRUE(stream.get() != NULL);
3943 EXPECT_EQ(0u, stream->stream_id());
3945 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3946 stream->SetDelegate(&delegate);
3948 scoped_ptr<SpdyHeaderBlock> headers(
3949 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3950 EXPECT_EQ(ERR_IO_PENDING,
3951 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3952 EXPECT_TRUE(stream->HasUrlFromHeaders());
3954 const int32 initial_window_size =
3955 SpdySession::GetDefaultInitialWindowSize(GetParam());
3956 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3957 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3958 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3960 data.RunFor(1);
3962 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3963 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3964 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3966 data.RunFor(1);
3968 EXPECT_EQ(initial_window_size - msg_data_size,
3969 session->session_send_window_size_);
3970 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3971 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3973 data.RunFor(1);
3975 EXPECT_EQ(initial_window_size - msg_data_size,
3976 session->session_send_window_size_);
3977 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
3978 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3980 data.RunFor(1);
3982 EXPECT_EQ(initial_window_size - msg_data_size,
3983 session->session_send_window_size_);
3984 EXPECT_EQ(initial_window_size - msg_data_size,
3985 session->session_recv_window_size_);
3986 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3988 data.RunFor(1);
3990 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
3991 EXPECT_EQ(initial_window_size - msg_data_size,
3992 session->session_recv_window_size_);
3993 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3995 EXPECT_TRUE(data.at_write_eof());
3996 EXPECT_TRUE(data.at_read_eof());
3998 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
4000 // Draining the delegate's read queue should increase the session's
4001 // receive window.
4002 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
4003 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
4004 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
4006 stream->Close();
4007 EXPECT_EQ(NULL, stream.get());
4009 EXPECT_EQ(OK, delegate.WaitForClose());
4011 EXPECT_EQ(initial_window_size, session->session_send_window_size_);
4012 EXPECT_EQ(initial_window_size, session->session_recv_window_size_);
4013 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
4016 // Given a stall function and an unstall function, runs a test to make
4017 // sure that a stream resumes after unstall.
4018 void SpdySessionTest::RunResumeAfterUnstallTest(
4019 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
4020 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
4021 unstall_function) {
4022 const char kStreamUrl[] = "http://www.example.org/";
4023 GURL url(kStreamUrl);
4025 session_deps_.host_resolver->set_synchronous_mode(true);
4027 scoped_ptr<SpdyFrame> req(
4028 spdy_util_.ConstructSpdyPost(
4029 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4030 scoped_ptr<SpdyFrame> body(
4031 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4032 MockWrite writes[] = {
4033 CreateMockWrite(*req, 0),
4034 CreateMockWrite(*body, 1),
4037 scoped_ptr<SpdyFrame> resp(
4038 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4039 scoped_ptr<SpdyFrame> echo(
4040 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4041 MockRead reads[] = {
4042 CreateMockRead(*resp, 2),
4043 MockRead(ASYNC, 0, 0, 3), // EOF
4046 DeterministicSocketData data(reads, arraysize(reads),
4047 writes, arraysize(writes));
4048 MockConnect connect_data(SYNCHRONOUS, OK);
4049 data.set_connect_data(connect_data);
4051 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4053 CreateDeterministicNetworkSession();
4054 base::WeakPtr<SpdySession> session =
4055 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4056 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4057 session->flow_control_state());
4059 base::WeakPtr<SpdyStream> stream =
4060 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4061 session, url, LOWEST, BoundNetLog());
4062 ASSERT_TRUE(stream.get() != NULL);
4064 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
4065 stream->SetDelegate(&delegate);
4067 EXPECT_FALSE(stream->HasUrlFromHeaders());
4068 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4070 scoped_ptr<SpdyHeaderBlock> headers(
4071 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4072 EXPECT_EQ(ERR_IO_PENDING,
4073 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4074 EXPECT_TRUE(stream->HasUrlFromHeaders());
4075 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
4077 stall_function.Run(session.get(), stream.get());
4079 data.RunFor(1);
4081 EXPECT_TRUE(stream->send_stalled_by_flow_control());
4083 unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
4085 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4087 data.RunFor(3);
4089 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
4091 EXPECT_TRUE(delegate.send_headers_completed());
4092 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
4093 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
4094 EXPECT_TRUE(data.at_write_eof());
4097 // Run the resume-after-unstall test with all possible stall and
4098 // unstall sequences.
4100 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
4101 if (GetParam() < kProtoSPDY31)
4102 return;
4104 RunResumeAfterUnstallTest(
4105 base::Bind(&SpdySessionTest::StallSessionOnly,
4106 base::Unretained(this)),
4107 base::Bind(&SpdySessionTest::UnstallSessionOnly,
4108 base::Unretained(this)));
4111 // Equivalent to
4112 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4113 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
4114 if (GetParam() < kProtoSPDY31)
4115 return;
4117 RunResumeAfterUnstallTest(
4118 base::Bind(&SpdySessionTest::StallStreamOnly,
4119 base::Unretained(this)),
4120 base::Bind(&SpdySessionTest::UnstallStreamOnly,
4121 base::Unretained(this)));
4124 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4125 if (GetParam() < kProtoSPDY31)
4126 return;
4128 RunResumeAfterUnstallTest(
4129 base::Bind(&SpdySessionTest::StallSessionStream,
4130 base::Unretained(this)),
4131 base::Bind(&SpdySessionTest::UnstallSessionStream,
4132 base::Unretained(this)));
4135 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4136 if (GetParam() < kProtoSPDY31)
4137 return;
4139 RunResumeAfterUnstallTest(
4140 base::Bind(&SpdySessionTest::StallStreamSession,
4141 base::Unretained(this)),
4142 base::Bind(&SpdySessionTest::UnstallSessionStream,
4143 base::Unretained(this)));
4146 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4147 if (GetParam() < kProtoSPDY31)
4148 return;
4150 RunResumeAfterUnstallTest(
4151 base::Bind(&SpdySessionTest::StallStreamSession,
4152 base::Unretained(this)),
4153 base::Bind(&SpdySessionTest::UnstallStreamSession,
4154 base::Unretained(this)));
4157 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4158 if (GetParam() < kProtoSPDY31)
4159 return;
4161 RunResumeAfterUnstallTest(
4162 base::Bind(&SpdySessionTest::StallSessionStream,
4163 base::Unretained(this)),
4164 base::Bind(&SpdySessionTest::UnstallStreamSession,
4165 base::Unretained(this)));
4168 // Cause a stall by reducing the flow control send window to 0. The
4169 // streams should resume in priority order when that window is then
4170 // increased.
4171 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4172 if (GetParam() < kProtoSPDY31)
4173 return;
4175 const char kStreamUrl[] = "http://www.example.org/";
4176 GURL url(kStreamUrl);
4178 session_deps_.host_resolver->set_synchronous_mode(true);
4180 scoped_ptr<SpdyFrame> req1(
4181 spdy_util_.ConstructSpdyPost(
4182 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4183 scoped_ptr<SpdyFrame> req2(
4184 spdy_util_.ConstructSpdyPost(
4185 kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
4186 scoped_ptr<SpdyFrame> body1(
4187 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4188 scoped_ptr<SpdyFrame> body2(
4189 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4190 MockWrite writes[] = {
4191 CreateMockWrite(*req1, 0),
4192 CreateMockWrite(*req2, 1),
4193 CreateMockWrite(*body2, 2),
4194 CreateMockWrite(*body1, 3),
4197 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4198 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4199 MockRead reads[] = {
4200 CreateMockRead(*resp1, 4),
4201 CreateMockRead(*resp2, 5),
4202 MockRead(ASYNC, 0, 0, 6), // EOF
4205 DeterministicSocketData data(reads, arraysize(reads),
4206 writes, arraysize(writes));
4207 MockConnect connect_data(SYNCHRONOUS, OK);
4208 data.set_connect_data(connect_data);
4210 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4212 CreateDeterministicNetworkSession();
4213 base::WeakPtr<SpdySession> session =
4214 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4215 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4216 session->flow_control_state());
4218 base::WeakPtr<SpdyStream> stream1 =
4219 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4220 session, url, LOWEST, BoundNetLog());
4221 ASSERT_TRUE(stream1.get() != NULL);
4223 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4224 stream1->SetDelegate(&delegate1);
4226 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4228 base::WeakPtr<SpdyStream> stream2 =
4229 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4230 session, url, MEDIUM, BoundNetLog());
4231 ASSERT_TRUE(stream2.get() != NULL);
4233 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4234 stream2->SetDelegate(&delegate2);
4236 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4238 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4239 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4241 StallSessionSend(session.get());
4243 scoped_ptr<SpdyHeaderBlock> headers1(
4244 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4245 EXPECT_EQ(ERR_IO_PENDING,
4246 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4247 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4248 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4250 data.RunFor(1);
4251 EXPECT_EQ(1u, stream1->stream_id());
4252 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4254 scoped_ptr<SpdyHeaderBlock> headers2(
4255 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4256 EXPECT_EQ(ERR_IO_PENDING,
4257 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4258 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4259 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4261 data.RunFor(1);
4262 EXPECT_EQ(3u, stream2->stream_id());
4263 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4265 // This should unstall only stream2.
4266 UnstallSessionSend(session.get(), kBodyDataSize);
4268 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4269 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4271 data.RunFor(1);
4273 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4274 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4276 // This should then unstall stream1.
4277 UnstallSessionSend(session.get(), kBodyDataSize);
4279 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4280 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4282 data.RunFor(4);
4284 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4285 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4287 EXPECT_TRUE(delegate1.send_headers_completed());
4288 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4289 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4291 EXPECT_TRUE(delegate2.send_headers_completed());
4292 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4293 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4295 EXPECT_TRUE(data.at_write_eof());
4298 // Delegate that closes a given stream after sending its body.
4299 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4300 public:
4301 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4302 base::StringPiece data)
4303 : StreamDelegateWithBody(stream, data) {}
4305 ~StreamClosingDelegate() override {}
4307 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4308 stream_to_close_ = stream_to_close;
4311 void OnDataSent() override {
4312 test::StreamDelegateWithBody::OnDataSent();
4313 if (stream_to_close_.get()) {
4314 stream_to_close_->Close();
4315 EXPECT_EQ(NULL, stream_to_close_.get());
4319 private:
4320 base::WeakPtr<SpdyStream> stream_to_close_;
4323 // Cause a stall by reducing the flow control send window to
4324 // 0. Unstalling the session should properly handle deleted streams.
4325 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4326 if (GetParam() < kProtoSPDY31)
4327 return;
4329 const char kStreamUrl[] = "http://www.example.org/";
4330 GURL url(kStreamUrl);
4332 session_deps_.host_resolver->set_synchronous_mode(true);
4334 scoped_ptr<SpdyFrame> req1(
4335 spdy_util_.ConstructSpdyPost(
4336 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4337 scoped_ptr<SpdyFrame> req2(
4338 spdy_util_.ConstructSpdyPost(
4339 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4340 scoped_ptr<SpdyFrame> req3(
4341 spdy_util_.ConstructSpdyPost(
4342 kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
4343 scoped_ptr<SpdyFrame> body2(
4344 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4345 MockWrite writes[] = {
4346 CreateMockWrite(*req1, 0),
4347 CreateMockWrite(*req2, 1),
4348 CreateMockWrite(*req3, 2),
4349 CreateMockWrite(*body2, 3),
4352 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4353 MockRead reads[] = {
4354 CreateMockRead(*resp2, 4),
4355 MockRead(ASYNC, 0, 0, 5), // EOF
4358 DeterministicSocketData data(reads, arraysize(reads),
4359 writes, arraysize(writes));
4360 MockConnect connect_data(SYNCHRONOUS, OK);
4361 data.set_connect_data(connect_data);
4363 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4365 CreateDeterministicNetworkSession();
4366 base::WeakPtr<SpdySession> session =
4367 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4368 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4369 session->flow_control_state());
4371 base::WeakPtr<SpdyStream> stream1 =
4372 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4373 session, url, LOWEST, BoundNetLog());
4374 ASSERT_TRUE(stream1.get() != NULL);
4376 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4377 stream1->SetDelegate(&delegate1);
4379 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4381 base::WeakPtr<SpdyStream> stream2 =
4382 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4383 session, url, LOWEST, BoundNetLog());
4384 ASSERT_TRUE(stream2.get() != NULL);
4386 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4387 stream2->SetDelegate(&delegate2);
4389 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4391 base::WeakPtr<SpdyStream> stream3 =
4392 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4393 session, url, LOWEST, BoundNetLog());
4394 ASSERT_TRUE(stream3.get() != NULL);
4396 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4397 stream3->SetDelegate(&delegate3);
4399 EXPECT_FALSE(stream3->HasUrlFromHeaders());
4401 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4402 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4403 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4405 StallSessionSend(session.get());
4407 scoped_ptr<SpdyHeaderBlock> headers1(
4408 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4409 EXPECT_EQ(ERR_IO_PENDING,
4410 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4411 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4412 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4414 data.RunFor(1);
4415 EXPECT_EQ(1u, stream1->stream_id());
4416 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4418 scoped_ptr<SpdyHeaderBlock> headers2(
4419 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4420 EXPECT_EQ(ERR_IO_PENDING,
4421 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4422 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4423 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4425 data.RunFor(1);
4426 EXPECT_EQ(3u, stream2->stream_id());
4427 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4429 scoped_ptr<SpdyHeaderBlock> headers3(
4430 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4431 EXPECT_EQ(ERR_IO_PENDING,
4432 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4433 EXPECT_TRUE(stream3->HasUrlFromHeaders());
4434 EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4436 data.RunFor(1);
4437 EXPECT_EQ(5u, stream3->stream_id());
4438 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4440 SpdyStreamId stream_id1 = stream1->stream_id();
4441 SpdyStreamId stream_id2 = stream2->stream_id();
4442 SpdyStreamId stream_id3 = stream3->stream_id();
4444 // Close stream1 preemptively.
4445 session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4446 EXPECT_EQ(NULL, stream1.get());
4448 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4449 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4450 EXPECT_TRUE(session->IsStreamActive(stream_id3));
4452 // Unstall stream2, which should then close stream3.
4453 delegate2.set_stream_to_close(stream3);
4454 UnstallSessionSend(session.get(), kBodyDataSize);
4456 data.RunFor(1);
4457 EXPECT_EQ(NULL, stream3.get());
4459 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4460 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4461 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4462 EXPECT_FALSE(session->IsStreamActive(stream_id3));
4464 data.RunFor(2);
4465 EXPECT_EQ(NULL, stream2.get());
4467 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4468 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4469 EXPECT_EQ(OK, delegate3.WaitForClose());
4471 EXPECT_TRUE(delegate1.send_headers_completed());
4472 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4474 EXPECT_TRUE(delegate2.send_headers_completed());
4475 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4476 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4478 EXPECT_TRUE(delegate3.send_headers_completed());
4479 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4481 EXPECT_TRUE(data.at_write_eof());
4484 // Cause a stall by reducing the flow control send window to
4485 // 0. Unstalling the session should properly handle the session itself
4486 // being closed.
4487 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4488 if (GetParam() < kProtoSPDY31)
4489 return;
4491 const char kStreamUrl[] = "http://www.example.org/";
4492 GURL url(kStreamUrl);
4494 session_deps_.host_resolver->set_synchronous_mode(true);
4496 scoped_ptr<SpdyFrame> req1(
4497 spdy_util_.ConstructSpdyPost(
4498 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4499 scoped_ptr<SpdyFrame> req2(
4500 spdy_util_.ConstructSpdyPost(
4501 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4502 scoped_ptr<SpdyFrame> body1(
4503 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4504 MockWrite writes[] = {
4505 CreateMockWrite(*req1, 0),
4506 CreateMockWrite(*req2, 1),
4509 MockRead reads[] = {
4510 MockRead(ASYNC, 0, 0, 2), // EOF
4513 DeterministicSocketData data(reads, arraysize(reads),
4514 writes, arraysize(writes));
4515 MockConnect connect_data(SYNCHRONOUS, OK);
4516 data.set_connect_data(connect_data);
4518 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4520 CreateDeterministicNetworkSession();
4521 base::WeakPtr<SpdySession> session =
4522 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4523 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4524 session->flow_control_state());
4526 base::WeakPtr<SpdyStream> stream1 =
4527 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4528 session, url, LOWEST, BoundNetLog());
4529 ASSERT_TRUE(stream1.get() != NULL);
4531 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4532 stream1->SetDelegate(&delegate1);
4534 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4536 base::WeakPtr<SpdyStream> stream2 =
4537 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4538 session, url, LOWEST, BoundNetLog());
4539 ASSERT_TRUE(stream2.get() != NULL);
4541 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4542 stream2->SetDelegate(&delegate2);
4544 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4546 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4547 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4549 StallSessionSend(session.get());
4551 scoped_ptr<SpdyHeaderBlock> headers1(
4552 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4553 EXPECT_EQ(ERR_IO_PENDING,
4554 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4555 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4556 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4558 data.RunFor(1);
4559 EXPECT_EQ(1u, stream1->stream_id());
4560 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4562 scoped_ptr<SpdyHeaderBlock> headers2(
4563 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4564 EXPECT_EQ(ERR_IO_PENDING,
4565 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4566 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4567 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4569 data.RunFor(1);
4570 EXPECT_EQ(3u, stream2->stream_id());
4571 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4573 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4575 // Unstall stream1.
4576 UnstallSessionSend(session.get(), kBodyDataSize);
4578 // Close the session (since we can't do it from within the delegate
4579 // method, since it's in the stream's loop).
4580 session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4581 base::RunLoop().RunUntilIdle();
4582 EXPECT_TRUE(session == NULL);
4584 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4586 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4587 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4589 EXPECT_TRUE(delegate1.send_headers_completed());
4590 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4592 EXPECT_TRUE(delegate2.send_headers_completed());
4593 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4595 EXPECT_TRUE(data.at_write_eof());
4598 TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4599 if (GetParam() < kProtoSPDY31)
4600 return;
4602 MockConnect connect_data(SYNCHRONOUS, OK);
4604 scoped_ptr<SpdyFrame> req(
4605 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4606 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4608 GOAWAY_FLOW_CONTROL_ERROR,
4609 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4610 "the receive window size of 1"));
4611 MockWrite writes[] = {
4612 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
4615 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4616 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4617 MockRead reads[] = {
4618 CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
4621 DeterministicSocketData data(
4622 reads, arraysize(reads), writes, arraysize(writes));
4623 data.set_connect_data(connect_data);
4624 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4626 CreateDeterministicNetworkSession();
4628 base::WeakPtr<SpdySession> session =
4629 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4631 GURL url(kDefaultURL);
4632 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4633 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
4634 ASSERT_TRUE(spdy_stream.get() != NULL);
4635 test::StreamDelegateDoNothing delegate(spdy_stream);
4636 spdy_stream->SetDelegate(&delegate);
4638 scoped_ptr<SpdyHeaderBlock> headers(
4639 spdy_util_.ConstructGetHeaderBlock(url.spec()));
4640 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4642 data.RunFor(1); // Write request.
4644 // Put session on the edge of overflowing it's recv window.
4645 session->session_recv_window_size_ = 1;
4647 // Read response headers & body. Body overflows the session window, and a
4648 // goaway is written.
4649 data.RunFor(3);
4650 base::MessageLoop::current()->RunUntilIdle();
4652 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4653 EXPECT_TRUE(session == NULL);
4656 TEST_P(SpdySessionTest, SplitHeaders) {
4657 GURL kStreamUrl("http://www.example.org/foo.dat");
4658 SpdyHeaderBlock headers;
4659 spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4660 headers["alpha"] = "beta";
4662 SpdyHeaderBlock request_headers;
4663 SpdyHeaderBlock response_headers;
4665 SplitPushedHeadersToRequestAndResponse(
4666 headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4668 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4669 std::string alpha_val =
4670 (it == response_headers.end()) ? std::string() : it->second;
4671 EXPECT_EQ("beta", alpha_val);
4673 GURL request_url =
4674 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4675 EXPECT_EQ(kStreamUrl, request_url);
4678 // Regression. Sorta. Push streams and client streams were sharing a single
4679 // limit for a long time.
4680 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4681 SettingsMap new_settings;
4682 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4683 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4684 scoped_ptr<SpdyFrame> settings_frame(
4685 spdy_util_.ConstructSpdySettings(new_settings));
4686 scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4687 NULL, 0, 2, 1, "http://www.example.org/a.dat"));
4688 MockRead reads[] = {
4689 CreateMockRead(*settings_frame), CreateMockRead(*pushed, 3),
4690 MockRead(ASYNC, 0, 4),
4693 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4694 scoped_ptr<SpdyFrame> req(
4695 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4696 MockWrite writes[] = {
4697 CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4700 DeterministicSocketData data(
4701 reads, arraysize(reads), writes, arraysize(writes));
4702 MockConnect connect_data(SYNCHRONOUS, OK);
4703 data.set_connect_data(connect_data);
4704 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4706 CreateDeterministicNetworkSession();
4708 base::WeakPtr<SpdySession> session =
4709 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4711 // Read the settings frame.
4712 data.RunFor(1);
4714 GURL url1(kDefaultURL);
4715 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4716 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4717 ASSERT_TRUE(spdy_stream1.get() != NULL);
4718 EXPECT_EQ(0u, spdy_stream1->stream_id());
4719 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4720 spdy_stream1->SetDelegate(&delegate1);
4722 EXPECT_EQ(0u, session->num_active_streams());
4723 EXPECT_EQ(1u, session->num_created_streams());
4724 EXPECT_EQ(0u, session->num_pushed_streams());
4725 EXPECT_EQ(0u, session->num_active_pushed_streams());
4727 scoped_ptr<SpdyHeaderBlock> headers(
4728 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4729 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4730 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4732 // Run until 1st stream is activated.
4733 EXPECT_EQ(0u, delegate1.stream_id());
4734 data.RunFor(2);
4735 EXPECT_EQ(1u, delegate1.stream_id());
4736 EXPECT_EQ(1u, session->num_active_streams());
4737 EXPECT_EQ(0u, session->num_created_streams());
4738 EXPECT_EQ(0u, session->num_pushed_streams());
4739 EXPECT_EQ(0u, session->num_active_pushed_streams());
4741 // Run until pushed stream is created.
4742 data.RunFor(1);
4743 EXPECT_EQ(2u, session->num_active_streams());
4744 EXPECT_EQ(0u, session->num_created_streams());
4745 EXPECT_EQ(1u, session->num_pushed_streams());
4746 EXPECT_EQ(1u, session->num_active_pushed_streams());
4748 // Second stream should not be stalled, although we have 2 active streams, but
4749 // one of them is push stream and should not be taken into account when we
4750 // create streams on the client.
4751 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4752 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4753 EXPECT_TRUE(spdy_stream2.get() != NULL);
4754 EXPECT_EQ(2u, session->num_active_streams());
4755 EXPECT_EQ(1u, session->num_created_streams());
4756 EXPECT_EQ(1u, session->num_pushed_streams());
4757 EXPECT_EQ(1u, session->num_active_pushed_streams());
4759 // Read EOF.
4760 data.RunFor(1);
4763 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4764 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4765 NULL, 0, 2, 1, "http://www.example.org/a.dat"));
4766 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4767 NULL, 0, 4, 1, "http://www.example.org/b.dat"));
4768 MockRead reads[] = {
4769 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4770 MockRead(ASYNC, 0, 4),
4773 scoped_ptr<SpdyFrame> req(
4774 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4775 scoped_ptr<SpdyFrame> rst(
4776 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4777 MockWrite writes[] = {
4778 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4781 DeterministicSocketData data(
4782 reads, arraysize(reads), writes, arraysize(writes));
4783 MockConnect connect_data(SYNCHRONOUS, OK);
4784 data.set_connect_data(connect_data);
4785 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4787 CreateDeterministicNetworkSession();
4789 base::WeakPtr<SpdySession> session =
4790 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4791 session->set_max_concurrent_pushed_streams(1);
4793 GURL url1(kDefaultURL);
4794 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4795 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4796 ASSERT_TRUE(spdy_stream1.get() != NULL);
4797 EXPECT_EQ(0u, spdy_stream1->stream_id());
4798 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4799 spdy_stream1->SetDelegate(&delegate1);
4801 EXPECT_EQ(0u, session->num_active_streams());
4802 EXPECT_EQ(1u, session->num_created_streams());
4803 EXPECT_EQ(0u, session->num_pushed_streams());
4804 EXPECT_EQ(0u, session->num_active_pushed_streams());
4806 scoped_ptr<SpdyHeaderBlock> headers(
4807 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4808 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4809 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4811 // Run until 1st stream is activated.
4812 EXPECT_EQ(0u, delegate1.stream_id());
4813 data.RunFor(1);
4814 EXPECT_EQ(1u, delegate1.stream_id());
4815 EXPECT_EQ(1u, session->num_active_streams());
4816 EXPECT_EQ(0u, session->num_created_streams());
4817 EXPECT_EQ(0u, session->num_pushed_streams());
4818 EXPECT_EQ(0u, session->num_active_pushed_streams());
4820 // Run until pushed stream is created.
4821 data.RunFor(1);
4822 EXPECT_EQ(2u, session->num_active_streams());
4823 EXPECT_EQ(0u, session->num_created_streams());
4824 EXPECT_EQ(1u, session->num_pushed_streams());
4825 EXPECT_EQ(1u, session->num_active_pushed_streams());
4827 // Reset incoming pushed stream.
4828 data.RunFor(2);
4829 EXPECT_EQ(2u, session->num_active_streams());
4830 EXPECT_EQ(0u, session->num_created_streams());
4831 EXPECT_EQ(1u, session->num_pushed_streams());
4832 EXPECT_EQ(1u, session->num_active_pushed_streams());
4834 // Read EOF.
4835 data.RunFor(1);
4838 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4839 // Streams in reserved remote state exist only in SPDY4.
4840 if (spdy_util_.spdy_version() < SPDY4)
4841 return;
4843 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4844 NULL, 0, 2, 1, "http://www.example.org/a.dat"));
4845 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4846 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/b.dat",
4847 push_headers.get());
4848 scoped_ptr<SpdyFrame> push_b(
4849 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4850 scoped_ptr<SpdyFrame> headers_b(
4851 spdy_util_.ConstructSpdyPushHeaders(4, NULL, 0));
4852 MockRead reads[] = {
4853 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4854 CreateMockRead(*headers_b, 3), MockRead(ASYNC, 0, 5),
4857 scoped_ptr<SpdyFrame> req(
4858 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4859 scoped_ptr<SpdyFrame> rst(
4860 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4861 MockWrite writes[] = {
4862 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
4865 DeterministicSocketData data(
4866 reads, arraysize(reads), writes, arraysize(writes));
4867 MockConnect connect_data(SYNCHRONOUS, OK);
4868 data.set_connect_data(connect_data);
4869 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4871 CreateDeterministicNetworkSession();
4873 base::WeakPtr<SpdySession> session =
4874 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4875 session->set_max_concurrent_pushed_streams(1);
4877 GURL url1(kDefaultURL);
4878 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4879 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4880 ASSERT_TRUE(spdy_stream1.get() != NULL);
4881 EXPECT_EQ(0u, spdy_stream1->stream_id());
4882 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4883 spdy_stream1->SetDelegate(&delegate1);
4885 EXPECT_EQ(0u, session->num_active_streams());
4886 EXPECT_EQ(1u, session->num_created_streams());
4887 EXPECT_EQ(0u, session->num_pushed_streams());
4888 EXPECT_EQ(0u, session->num_active_pushed_streams());
4890 scoped_ptr<SpdyHeaderBlock> headers(
4891 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4892 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4893 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4895 // Run until 1st stream is activated.
4896 EXPECT_EQ(0u, delegate1.stream_id());
4897 data.RunFor(1);
4898 EXPECT_EQ(1u, delegate1.stream_id());
4899 EXPECT_EQ(1u, session->num_active_streams());
4900 EXPECT_EQ(0u, session->num_created_streams());
4901 EXPECT_EQ(0u, session->num_pushed_streams());
4902 EXPECT_EQ(0u, session->num_active_pushed_streams());
4904 // Run until pushed stream is created.
4905 data.RunFor(1);
4906 EXPECT_EQ(2u, session->num_active_streams());
4907 EXPECT_EQ(0u, session->num_created_streams());
4908 EXPECT_EQ(1u, session->num_pushed_streams());
4909 EXPECT_EQ(1u, session->num_active_pushed_streams());
4911 // Accept promised stream. It should not count towards pushed stream limit.
4912 data.RunFor(1);
4913 EXPECT_EQ(3u, session->num_active_streams());
4914 EXPECT_EQ(0u, session->num_created_streams());
4915 EXPECT_EQ(2u, session->num_pushed_streams());
4916 EXPECT_EQ(1u, session->num_active_pushed_streams());
4918 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4919 // while we accept only one.
4920 data.RunFor(2);
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(1u, session->num_active_pushed_streams());
4926 // Read EOF.
4927 data.RunFor(1);
4930 TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
4931 // Streams in reserved remote state exist only in SPDY4.
4932 if (spdy_util_.spdy_version() < SPDY4)
4933 return;
4935 const char kPushedUrl[] = "http://www.example.org/a.dat";
4936 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4937 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
4938 scoped_ptr<SpdyFrame> push_promise(
4939 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
4940 scoped_ptr<SpdyFrame> headers_frame(
4941 spdy_util_.ConstructSpdyPushHeaders(2, NULL, 0));
4942 MockRead reads[] = {
4943 CreateMockRead(*push_promise, 1), CreateMockRead(*headers_frame, 2),
4944 MockRead(ASYNC, 0, 4),
4947 scoped_ptr<SpdyFrame> req(
4948 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4949 scoped_ptr<SpdyFrame> rst(
4950 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
4951 MockWrite writes[] = {
4952 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4955 DeterministicSocketData data(
4956 reads, arraysize(reads), writes, arraysize(writes));
4957 MockConnect connect_data(SYNCHRONOUS, OK);
4958 data.set_connect_data(connect_data);
4959 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4961 CreateDeterministicNetworkSession();
4963 base::WeakPtr<SpdySession> session =
4964 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4966 GURL url1(kDefaultURL);
4967 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4968 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4969 ASSERT_TRUE(spdy_stream1.get() != NULL);
4970 EXPECT_EQ(0u, spdy_stream1->stream_id());
4971 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4972 spdy_stream1->SetDelegate(&delegate1);
4974 EXPECT_EQ(0u, session->num_active_streams());
4975 EXPECT_EQ(1u, session->num_created_streams());
4976 EXPECT_EQ(0u, session->num_pushed_streams());
4977 EXPECT_EQ(0u, session->num_active_pushed_streams());
4979 scoped_ptr<SpdyHeaderBlock> headers(
4980 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4981 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4982 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4984 // Run until 1st stream is activated.
4985 EXPECT_EQ(0u, delegate1.stream_id());
4986 data.RunFor(1);
4987 EXPECT_EQ(1u, delegate1.stream_id());
4988 EXPECT_EQ(1u, session->num_active_streams());
4989 EXPECT_EQ(0u, session->num_created_streams());
4990 EXPECT_EQ(0u, session->num_pushed_streams());
4991 EXPECT_EQ(0u, session->num_active_pushed_streams());
4993 // Run until pushed stream is created.
4994 data.RunFor(1);
4995 EXPECT_EQ(2u, session->num_active_streams());
4996 EXPECT_EQ(0u, session->num_created_streams());
4997 EXPECT_EQ(1u, session->num_pushed_streams());
4998 EXPECT_EQ(0u, session->num_active_pushed_streams());
5000 base::WeakPtr<SpdyStream> pushed_stream;
5001 int rv =
5002 session->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
5003 ASSERT_EQ(OK, rv);
5004 ASSERT_TRUE(pushed_stream.get() != NULL);
5005 test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
5006 pushed_stream->SetDelegate(&delegate2);
5008 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
5009 // that all our counters are in consistent state.
5010 data.RunFor(1);
5011 EXPECT_EQ(1u, session->num_active_streams());
5012 EXPECT_EQ(0u, session->num_created_streams());
5013 EXPECT_EQ(0u, session->num_pushed_streams());
5014 EXPECT_EQ(0u, session->num_active_pushed_streams());
5016 // Read EOF.
5017 data.RunFor(2);
5020 TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
5021 session_deps_.host_resolver->set_synchronous_mode(true);
5023 MockRead reads[] = {
5024 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
5027 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
5029 MockConnect connect_data(SYNCHRONOUS, OK);
5030 data.set_connect_data(connect_data);
5031 session_deps_.socket_factory->AddSocketDataProvider(&data);
5033 CreateNetworkSession();
5034 base::WeakPtr<SpdySession> session =
5035 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
5037 session->stream_hi_water_mark_ = 5;
5038 // Low client (odd) ids are fine.
5039 EXPECT_TRUE(session->OnUnknownFrame(3, 0));
5040 // Client id exceeding watermark.
5041 EXPECT_FALSE(session->OnUnknownFrame(9, 0));
5043 session->last_accepted_push_stream_id_ = 6;
5044 // Low server (even) ids are fine.
5045 EXPECT_TRUE(session->OnUnknownFrame(2, 0));
5046 // Server id exceeding last accepted id.
5047 EXPECT_FALSE(session->OnUnknownFrame(8, 0));
5050 TEST(MapFramerErrorToProtocolError, MapsValues) {
5051 CHECK_EQ(
5052 SPDY_ERROR_INVALID_CONTROL_FRAME,
5053 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
5054 CHECK_EQ(
5055 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
5056 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
5057 CHECK_EQ(
5058 SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
5059 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
5060 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
5061 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
5064 TEST(MapFramerErrorToNetError, MapsValue) {
5065 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
5066 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
5067 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5068 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
5069 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5070 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
5071 CHECK_EQ(
5072 ERR_SPDY_FRAME_SIZE_ERROR,
5073 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
5076 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
5077 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
5078 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
5079 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
5080 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
5081 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
5082 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
5083 CHECK_EQ(STATUS_CODE_INADEQUATE_SECURITY,
5084 MapRstStreamStatusToProtocolError(RST_STREAM_INADEQUATE_SECURITY));
5085 CHECK_EQ(STATUS_CODE_HTTP_1_1_REQUIRED,
5086 MapRstStreamStatusToProtocolError(RST_STREAM_HTTP_1_1_REQUIRED));
5089 TEST(MapNetErrorToGoAwayStatus, MapsValue) {
5090 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
5091 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
5092 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
5093 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
5094 CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
5095 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
5096 CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
5097 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
5098 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
5099 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
5100 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
5103 TEST(CanPoolTest, CanPool) {
5104 // Load a cert that is valid for:
5105 // www.example.org
5106 // mail.example.org
5107 // www.example.com
5109 TransportSecurityState tss;
5110 SSLInfo ssl_info;
5111 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5112 "spdy_pooling.pem");
5114 EXPECT_TRUE(SpdySession::CanPool(
5115 &tss, ssl_info, "www.example.org", "www.example.org"));
5116 EXPECT_TRUE(SpdySession::CanPool(
5117 &tss, ssl_info, "www.example.org", "mail.example.org"));
5118 EXPECT_TRUE(SpdySession::CanPool(
5119 &tss, ssl_info, "www.example.org", "mail.example.com"));
5120 EXPECT_FALSE(SpdySession::CanPool(
5121 &tss, ssl_info, "www.example.org", "mail.google.com"));
5124 TEST(CanPoolTest, CanNotPoolWithCertErrors) {
5125 // Load a cert that is valid for:
5126 // www.example.org
5127 // mail.example.org
5128 // www.example.com
5130 TransportSecurityState tss;
5131 SSLInfo ssl_info;
5132 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5133 "spdy_pooling.pem");
5134 ssl_info.cert_status = CERT_STATUS_REVOKED;
5136 EXPECT_FALSE(SpdySession::CanPool(
5137 &tss, ssl_info, "www.example.org", "mail.example.org"));
5140 TEST(CanPoolTest, CanNotPoolWithClientCerts) {
5141 // Load a cert that is valid for:
5142 // www.example.org
5143 // mail.example.org
5144 // www.example.com
5146 TransportSecurityState tss;
5147 SSLInfo ssl_info;
5148 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5149 "spdy_pooling.pem");
5150 ssl_info.client_cert_sent = true;
5152 EXPECT_FALSE(SpdySession::CanPool(
5153 &tss, ssl_info, "www.example.org", "mail.example.org"));
5156 TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
5157 // Load a cert that is valid for:
5158 // www.example.org
5159 // mail.example.org
5160 // www.example.com
5162 TransportSecurityState tss;
5163 SSLInfo ssl_info;
5164 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5165 "spdy_pooling.pem");
5166 ssl_info.channel_id_sent = true;
5168 EXPECT_TRUE(SpdySession::CanPool(
5169 &tss, ssl_info, "www.example.org", "mail.example.org"));
5170 EXPECT_FALSE(SpdySession::CanPool(
5171 &tss, ssl_info, "www.example.org", "www.example.com"));
5174 TEST(CanPoolTest, CanNotPoolWithBadPins) {
5175 uint8 primary_pin = 1;
5176 uint8 backup_pin = 2;
5177 uint8 bad_pin = 3;
5178 TransportSecurityState tss;
5179 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5181 SSLInfo ssl_info;
5182 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5183 "spdy_pooling.pem");
5184 ssl_info.is_issued_by_known_root = true;
5185 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
5187 EXPECT_FALSE(SpdySession::CanPool(
5188 &tss, ssl_info, "www.example.org", "mail.example.org"));
5191 TEST(CanPoolTest, CanPoolWithAcceptablePins) {
5192 uint8 primary_pin = 1;
5193 uint8 backup_pin = 2;
5194 TransportSecurityState tss;
5195 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5197 SSLInfo ssl_info;
5198 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5199 "spdy_pooling.pem");
5200 ssl_info.is_issued_by_known_root = true;
5201 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
5203 EXPECT_TRUE(SpdySession::CanPool(
5204 &tss, ssl_info, "www.example.org", "mail.example.org"));
5207 } // namespace net