GoogleURLTrackerInfoBarDelegate: Initialize uninitialized member in constructor.
[chromium-blink-merge.git] / net / spdy / spdy_session_unittest.cc
blob1f7ca60daf75cd4a5577812870b720fbd2408592
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/bind.h"
8 #include "base/callback.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "net/base/io_buffer.h"
12 #include "net/base/ip_endpoint.h"
13 #include "net/base/net_log_unittest.h"
14 #include "net/base/request_priority.h"
15 #include "net/base/test_data_directory.h"
16 #include "net/base/test_data_stream.h"
17 #include "net/socket/client_socket_pool_manager.h"
18 #include "net/socket/next_proto.h"
19 #include "net/socket/socket_test_util.h"
20 #include "net/spdy/spdy_http_utils.h"
21 #include "net/spdy/spdy_session_pool.h"
22 #include "net/spdy/spdy_session_test_util.h"
23 #include "net/spdy/spdy_stream.h"
24 #include "net/spdy/spdy_stream_test_util.h"
25 #include "net/spdy/spdy_test_util_common.h"
26 #include "net/spdy/spdy_test_utils.h"
27 #include "net/test/cert_test_util.h"
28 #include "testing/platform_test.h"
30 namespace net {
32 namespace {
34 static const char kTestUrl[] = "http://www.example.org/";
35 static const char kTestHost[] = "www.example.org";
36 static const int kTestPort = 80;
38 const char kBodyData[] = "Body data";
39 const size_t kBodyDataSize = arraysize(kBodyData);
40 const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize);
42 static base::TimeDelta g_time_delta;
43 base::TimeTicks TheNearFuture() {
44 return base::TimeTicks::Now() + g_time_delta;
47 } // namespace
49 class SpdySessionTest : public PlatformTest,
50 public ::testing::WithParamInterface<NextProto> {
51 public:
52 // Functions used with RunResumeAfterUnstallTest().
54 void StallSessionOnly(SpdySession* session, SpdyStream* stream) {
55 StallSessionSend(session);
58 void StallStreamOnly(SpdySession* session, SpdyStream* stream) {
59 StallStreamSend(stream);
62 void StallSessionStream(SpdySession* session, SpdyStream* stream) {
63 StallSessionSend(session);
64 StallStreamSend(stream);
67 void StallStreamSession(SpdySession* session, SpdyStream* stream) {
68 StallStreamSend(stream);
69 StallSessionSend(session);
72 void UnstallSessionOnly(SpdySession* session,
73 SpdyStream* stream,
74 int32 delta_window_size) {
75 UnstallSessionSend(session, delta_window_size);
78 void UnstallStreamOnly(SpdySession* session,
79 SpdyStream* stream,
80 int32 delta_window_size) {
81 UnstallStreamSend(stream, delta_window_size);
84 void UnstallSessionStream(SpdySession* session,
85 SpdyStream* stream,
86 int32 delta_window_size) {
87 UnstallSessionSend(session, delta_window_size);
88 UnstallStreamSend(stream, delta_window_size);
91 void UnstallStreamSession(SpdySession* session,
92 SpdyStream* stream,
93 int32 delta_window_size) {
94 UnstallStreamSend(stream, delta_window_size);
95 UnstallSessionSend(session, delta_window_size);
98 protected:
99 SpdySessionTest()
100 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
101 HttpNetworkSession::NORMAL_SOCKET_POOL)),
102 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
103 HttpNetworkSession::NORMAL_SOCKET_POOL)),
104 spdy_util_(GetParam()),
105 session_deps_(GetParam()),
106 spdy_session_pool_(NULL),
107 test_url_(kTestUrl),
108 test_host_port_pair_(kTestHost, kTestPort),
109 key_(test_host_port_pair_, ProxyServer::Direct(),
110 PRIVACY_MODE_DISABLED) {
113 virtual ~SpdySessionTest() {
114 // Important to restore the per-pool limit first, since the pool limit must
115 // always be greater than group limit, and the tests reduce both limits.
116 ClientSocketPoolManager::set_max_sockets_per_pool(
117 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
118 ClientSocketPoolManager::set_max_sockets_per_group(
119 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
122 virtual void SetUp() OVERRIDE {
123 g_time_delta = base::TimeDelta();
126 void CreateDeterministicNetworkSession() {
127 http_session_ =
128 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
129 spdy_session_pool_ = http_session_->spdy_session_pool();
132 void CreateNetworkSession() {
133 http_session_ =
134 SpdySessionDependencies::SpdyCreateSession(&session_deps_);
135 spdy_session_pool_ = http_session_->spdy_session_pool();
138 void StallSessionSend(SpdySession* session) {
139 // Reduce the send window size to 0 to stall.
140 while (session->session_send_window_size_ > 0) {
141 session->DecreaseSendWindowSize(
142 std::min(kMaxSpdyFrameChunkSize, session->session_send_window_size_));
146 void UnstallSessionSend(SpdySession* session, int32 delta_window_size) {
147 session->IncreaseSendWindowSize(delta_window_size);
150 void StallStreamSend(SpdyStream* stream) {
151 // Reduce the send window size to 0 to stall.
152 while (stream->send_window_size() > 0) {
153 stream->DecreaseSendWindowSize(
154 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
158 void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) {
159 stream->IncreaseSendWindowSize(delta_window_size);
162 void RunResumeAfterUnstallTest(
163 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
164 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
165 unstall_function);
167 // Original socket limits. Some tests set these. Safest to always restore
168 // them once each test has been run.
169 int old_max_group_sockets_;
170 int old_max_pool_sockets_;
172 SpdyTestUtil spdy_util_;
173 SpdySessionDependencies session_deps_;
174 scoped_refptr<HttpNetworkSession> http_session_;
175 SpdySessionPool* spdy_session_pool_;
176 GURL test_url_;
177 HostPortPair test_host_port_pair_;
178 SpdySessionKey key_;
181 INSTANTIATE_TEST_CASE_P(
182 NextProto,
183 SpdySessionTest,
184 testing::Values(kProtoDeprecatedSPDY2,
185 kProtoSPDY3, kProtoSPDY31, 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_FAILED);
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 virtual ~StreamRequestDestroyingCallback() {}
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
286 // immediately close.
287 TEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
288 session_deps_.host_resolver->set_synchronous_mode(true);
290 MockConnect connect_data(SYNCHRONOUS, OK);
291 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
292 MockRead reads[] = {
293 CreateMockRead(*goaway, 0),
295 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
296 data.set_connect_data(connect_data);
297 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
299 CreateDeterministicNetworkSession();
301 base::WeakPtr<SpdySession> session =
302 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
304 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
306 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
308 // Read and process the GOAWAY frame.
309 data.RunFor(1);
311 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
313 EXPECT_TRUE(session == NULL);
316 // A session receiving a GOAWAY frame immediately with no active
317 // streams should then close.
318 TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
319 session_deps_.host_resolver->set_synchronous_mode(true);
321 MockConnect connect_data(SYNCHRONOUS, OK);
322 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
323 MockRead reads[] = {
324 CreateMockRead(*goaway, 0, SYNCHRONOUS),
326 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
327 data.set_connect_data(connect_data);
328 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
330 CreateDeterministicNetworkSession();
332 data.StopAfter(1);
334 base::WeakPtr<SpdySession> session =
335 TryCreateInsecureSpdySessionExpectingFailure(
336 http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
337 base::RunLoop().RunUntilIdle();
339 EXPECT_FALSE(session);
340 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
343 // A session receiving a GOAWAY frame with active streams should close
344 // when the last active stream is closed.
345 TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
346 session_deps_.host_resolver->set_synchronous_mode(true);
348 MockConnect connect_data(SYNCHRONOUS, OK);
349 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
350 MockRead reads[] = {
351 CreateMockRead(*goaway, 2),
352 MockRead(ASYNC, 0, 3) // EOF
354 scoped_ptr<SpdyFrame> req1(
355 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
356 scoped_ptr<SpdyFrame> req2(
357 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
358 MockWrite writes[] = {
359 CreateMockWrite(*req1, 0),
360 CreateMockWrite(*req2, 1),
362 DeterministicSocketData data(reads, arraysize(reads),
363 writes, arraysize(writes));
364 data.set_connect_data(connect_data);
365 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
367 CreateDeterministicNetworkSession();
369 base::WeakPtr<SpdySession> session =
370 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
372 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
374 GURL url(kDefaultURL);
375 base::WeakPtr<SpdyStream> spdy_stream1 =
376 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
377 session, url, MEDIUM, BoundNetLog());
378 test::StreamDelegateDoNothing delegate1(spdy_stream1);
379 spdy_stream1->SetDelegate(&delegate1);
381 base::WeakPtr<SpdyStream> spdy_stream2 =
382 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
383 session, url, MEDIUM, BoundNetLog());
384 test::StreamDelegateDoNothing delegate2(spdy_stream2);
385 spdy_stream2->SetDelegate(&delegate2);
387 scoped_ptr<SpdyHeaderBlock> headers(
388 spdy_util_.ConstructGetHeaderBlock(url.spec()));
389 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
391 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
392 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
393 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
394 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
396 data.RunFor(2);
398 EXPECT_EQ(1u, spdy_stream1->stream_id());
399 EXPECT_EQ(3u, spdy_stream2->stream_id());
401 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
403 // Read and process the GOAWAY frame.
404 data.RunFor(1);
406 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
408 EXPECT_FALSE(session->IsStreamActive(3));
409 EXPECT_EQ(NULL, spdy_stream2.get());
410 EXPECT_TRUE(session->IsStreamActive(1));
412 EXPECT_FALSE(session->IsClosed());
414 // Should close the session.
415 spdy_stream1->Close();
416 EXPECT_EQ(NULL, spdy_stream1.get());
418 EXPECT_TRUE(session == NULL);
421 // Have a session receive two GOAWAY frames, with the last one causing
422 // the last active stream to be closed. The session should then be
423 // closed after the second GOAWAY frame.
424 TEST_P(SpdySessionTest, GoAwayTwice) {
425 session_deps_.host_resolver->set_synchronous_mode(true);
427 MockConnect connect_data(SYNCHRONOUS, OK);
428 scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
429 scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
430 MockRead reads[] = {
431 CreateMockRead(*goaway1, 2),
432 CreateMockRead(*goaway2, 3),
433 MockRead(ASYNC, 0, 4) // EOF
435 scoped_ptr<SpdyFrame> req1(
436 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
437 scoped_ptr<SpdyFrame> req2(
438 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
439 MockWrite writes[] = {
440 CreateMockWrite(*req1, 0),
441 CreateMockWrite(*req2, 1),
443 DeterministicSocketData data(reads, arraysize(reads),
444 writes, arraysize(writes));
445 data.set_connect_data(connect_data);
446 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
448 CreateDeterministicNetworkSession();
450 base::WeakPtr<SpdySession> session =
451 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
453 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
455 GURL url(kDefaultURL);
456 base::WeakPtr<SpdyStream> spdy_stream1 =
457 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
458 session, url, MEDIUM, BoundNetLog());
459 test::StreamDelegateDoNothing delegate1(spdy_stream1);
460 spdy_stream1->SetDelegate(&delegate1);
462 base::WeakPtr<SpdyStream> spdy_stream2 =
463 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
464 session, url, MEDIUM, BoundNetLog());
465 test::StreamDelegateDoNothing delegate2(spdy_stream2);
466 spdy_stream2->SetDelegate(&delegate2);
468 scoped_ptr<SpdyHeaderBlock> headers(
469 spdy_util_.ConstructGetHeaderBlock(url.spec()));
470 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
472 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
473 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
474 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
475 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
477 data.RunFor(2);
479 EXPECT_EQ(1u, spdy_stream1->stream_id());
480 EXPECT_EQ(3u, spdy_stream2->stream_id());
482 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
484 // Read and process the first GOAWAY frame.
485 data.RunFor(1);
487 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
489 EXPECT_FALSE(session->IsStreamActive(3));
490 EXPECT_EQ(NULL, spdy_stream2.get());
491 EXPECT_TRUE(session->IsStreamActive(1));
493 EXPECT_FALSE(session->IsClosed());
495 // Read and process the second GOAWAY frame, which should close the
496 // session.
497 data.RunFor(1);
499 EXPECT_TRUE(session == NULL);
502 // Have a session with active streams receive a GOAWAY frame and then
503 // close it. It should handle the close properly (i.e., not try to
504 // make itself unavailable in its pool twice).
505 TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
506 session_deps_.host_resolver->set_synchronous_mode(true);
508 MockConnect connect_data(SYNCHRONOUS, OK);
509 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
510 MockRead reads[] = {
511 CreateMockRead(*goaway, 2),
512 MockRead(ASYNC, 0, 3) // EOF
514 scoped_ptr<SpdyFrame> req1(
515 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
516 scoped_ptr<SpdyFrame> req2(
517 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
518 MockWrite writes[] = {
519 CreateMockWrite(*req1, 0),
520 CreateMockWrite(*req2, 1),
522 DeterministicSocketData data(reads, arraysize(reads),
523 writes, arraysize(writes));
524 data.set_connect_data(connect_data);
525 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
527 CreateDeterministicNetworkSession();
529 base::WeakPtr<SpdySession> session =
530 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
532 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
534 GURL url(kDefaultURL);
535 base::WeakPtr<SpdyStream> spdy_stream1 =
536 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
537 session, url, MEDIUM, BoundNetLog());
538 test::StreamDelegateDoNothing delegate1(spdy_stream1);
539 spdy_stream1->SetDelegate(&delegate1);
541 base::WeakPtr<SpdyStream> spdy_stream2 =
542 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
543 session, url, MEDIUM, BoundNetLog());
544 test::StreamDelegateDoNothing delegate2(spdy_stream2);
545 spdy_stream2->SetDelegate(&delegate2);
547 scoped_ptr<SpdyHeaderBlock> headers(
548 spdy_util_.ConstructGetHeaderBlock(url.spec()));
549 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
551 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
552 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
553 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
554 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
556 data.RunFor(2);
558 EXPECT_EQ(1u, spdy_stream1->stream_id());
559 EXPECT_EQ(3u, spdy_stream2->stream_id());
561 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
563 // Read and process the GOAWAY frame.
564 data.RunFor(1);
566 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
568 EXPECT_FALSE(session->IsStreamActive(3));
569 EXPECT_EQ(NULL, spdy_stream2.get());
570 EXPECT_TRUE(session->IsStreamActive(1));
572 EXPECT_FALSE(session->IsClosed());
574 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
576 EXPECT_EQ(NULL, spdy_stream1.get());
577 EXPECT_TRUE(session == NULL);
580 // Try to create a stream after receiving a GOAWAY frame. It should
581 // fail.
582 TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
583 session_deps_.host_resolver->set_synchronous_mode(true);
585 MockConnect connect_data(SYNCHRONOUS, OK);
586 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
587 MockRead reads[] = {
588 CreateMockRead(*goaway, 1),
589 MockRead(ASYNC, 0, 2) // EOF
591 scoped_ptr<SpdyFrame> req(
592 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
593 MockWrite writes[] = {
594 CreateMockWrite(*req, 0),
596 DeterministicSocketData data(reads, arraysize(reads),
597 writes, arraysize(writes));
598 data.set_connect_data(connect_data);
599 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
601 CreateDeterministicNetworkSession();
603 base::WeakPtr<SpdySession> session =
604 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
606 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
608 GURL url(kDefaultURL);
609 base::WeakPtr<SpdyStream> spdy_stream =
610 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
611 session, url, MEDIUM, BoundNetLog());
612 test::StreamDelegateDoNothing delegate(spdy_stream);
613 spdy_stream->SetDelegate(&delegate);
615 scoped_ptr<SpdyHeaderBlock> headers(
616 spdy_util_.ConstructGetHeaderBlock(url.spec()));
617 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
618 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
620 data.RunFor(1);
622 EXPECT_EQ(1u, spdy_stream->stream_id());
624 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
626 // Read and process the GOAWAY frame.
627 data.RunFor(1);
629 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
630 EXPECT_TRUE(session->IsStreamActive(1));
632 SpdyStreamRequest stream_request;
633 int rv = stream_request.StartRequest(
634 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog(),
635 CompletionCallback());
636 EXPECT_EQ(ERR_FAILED, rv);
638 // Read and process EOF.
639 data.RunFor(1);
641 EXPECT_TRUE(session == NULL);
644 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
645 // the stream being refused.
646 TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
647 session_deps_.host_resolver->set_synchronous_mode(true);
649 MockConnect connect_data(SYNCHRONOUS, OK);
650 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
651 scoped_ptr<SpdyFrame>
652 push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kDefaultURL));
653 MockRead reads[] = {
654 CreateMockRead(*goaway, 1),
655 CreateMockRead(*push, 2),
656 MockRead(ASYNC, 0, 4) // EOF
658 scoped_ptr<SpdyFrame> req(
659 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
660 scoped_ptr<SpdyFrame> rst(
661 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
662 MockWrite writes[] = {
663 CreateMockWrite(*req, 0),
664 CreateMockWrite(*rst, 3)
666 DeterministicSocketData data(reads, arraysize(reads),
667 writes, arraysize(writes));
668 data.set_connect_data(connect_data);
669 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
671 CreateDeterministicNetworkSession();
673 base::WeakPtr<SpdySession> session =
674 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
676 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
678 GURL url(kDefaultURL);
679 base::WeakPtr<SpdyStream> spdy_stream =
680 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
681 session, url, MEDIUM, BoundNetLog());
682 test::StreamDelegateDoNothing delegate(spdy_stream);
683 spdy_stream->SetDelegate(&delegate);
685 scoped_ptr<SpdyHeaderBlock> headers(
686 spdy_util_.ConstructGetHeaderBlock(url.spec()));
687 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
688 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
690 data.RunFor(1);
692 EXPECT_EQ(1u, spdy_stream->stream_id());
694 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
696 // Read and process the GOAWAY frame.
697 data.RunFor(1);
699 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
700 EXPECT_TRUE(session->IsStreamActive(1));
702 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
703 // and EOF.
704 data.RunFor(3);
706 EXPECT_TRUE(session == NULL);
709 // A session observing a network change with active streams should close
710 // when the last active stream is closed.
711 TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
712 session_deps_.host_resolver->set_synchronous_mode(true);
714 MockConnect connect_data(SYNCHRONOUS, OK);
715 MockRead reads[] = {
716 MockRead(ASYNC, 0, 1) // EOF
718 scoped_ptr<SpdyFrame> req1(
719 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
720 MockWrite writes[] = {
721 CreateMockWrite(*req1, 0),
723 DeterministicSocketData data(reads, arraysize(reads),
724 writes, arraysize(writes));
725 data.set_connect_data(connect_data);
726 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
728 CreateDeterministicNetworkSession();
730 base::WeakPtr<SpdySession> session =
731 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
733 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
735 base::WeakPtr<SpdyStream> spdy_stream =
736 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session,
737 GURL(kDefaultURL), MEDIUM, BoundNetLog());
738 test::StreamDelegateDoNothing delegate(spdy_stream);
739 spdy_stream->SetDelegate(&delegate);
741 scoped_ptr<SpdyHeaderBlock> headers(
742 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
744 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
745 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
747 data.RunFor(1);
749 EXPECT_EQ(1u, spdy_stream->stream_id());
751 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
753 spdy_session_pool_->OnIPAddressChanged();
755 // The SpdySessionPool behavior differs based on how the OSs reacts to
756 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
757 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
758 // For OSs where the TCP connections will close upon relevant network
759 // changes, SpdySessionPool doesn't need to force them to close, so in these
760 // cases verify the session has become unavailable but remains open and the
761 // pre-existing stream is still active.
762 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
764 EXPECT_FALSE(session->IsClosed());
766 EXPECT_TRUE(session->IsStreamActive(1));
768 // Should close the session.
769 spdy_stream->Close();
770 #endif
771 EXPECT_EQ(NULL, spdy_stream.get());
773 EXPECT_TRUE(session == NULL);
776 TEST_P(SpdySessionTest, ClientPing) {
777 session_deps_.enable_ping = true;
778 session_deps_.host_resolver->set_synchronous_mode(true);
780 MockConnect connect_data(SYNCHRONOUS, OK);
781 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
782 MockRead reads[] = {
783 CreateMockRead(*read_ping, 1),
784 MockRead(ASYNC, 0, 0, 2) // EOF
786 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
787 MockWrite writes[] = {
788 CreateMockWrite(*write_ping, 0),
790 DeterministicSocketData data(
791 reads, arraysize(reads), writes, arraysize(writes));
792 data.set_connect_data(connect_data);
793 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
795 CreateDeterministicNetworkSession();
797 base::WeakPtr<SpdySession> session =
798 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
800 base::WeakPtr<SpdyStream> spdy_stream1 =
801 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
802 session, test_url_, MEDIUM, BoundNetLog());
803 ASSERT_TRUE(spdy_stream1.get() != NULL);
804 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
805 spdy_stream1->SetDelegate(&delegate);
807 base::TimeTicks before_ping_time = base::TimeTicks::Now();
809 session->set_connection_at_risk_of_loss_time(
810 base::TimeDelta::FromSeconds(-1));
811 session->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
813 session->SendPrefacePingIfNoneInFlight();
815 data.RunFor(2);
817 session->CheckPingStatus(before_ping_time);
819 EXPECT_EQ(0, session->pings_in_flight());
820 EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1));
821 EXPECT_FALSE(session->check_ping_status_pending());
822 EXPECT_GE(session->last_activity_time(), before_ping_time);
824 data.RunFor(1);
826 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
828 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
829 EXPECT_TRUE(session == NULL);
832 TEST_P(SpdySessionTest, ServerPing) {
833 session_deps_.host_resolver->set_synchronous_mode(true);
835 MockConnect connect_data(SYNCHRONOUS, OK);
836 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
837 MockRead reads[] = {
838 CreateMockRead(*read_ping),
839 MockRead(SYNCHRONOUS, 0, 0) // EOF
841 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
842 MockWrite writes[] = {
843 CreateMockWrite(*write_ping),
845 StaticSocketDataProvider data(
846 reads, arraysize(reads), writes, arraysize(writes));
847 data.set_connect_data(connect_data);
848 session_deps_.socket_factory->AddSocketDataProvider(&data);
850 CreateNetworkSession();
852 base::WeakPtr<SpdySession> session =
853 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
855 base::WeakPtr<SpdyStream> spdy_stream1 =
856 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
857 session, test_url_, MEDIUM, BoundNetLog());
858 ASSERT_TRUE(spdy_stream1.get() != NULL);
859 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
860 spdy_stream1->SetDelegate(&delegate);
862 // Flush the read completion task.
863 base::MessageLoop::current()->RunUntilIdle();
865 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
867 EXPECT_TRUE(session == NULL);
868 EXPECT_EQ(NULL, spdy_stream1.get());
871 // Cause a ping to be sent out while producing a write. The write loop
872 // should handle this properly, i.e. another DoWriteLoop task should
873 // not be posted. This is a regression test for
874 // http://crbug.com/261043 .
875 TEST_P(SpdySessionTest, PingAndWriteLoop) {
876 session_deps_.enable_ping = true;
877 session_deps_.time_func = TheNearFuture;
879 MockConnect connect_data(SYNCHRONOUS, OK);
880 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
881 scoped_ptr<SpdyFrame> req(
882 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
883 MockWrite writes[] = {
884 CreateMockWrite(*req, 0),
885 CreateMockWrite(*write_ping, 1),
888 MockRead reads[] = {
889 MockRead(ASYNC, 0, 2) // EOF
892 session_deps_.host_resolver->set_synchronous_mode(true);
894 DeterministicSocketData data(reads, arraysize(reads),
895 writes, arraysize(writes));
896 data.set_connect_data(connect_data);
897 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
899 CreateDeterministicNetworkSession();
901 base::WeakPtr<SpdySession> session =
902 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
904 GURL url(kDefaultURL);
905 base::WeakPtr<SpdyStream> spdy_stream =
906 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
907 session, url, LOWEST, BoundNetLog());
908 test::StreamDelegateDoNothing delegate(spdy_stream);
909 spdy_stream->SetDelegate(&delegate);
911 scoped_ptr<SpdyHeaderBlock> headers(
912 spdy_util_.ConstructGetHeaderBlock(url.spec()));
913 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
915 // Shift time so that a ping will be sent out.
916 g_time_delta = base::TimeDelta::FromSeconds(11);
918 data.RunFor(2);
920 session->CloseSessionOnError(ERR_ABORTED, "Aborting");
923 TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
924 const SpdyStreamId kLastStreamId = 0x7fffffff;
925 session_deps_.host_resolver->set_synchronous_mode(true);
927 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
928 // fixed to allow for two stream ID assignments, and three concurrent
929 // streams. Four streams are started, and two are activated. Verify the
930 // session goes away, and that the created (but not activated) and
931 // stalled streams are aborted. Also verify the activated streams complete,
932 // at which point the session closes.
934 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
935 NULL, 0, false, kLastStreamId - 2, MEDIUM, true));
936 scoped_ptr<SpdyFrame> req2(
937 spdy_util_.ConstructSpdyGet(NULL, 0, false, kLastStreamId, MEDIUM, true));
939 MockWrite writes[] = {
940 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
943 scoped_ptr<SpdyFrame> resp1(
944 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId - 2));
945 scoped_ptr<SpdyFrame> resp2(
946 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId));
948 scoped_ptr<SpdyFrame> body1(
949 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
950 scoped_ptr<SpdyFrame> body2(
951 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
953 MockRead reads[] = {
954 CreateMockRead(*resp1, 2), CreateMockRead(*resp2, 3),
955 CreateMockRead(*body1, 4), CreateMockRead(*body2, 5),
956 MockRead(ASYNC, 0, 6) // EOF
959 DeterministicSocketData data(
960 reads, arraysize(reads), writes, arraysize(writes));
962 MockConnect connect_data(SYNCHRONOUS, OK);
963 data.set_connect_data(connect_data);
964 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
966 CreateDeterministicNetworkSession();
967 base::WeakPtr<SpdySession> session =
968 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
970 // Fix stream_hi_water_mark_ to allow for two stream activations.
971 session->stream_hi_water_mark_ = kLastStreamId - 2;
972 // Fix max_concurrent_streams to allow for three stream creations.
973 session->max_concurrent_streams_ = 3;
975 // Create three streams synchronously, and begin a fourth (which is stalled).
976 GURL url(kDefaultURL);
977 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
978 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
979 test::StreamDelegateDoNothing delegate1(stream1);
980 stream1->SetDelegate(&delegate1);
982 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
983 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
984 test::StreamDelegateDoNothing delegate2(stream2);
985 stream2->SetDelegate(&delegate2);
987 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
988 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
989 test::StreamDelegateDoNothing delegate3(stream3);
990 stream3->SetDelegate(&delegate3);
992 SpdyStreamRequest request4;
993 TestCompletionCallback callback4;
994 EXPECT_EQ(ERR_IO_PENDING,
995 request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
996 session,
997 url,
998 MEDIUM,
999 BoundNetLog(),
1000 callback4.callback()));
1002 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1003 EXPECT_EQ(0u, session->num_active_streams());
1004 EXPECT_EQ(3u, session->num_created_streams());
1005 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1007 // Activate stream 1. One ID remains available.
1008 stream1->SendRequestHeaders(
1009 scoped_ptr<SpdyHeaderBlock>(
1010 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1011 NO_MORE_DATA_TO_SEND);
1012 data.RunFor(1);
1014 EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1015 EXPECT_EQ(1u, session->num_active_streams());
1016 EXPECT_EQ(2u, session->num_created_streams());
1017 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1019 // Activate stream 2. ID space is exhausted.
1020 stream2->SendRequestHeaders(
1021 scoped_ptr<SpdyHeaderBlock>(
1022 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1023 NO_MORE_DATA_TO_SEND);
1024 data.RunFor(1);
1026 // Active streams remain active.
1027 EXPECT_EQ(kLastStreamId, stream2->stream_id());
1028 EXPECT_EQ(2u, session->num_active_streams());
1030 // Session is going away. Created and stalled streams were aborted.
1031 EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session->availability_state_);
1032 EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose());
1033 EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult());
1034 EXPECT_EQ(0u, session->num_created_streams());
1035 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1037 // Read responses on remaining active streams.
1038 data.RunFor(4);
1039 EXPECT_EQ(OK, delegate1.WaitForClose());
1040 EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1041 EXPECT_EQ(OK, delegate2.WaitForClose());
1042 EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1044 // Session was destroyed.
1045 EXPECT_FALSE(session.get());
1048 // Verifies that an unstalled pending stream creation racing with a new stream
1049 // creation doesn't violate the maximum stream concurrency. Regression test for
1050 // crbug.com/373858.
1051 TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) {
1052 session_deps_.host_resolver->set_synchronous_mode(true);
1054 MockRead reads[] = {
1055 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1058 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1060 MockConnect connect_data(SYNCHRONOUS, OK);
1061 data.set_connect_data(connect_data);
1062 session_deps_.socket_factory->AddSocketDataProvider(&data);
1064 CreateNetworkSession();
1065 base::WeakPtr<SpdySession> session =
1066 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1068 // Fix max_concurrent_streams to allow for one open stream.
1069 session->max_concurrent_streams_ = 1;
1071 // Create two streams: one synchronously, and one which stalls.
1072 GURL url(kDefaultURL);
1073 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1074 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1076 SpdyStreamRequest request2;
1077 TestCompletionCallback callback2;
1078 EXPECT_EQ(ERR_IO_PENDING,
1079 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1080 session,
1081 url,
1082 MEDIUM,
1083 BoundNetLog(),
1084 callback2.callback()));
1086 EXPECT_EQ(1u, session->num_created_streams());
1087 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1089 // Cancel the first stream. A callback to unstall the second stream was
1090 // posted. Don't run it yet.
1091 stream1->Cancel();
1093 EXPECT_EQ(0u, session->num_created_streams());
1094 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1096 // Create a third stream prior to the second stream's callback.
1097 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1098 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1100 EXPECT_EQ(1u, session->num_created_streams());
1101 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1103 // NOW run the message loop. The unstalled stream will re-stall itself.
1104 base::MessageLoop::current()->RunUntilIdle();
1105 EXPECT_EQ(1u, session->num_created_streams());
1106 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1108 // Cancel the third stream and run the message loop. Verify that the second
1109 // stream creation now completes.
1110 stream3->Cancel();
1111 base::MessageLoop::current()->RunUntilIdle();
1113 EXPECT_EQ(1u, session->num_created_streams());
1114 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1115 EXPECT_EQ(OK, callback2.WaitForResult());
1118 TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
1119 session_deps_.host_resolver->set_synchronous_mode(true);
1120 session_deps_.time_func = TheNearFuture;
1122 scoped_ptr<SpdyFrame> req(
1123 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1124 scoped_ptr<SpdyFrame> rst(
1125 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
1127 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
1128 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
1129 scoped_ptr<SpdyFrame> push_a_body(
1130 spdy_util_.ConstructSpdyBodyFrame(2, false));
1131 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
1132 NULL, 0, 4, 1, "http://www.google.com/b.dat"));
1133 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)};
1134 MockRead reads[] = {
1135 CreateMockRead(*push_a, 1), CreateMockRead(*push_a_body, 2),
1136 CreateMockRead(*push_b, 3), MockRead(ASYNC, 0, 5), // EOF
1138 DeterministicSocketData data(
1139 reads, arraysize(reads), writes, arraysize(writes));
1141 MockConnect connect_data(SYNCHRONOUS, OK);
1142 data.set_connect_data(connect_data);
1143 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1145 CreateDeterministicNetworkSession();
1146 base::WeakPtr<SpdySession> session =
1147 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1149 // Process the principal request, and the first push stream request & body.
1150 GURL url(kDefaultURL);
1151 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1152 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1153 test::StreamDelegateDoNothing delegate(spdy_stream);
1154 spdy_stream->SetDelegate(&delegate);
1156 scoped_ptr<SpdyHeaderBlock> headers(
1157 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1158 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1160 data.RunFor(3);
1162 // Verify that there is one unclaimed push stream.
1163 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1164 SpdySession::PushedStreamMap::iterator iter =
1165 session->unclaimed_pushed_streams_.find(
1166 GURL("http://www.google.com/a.dat"));
1167 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1169 if (session->flow_control_state_ ==
1170 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1171 // Unclaimed push body consumed bytes from the session window.
1172 EXPECT_EQ(kSpdySessionInitialWindowSize - kUploadDataSize,
1173 session->session_recv_window_size_);
1174 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
1177 // Shift time to expire the push stream. Read the second SYN_STREAM,
1178 // and verify a RST_STREAM was written.
1179 g_time_delta = base::TimeDelta::FromSeconds(301);
1180 data.RunFor(2);
1182 // Verify that the second pushed stream evicted the first pushed stream.
1183 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1184 iter = session->unclaimed_pushed_streams_.find(
1185 GURL("http://www.google.com/b.dat"));
1186 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1188 if (session->flow_control_state_ ==
1189 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1190 // Verify that the session window reclaimed the evicted stream body.
1191 EXPECT_EQ(kSpdySessionInitialWindowSize,
1192 session->session_recv_window_size_);
1193 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
1196 // Read and process EOF.
1197 data.RunFor(1);
1198 EXPECT_TRUE(session == NULL);
1201 TEST_P(SpdySessionTest, FailedPing) {
1202 session_deps_.host_resolver->set_synchronous_mode(true);
1204 MockConnect connect_data(SYNCHRONOUS, OK);
1205 MockRead reads[] = {
1206 MockRead(ASYNC, 0, 0, 0) // EOF
1208 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
1209 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
1210 data.set_connect_data(connect_data);
1211 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1213 CreateDeterministicNetworkSession();
1215 base::WeakPtr<SpdySession> session =
1216 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1218 base::WeakPtr<SpdyStream> spdy_stream1 =
1219 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1220 session, test_url_, MEDIUM, BoundNetLog());
1221 ASSERT_TRUE(spdy_stream1.get() != NULL);
1222 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
1223 spdy_stream1->SetDelegate(&delegate);
1225 session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1226 session->set_hung_interval(base::TimeDelta::FromSeconds(0));
1228 // Send a PING frame.
1229 session->WritePingFrame(1, false);
1230 EXPECT_LT(0, session->pings_in_flight());
1231 EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1));
1232 EXPECT_TRUE(session->check_ping_status_pending());
1234 // Assert session is not closed.
1235 EXPECT_FALSE(session->IsClosed());
1236 EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams());
1237 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1239 // We set last time we have received any data in 1 sec less than now.
1240 // CheckPingStatus will trigger timeout because hung interval is zero.
1241 base::TimeTicks now = base::TimeTicks::Now();
1242 session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
1243 session->CheckPingStatus(now);
1245 EXPECT_TRUE(session == NULL);
1246 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1247 EXPECT_EQ(NULL, spdy_stream1.get());
1250 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1251 // settings frame increasing the max concurrent streams by 1. Make
1252 // sure nothing blows up. This is a regression test for
1253 // http://crbug.com/57331 .
1254 TEST_P(SpdySessionTest, OnSettings) {
1255 session_deps_.host_resolver->set_synchronous_mode(true);
1257 const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1259 SettingsMap new_settings;
1260 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1261 new_settings[kSpdySettingsIds] =
1262 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1263 scoped_ptr<SpdyFrame> settings_frame(
1264 spdy_util_.ConstructSpdySettings(new_settings));
1265 MockRead reads[] = {
1266 CreateMockRead(*settings_frame, 0),
1267 MockRead(ASYNC, 0, 1),
1270 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1271 MockWrite writes[] = {
1272 CreateMockWrite(*settings_ack, 2),
1275 DeterministicSocketData data(reads, arraysize(reads),
1276 writes, arraysize(writes));
1277 MockConnect connect_data(SYNCHRONOUS, OK);
1278 data.set_connect_data(connect_data);
1279 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1281 CreateDeterministicNetworkSession();
1283 base::WeakPtr<SpdySession> session =
1284 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1286 // Create the maximum number of concurrent streams.
1287 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1288 base::WeakPtr<SpdyStream> spdy_stream =
1289 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1290 session, test_url_, MEDIUM, BoundNetLog());
1291 ASSERT_TRUE(spdy_stream != NULL);
1294 StreamReleaserCallback stream_releaser;
1295 SpdyStreamRequest request;
1296 ASSERT_EQ(ERR_IO_PENDING,
1297 request.StartRequest(
1298 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1299 BoundNetLog(),
1300 stream_releaser.MakeCallback(&request)));
1302 data.RunFor(1);
1304 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1306 data.RunFor(1);
1307 EXPECT_TRUE(session == NULL);
1310 // Start with a persisted value for max concurrent streams. Receive a
1311 // settings frame increasing the max concurrent streams by 1 and which
1312 // also clears the persisted data. Verify that persisted data is
1313 // correct.
1314 TEST_P(SpdySessionTest, ClearSettings) {
1315 if (spdy_util_.spdy_version() >= SPDY4) {
1316 // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1317 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4.
1318 return;
1320 session_deps_.host_resolver->set_synchronous_mode(true);
1322 SettingsMap new_settings;
1323 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1324 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1325 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1326 scoped_ptr<SpdyFrame> settings_frame(
1327 spdy_util_.ConstructSpdySettings(new_settings));
1328 uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1329 test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1330 MockRead reads[] = {
1331 CreateMockRead(*settings_frame, 0),
1332 MockRead(ASYNC, 0, 1),
1335 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
1336 MockConnect connect_data(SYNCHRONOUS, OK);
1337 data.set_connect_data(connect_data);
1338 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1340 CreateDeterministicNetworkSession();
1342 // Initialize the SpdySetting with the default.
1343 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1344 test_host_port_pair_,
1345 SETTINGS_MAX_CONCURRENT_STREAMS,
1346 SETTINGS_FLAG_PLEASE_PERSIST,
1347 kInitialMaxConcurrentStreams);
1349 EXPECT_FALSE(
1350 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1351 test_host_port_pair_).empty());
1353 base::WeakPtr<SpdySession> session =
1354 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1356 // Create the maximum number of concurrent streams.
1357 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1358 base::WeakPtr<SpdyStream> spdy_stream =
1359 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1360 session, test_url_, MEDIUM, BoundNetLog());
1361 ASSERT_TRUE(spdy_stream != NULL);
1364 StreamReleaserCallback stream_releaser;
1366 SpdyStreamRequest request;
1367 ASSERT_EQ(ERR_IO_PENDING,
1368 request.StartRequest(
1369 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1370 BoundNetLog(),
1371 stream_releaser.MakeCallback(&request)));
1373 data.RunFor(1);
1375 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1377 // Make sure that persisted data is cleared.
1378 EXPECT_TRUE(
1379 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1380 test_host_port_pair_).empty());
1382 // Make sure session's max_concurrent_streams is correct.
1383 EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1384 session->max_concurrent_streams());
1386 data.RunFor(1);
1387 EXPECT_TRUE(session == NULL);
1390 // Start with max concurrent streams set to 1. Request two streams.
1391 // When the first completes, have the callback close its stream, which
1392 // should trigger the second stream creation. Then cancel that one
1393 // immediately. Don't crash. This is a regression test for
1394 // http://crbug.com/63532 .
1395 TEST_P(SpdySessionTest, CancelPendingCreateStream) {
1396 session_deps_.host_resolver->set_synchronous_mode(true);
1398 MockRead reads[] = {
1399 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1402 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1403 MockConnect connect_data(SYNCHRONOUS, OK);
1405 data.set_connect_data(connect_data);
1406 session_deps_.socket_factory->AddSocketDataProvider(&data);
1408 CreateNetworkSession();
1410 // Initialize the SpdySetting with 1 max concurrent streams.
1411 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1412 test_host_port_pair_,
1413 SETTINGS_MAX_CONCURRENT_STREAMS,
1414 SETTINGS_FLAG_PLEASE_PERSIST,
1417 base::WeakPtr<SpdySession> session =
1418 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1420 // Leave room for only one more stream to be created.
1421 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1422 base::WeakPtr<SpdyStream> spdy_stream =
1423 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1424 session, test_url_, MEDIUM, BoundNetLog());
1425 ASSERT_TRUE(spdy_stream != NULL);
1428 // Create 2 more streams. First will succeed. Second will be pending.
1429 base::WeakPtr<SpdyStream> spdy_stream1 =
1430 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1431 session, test_url_, MEDIUM, BoundNetLog());
1432 ASSERT_TRUE(spdy_stream1.get() != NULL);
1434 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1435 // a valgrind error if the callback is invoked when it's not supposed to be.
1436 scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
1438 SpdyStreamRequest request;
1439 ASSERT_EQ(ERR_IO_PENDING,
1440 request.StartRequest(
1441 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1442 BoundNetLog(),
1443 callback->callback()));
1445 // Release the first one, this will allow the second to be created.
1446 spdy_stream1->Cancel();
1447 EXPECT_EQ(NULL, spdy_stream1.get());
1449 request.CancelRequest();
1450 callback.reset();
1452 // Should not crash when running the pending callback.
1453 base::MessageLoop::current()->RunUntilIdle();
1456 TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
1457 session_deps_.host_resolver->set_synchronous_mode(true);
1459 MockRead reads[] = {
1460 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1463 SettingsMap settings;
1464 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
1465 const SpdySettingsIds kSpdySettingsIds2 = SETTINGS_INITIAL_WINDOW_SIZE;
1466 const uint32 kInitialRecvWindowSize = 10 * 1024 * 1024;
1467 settings[kSpdySettingsIds1] =
1468 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
1469 if (spdy_util_.spdy_version() >= SPDY3) {
1470 settings[kSpdySettingsIds2] =
1471 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialRecvWindowSize);
1473 MockConnect connect_data(SYNCHRONOUS, OK);
1474 scoped_ptr<SpdyFrame> settings_frame(
1475 spdy_util_.ConstructSpdySettings(settings));
1476 scoped_ptr<SpdyFrame> initial_window_update(
1477 spdy_util_.ConstructSpdyWindowUpdate(
1478 kSessionFlowControlStreamId,
1479 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
1480 std::vector<MockWrite> writes;
1481 if (GetParam() == kProtoSPDY4) {
1482 writes.push_back(
1483 MockWrite(ASYNC,
1484 kHttp2ConnectionHeaderPrefix,
1485 kHttp2ConnectionHeaderPrefixSize));
1487 writes.push_back(CreateMockWrite(*settings_frame));
1488 if (GetParam() >= kProtoSPDY31) {
1489 writes.push_back(CreateMockWrite(*initial_window_update));
1492 SettingsMap server_settings;
1493 const uint32 initial_max_concurrent_streams = 1;
1494 server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1495 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1496 initial_max_concurrent_streams);
1497 scoped_ptr<SpdyFrame> server_settings_frame(
1498 spdy_util_.ConstructSpdySettings(server_settings));
1499 writes.push_back(CreateMockWrite(*server_settings_frame));
1501 session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize;
1503 StaticSocketDataProvider data(reads, arraysize(reads),
1504 vector_as_array(&writes), writes.size());
1505 data.set_connect_data(connect_data);
1506 session_deps_.socket_factory->AddSocketDataProvider(&data);
1508 CreateNetworkSession();
1510 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1511 test_host_port_pair_,
1512 SETTINGS_MAX_CONCURRENT_STREAMS,
1513 SETTINGS_FLAG_PLEASE_PERSIST,
1514 initial_max_concurrent_streams);
1516 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1517 pool_peer.SetEnableSendingInitialData(true);
1519 base::WeakPtr<SpdySession> session =
1520 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1522 base::MessageLoop::current()->RunUntilIdle();
1523 EXPECT_TRUE(data.at_write_eof());
1526 TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
1527 CreateNetworkSession();
1529 base::WeakPtr<HttpServerProperties> test_http_server_properties =
1530 spdy_session_pool_->http_server_properties();
1531 SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
1532 test_http_server_properties->SetSpdySetting(
1533 test_host_port_pair_,
1534 SETTINGS_MAX_CONCURRENT_STREAMS,
1535 SETTINGS_FLAG_PLEASE_PERSIST,
1537 EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
1538 test_host_port_pair_).size());
1539 spdy_session_pool_->OnIPAddressChanged();
1540 EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
1541 test_host_port_pair_).size());
1544 TEST_P(SpdySessionTest, Initialize) {
1545 CapturingBoundNetLog log;
1546 session_deps_.net_log = log.bound().net_log();
1547 session_deps_.host_resolver->set_synchronous_mode(true);
1549 MockConnect connect_data(SYNCHRONOUS, OK);
1550 MockRead reads[] = {
1551 MockRead(ASYNC, 0, 0) // EOF
1554 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1555 data.set_connect_data(connect_data);
1556 session_deps_.socket_factory->AddSocketDataProvider(&data);
1558 CreateNetworkSession();
1560 base::WeakPtr<SpdySession> session =
1561 CreateInsecureSpdySession(http_session_, key_, log.bound());
1562 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1564 // Flush the read completion task.
1565 base::MessageLoop::current()->RunUntilIdle();
1567 net::CapturingNetLog::CapturedEntryList entries;
1568 log.GetEntries(&entries);
1569 EXPECT_LT(0u, entries.size());
1571 // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly.
1572 int pos = net::ExpectLogContainsSomewhere(
1573 entries, 0,
1574 net::NetLog::TYPE_SPDY_SESSION_INITIALIZED,
1575 net::NetLog::PHASE_NONE);
1576 EXPECT_LT(0, pos);
1578 CapturingNetLog::CapturedEntry entry = entries[pos];
1579 NetLog::Source socket_source;
1580 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1581 &socket_source));
1582 EXPECT_TRUE(socket_source.IsValid());
1583 EXPECT_NE(log.bound().source().id, socket_source.id);
1586 TEST_P(SpdySessionTest, CloseSessionOnError) {
1587 session_deps_.host_resolver->set_synchronous_mode(true);
1589 MockConnect connect_data(SYNCHRONOUS, OK);
1590 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
1591 MockRead reads[] = {
1592 CreateMockRead(*goaway),
1593 MockRead(SYNCHRONOUS, 0, 0) // EOF
1596 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1597 data.set_connect_data(connect_data);
1598 session_deps_.socket_factory->AddSocketDataProvider(&data);
1600 CreateNetworkSession();
1602 CapturingBoundNetLog log;
1603 base::WeakPtr<SpdySession> session =
1604 CreateInsecureSpdySession(http_session_, key_, log.bound());
1605 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1607 // Flush the read completion task.
1608 base::MessageLoop::current()->RunUntilIdle();
1610 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1611 EXPECT_TRUE(session == NULL);
1613 // Check that the NetLog was filled reasonably.
1614 net::CapturingNetLog::CapturedEntryList entries;
1615 log.GetEntries(&entries);
1616 EXPECT_LT(0u, entries.size());
1618 // Check that we logged SPDY_SESSION_CLOSE correctly.
1619 int pos = net::ExpectLogContainsSomewhere(
1620 entries, 0,
1621 net::NetLog::TYPE_SPDY_SESSION_CLOSE,
1622 net::NetLog::PHASE_NONE);
1624 if (pos < static_cast<int>(entries.size())) {
1625 CapturingNetLog::CapturedEntry entry = entries[pos];
1626 int error_code = 0;
1627 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1628 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1629 } else {
1630 ADD_FAILURE();
1634 // Queue up a low-priority SYN_STREAM followed by a high-priority
1635 // one. The high priority one should still send first and receive
1636 // first.
1637 TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1638 // Construct the request.
1639 MockConnect connect_data(SYNCHRONOUS, OK);
1640 scoped_ptr<SpdyFrame> req_highest(
1641 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true));
1642 scoped_ptr<SpdyFrame> req_lowest(
1643 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1644 MockWrite writes[] = {
1645 CreateMockWrite(*req_highest, 0),
1646 CreateMockWrite(*req_lowest, 1),
1649 scoped_ptr<SpdyFrame> resp_highest(
1650 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1651 scoped_ptr<SpdyFrame> body_highest(
1652 spdy_util_.ConstructSpdyBodyFrame(1, true));
1653 scoped_ptr<SpdyFrame> resp_lowest(
1654 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1655 scoped_ptr<SpdyFrame> body_lowest(
1656 spdy_util_.ConstructSpdyBodyFrame(3, true));
1657 MockRead reads[] = {
1658 CreateMockRead(*resp_highest, 2),
1659 CreateMockRead(*body_highest, 3),
1660 CreateMockRead(*resp_lowest, 4),
1661 CreateMockRead(*body_lowest, 5),
1662 MockRead(ASYNC, 0, 6) // EOF
1665 session_deps_.host_resolver->set_synchronous_mode(true);
1667 DeterministicSocketData data(reads, arraysize(reads),
1668 writes, arraysize(writes));
1669 data.set_connect_data(connect_data);
1670 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1672 CreateDeterministicNetworkSession();
1674 base::WeakPtr<SpdySession> session =
1675 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1677 GURL url(kDefaultURL);
1679 base::WeakPtr<SpdyStream> spdy_stream_lowest =
1680 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1681 session, url, LOWEST, BoundNetLog());
1682 ASSERT_TRUE(spdy_stream_lowest);
1683 EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1684 test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1685 spdy_stream_lowest->SetDelegate(&delegate_lowest);
1687 base::WeakPtr<SpdyStream> spdy_stream_highest =
1688 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1689 session, url, HIGHEST, BoundNetLog());
1690 ASSERT_TRUE(spdy_stream_highest);
1691 EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1692 test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1693 spdy_stream_highest->SetDelegate(&delegate_highest);
1695 // Queue the lower priority one first.
1697 scoped_ptr<SpdyHeaderBlock> headers_lowest(
1698 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1699 spdy_stream_lowest->SendRequestHeaders(
1700 headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1701 EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1703 scoped_ptr<SpdyHeaderBlock> headers_highest(
1704 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1705 spdy_stream_highest->SendRequestHeaders(
1706 headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1707 EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1709 data.RunFor(7);
1711 EXPECT_FALSE(spdy_stream_lowest);
1712 EXPECT_FALSE(spdy_stream_highest);
1713 EXPECT_EQ(3u, delegate_lowest.stream_id());
1714 EXPECT_EQ(1u, delegate_highest.stream_id());
1717 TEST_P(SpdySessionTest, CancelStream) {
1718 MockConnect connect_data(SYNCHRONOUS, OK);
1719 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1720 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1721 scoped_ptr<SpdyFrame> req2(
1722 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1723 MockWrite writes[] = {
1724 CreateMockWrite(*req2, 0),
1727 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1728 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1729 MockRead reads[] = {
1730 CreateMockRead(*resp2, 1),
1731 CreateMockRead(*body2, 2),
1732 MockRead(ASYNC, 0, 3) // EOF
1735 session_deps_.host_resolver->set_synchronous_mode(true);
1737 DeterministicSocketData data(reads, arraysize(reads),
1738 writes, arraysize(writes));
1739 data.set_connect_data(connect_data);
1740 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1742 CreateDeterministicNetworkSession();
1744 base::WeakPtr<SpdySession> session =
1745 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1747 GURL url1(kDefaultURL);
1748 base::WeakPtr<SpdyStream> spdy_stream1 =
1749 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1750 session, url1, HIGHEST, BoundNetLog());
1751 ASSERT_TRUE(spdy_stream1.get() != NULL);
1752 EXPECT_EQ(0u, spdy_stream1->stream_id());
1753 test::StreamDelegateDoNothing delegate1(spdy_stream1);
1754 spdy_stream1->SetDelegate(&delegate1);
1756 GURL url2(kDefaultURL);
1757 base::WeakPtr<SpdyStream> spdy_stream2 =
1758 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1759 session, url2, LOWEST, BoundNetLog());
1760 ASSERT_TRUE(spdy_stream2.get() != NULL);
1761 EXPECT_EQ(0u, spdy_stream2->stream_id());
1762 test::StreamDelegateDoNothing delegate2(spdy_stream2);
1763 spdy_stream2->SetDelegate(&delegate2);
1765 scoped_ptr<SpdyHeaderBlock> headers(
1766 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1767 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1768 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1770 scoped_ptr<SpdyHeaderBlock> headers2(
1771 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1772 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1773 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1775 EXPECT_EQ(0u, spdy_stream1->stream_id());
1777 spdy_stream1->Cancel();
1778 EXPECT_EQ(NULL, spdy_stream1.get());
1780 EXPECT_EQ(0u, delegate1.stream_id());
1782 data.RunFor(1);
1784 EXPECT_EQ(0u, delegate1.stream_id());
1785 EXPECT_EQ(1u, delegate2.stream_id());
1787 spdy_stream2->Cancel();
1788 EXPECT_EQ(NULL, spdy_stream2.get());
1791 // Create two streams that are set to re-close themselves on close,
1792 // and then close the session. Nothing should blow up. Also a
1793 // regression test for http://crbug.com/139518 .
1794 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1795 session_deps_.host_resolver->set_synchronous_mode(true);
1797 MockConnect connect_data(SYNCHRONOUS, OK);
1799 // No actual data will be sent.
1800 MockWrite writes[] = {
1801 MockWrite(ASYNC, 0, 1) // EOF
1804 MockRead reads[] = {
1805 MockRead(ASYNC, 0, 0) // EOF
1807 DeterministicSocketData data(reads, arraysize(reads),
1808 writes, arraysize(writes));
1809 data.set_connect_data(connect_data);
1810 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1812 CreateDeterministicNetworkSession();
1814 base::WeakPtr<SpdySession> session =
1815 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1817 GURL url1(kDefaultURL);
1818 base::WeakPtr<SpdyStream> spdy_stream1 =
1819 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1820 session, url1, HIGHEST, BoundNetLog());
1821 ASSERT_TRUE(spdy_stream1.get() != NULL);
1822 EXPECT_EQ(0u, spdy_stream1->stream_id());
1824 GURL url2(kDefaultURL);
1825 base::WeakPtr<SpdyStream> spdy_stream2 =
1826 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1827 session, url2, LOWEST, BoundNetLog());
1828 ASSERT_TRUE(spdy_stream2.get() != NULL);
1829 EXPECT_EQ(0u, spdy_stream2->stream_id());
1831 test::ClosingDelegate delegate1(spdy_stream1);
1832 spdy_stream1->SetDelegate(&delegate1);
1834 test::ClosingDelegate delegate2(spdy_stream2);
1835 spdy_stream2->SetDelegate(&delegate2);
1837 scoped_ptr<SpdyHeaderBlock> headers(
1838 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1839 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1840 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1842 scoped_ptr<SpdyHeaderBlock> headers2(
1843 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1844 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1845 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1847 // Ensure that the streams have not yet been activated and assigned an id.
1848 EXPECT_EQ(0u, spdy_stream1->stream_id());
1849 EXPECT_EQ(0u, spdy_stream2->stream_id());
1851 // Ensure we don't crash while closing the session.
1852 session->CloseSessionOnError(ERR_ABORTED, std::string());
1854 EXPECT_EQ(NULL, spdy_stream1.get());
1855 EXPECT_EQ(NULL, spdy_stream2.get());
1857 EXPECT_TRUE(delegate1.StreamIsClosed());
1858 EXPECT_TRUE(delegate2.StreamIsClosed());
1860 EXPECT_TRUE(session == NULL);
1863 // Create two streams that are set to close each other on close, and
1864 // then close the session. Nothing should blow up.
1865 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
1866 session_deps_.host_resolver->set_synchronous_mode(true);
1868 MockConnect connect_data(SYNCHRONOUS, OK);
1870 // No actual data will be sent.
1871 MockWrite writes[] = {
1872 MockWrite(ASYNC, 0, 1) // EOF
1875 MockRead reads[] = {
1876 MockRead(ASYNC, 0, 0) // EOF
1878 DeterministicSocketData data(reads, arraysize(reads),
1879 writes, arraysize(writes));
1880 data.set_connect_data(connect_data);
1881 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1883 CreateDeterministicNetworkSession();
1885 base::WeakPtr<SpdySession> session =
1886 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1888 GURL url1(kDefaultURL);
1889 base::WeakPtr<SpdyStream> spdy_stream1 =
1890 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1891 session, url1, HIGHEST, BoundNetLog());
1892 ASSERT_TRUE(spdy_stream1.get() != NULL);
1893 EXPECT_EQ(0u, spdy_stream1->stream_id());
1895 GURL url2(kDefaultURL);
1896 base::WeakPtr<SpdyStream> spdy_stream2 =
1897 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1898 session, url2, LOWEST, BoundNetLog());
1899 ASSERT_TRUE(spdy_stream2.get() != NULL);
1900 EXPECT_EQ(0u, spdy_stream2->stream_id());
1902 // Make |spdy_stream1| close |spdy_stream2|.
1903 test::ClosingDelegate delegate1(spdy_stream2);
1904 spdy_stream1->SetDelegate(&delegate1);
1906 // Make |spdy_stream2| close |spdy_stream1|.
1907 test::ClosingDelegate delegate2(spdy_stream1);
1908 spdy_stream2->SetDelegate(&delegate2);
1910 scoped_ptr<SpdyHeaderBlock> headers(
1911 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1912 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1913 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1915 scoped_ptr<SpdyHeaderBlock> headers2(
1916 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1917 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1918 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1920 // Ensure that the streams have not yet been activated and assigned an id.
1921 EXPECT_EQ(0u, spdy_stream1->stream_id());
1922 EXPECT_EQ(0u, spdy_stream2->stream_id());
1924 // Ensure we don't crash while closing the session.
1925 session->CloseSessionOnError(ERR_ABORTED, std::string());
1927 EXPECT_EQ(NULL, spdy_stream1.get());
1928 EXPECT_EQ(NULL, spdy_stream2.get());
1930 EXPECT_TRUE(delegate1.StreamIsClosed());
1931 EXPECT_TRUE(delegate2.StreamIsClosed());
1933 EXPECT_TRUE(session == NULL);
1936 // Create two streams that are set to re-close themselves on close,
1937 // activate them, and then close the session. Nothing should blow up.
1938 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
1939 session_deps_.host_resolver->set_synchronous_mode(true);
1941 MockConnect connect_data(SYNCHRONOUS, OK);
1943 scoped_ptr<SpdyFrame> req1(
1944 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1945 scoped_ptr<SpdyFrame> req2(
1946 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
1947 MockWrite writes[] = {
1948 CreateMockWrite(*req1, 0),
1949 CreateMockWrite(*req2, 1),
1952 MockRead reads[] = {
1953 MockRead(ASYNC, 0, 2) // EOF
1956 DeterministicSocketData data(reads, arraysize(reads),
1957 writes, arraysize(writes));
1958 data.set_connect_data(connect_data);
1959 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1961 CreateDeterministicNetworkSession();
1963 base::WeakPtr<SpdySession> session =
1964 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1966 GURL url1(kDefaultURL);
1967 base::WeakPtr<SpdyStream> spdy_stream1 =
1968 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1969 session, url1, MEDIUM, BoundNetLog());
1970 ASSERT_TRUE(spdy_stream1.get() != NULL);
1971 EXPECT_EQ(0u, spdy_stream1->stream_id());
1973 GURL url2(kDefaultURL);
1974 base::WeakPtr<SpdyStream> spdy_stream2 =
1975 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1976 session, url2, MEDIUM, BoundNetLog());
1977 ASSERT_TRUE(spdy_stream2.get() != NULL);
1978 EXPECT_EQ(0u, spdy_stream2->stream_id());
1980 test::ClosingDelegate delegate1(spdy_stream1);
1981 spdy_stream1->SetDelegate(&delegate1);
1983 test::ClosingDelegate delegate2(spdy_stream2);
1984 spdy_stream2->SetDelegate(&delegate2);
1986 scoped_ptr<SpdyHeaderBlock> headers(
1987 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1988 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1989 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1991 scoped_ptr<SpdyHeaderBlock> headers2(
1992 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1993 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1994 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1996 // Ensure that the streams have not yet been activated and assigned an id.
1997 EXPECT_EQ(0u, spdy_stream1->stream_id());
1998 EXPECT_EQ(0u, spdy_stream2->stream_id());
2000 data.RunFor(2);
2002 EXPECT_EQ(1u, spdy_stream1->stream_id());
2003 EXPECT_EQ(3u, spdy_stream2->stream_id());
2005 // Ensure we don't crash while closing the session.
2006 session->CloseSessionOnError(ERR_ABORTED, std::string());
2008 EXPECT_EQ(NULL, spdy_stream1.get());
2009 EXPECT_EQ(NULL, spdy_stream2.get());
2011 EXPECT_TRUE(delegate1.StreamIsClosed());
2012 EXPECT_TRUE(delegate2.StreamIsClosed());
2014 EXPECT_TRUE(session == NULL);
2017 // Create two streams that are set to close each other on close,
2018 // activate them, and then close the session. Nothing should blow up.
2019 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2020 session_deps_.host_resolver->set_synchronous_mode(true);
2022 MockConnect connect_data(SYNCHRONOUS, OK);
2024 scoped_ptr<SpdyFrame> req1(
2025 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2026 scoped_ptr<SpdyFrame> req2(
2027 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2028 MockWrite writes[] = {
2029 CreateMockWrite(*req1, 0),
2030 CreateMockWrite(*req2, 1),
2033 MockRead reads[] = {
2034 MockRead(ASYNC, 0, 2) // EOF
2037 DeterministicSocketData data(reads, arraysize(reads),
2038 writes, arraysize(writes));
2039 data.set_connect_data(connect_data);
2040 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2042 CreateDeterministicNetworkSession();
2044 base::WeakPtr<SpdySession> session =
2045 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2047 GURL url1(kDefaultURL);
2048 base::WeakPtr<SpdyStream> spdy_stream1 =
2049 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2050 session, url1, MEDIUM, BoundNetLog());
2051 ASSERT_TRUE(spdy_stream1.get() != NULL);
2052 EXPECT_EQ(0u, spdy_stream1->stream_id());
2054 GURL url2(kDefaultURL);
2055 base::WeakPtr<SpdyStream> spdy_stream2 =
2056 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2057 session, url2, MEDIUM, BoundNetLog());
2058 ASSERT_TRUE(spdy_stream2.get() != NULL);
2059 EXPECT_EQ(0u, spdy_stream2->stream_id());
2061 // Make |spdy_stream1| close |spdy_stream2|.
2062 test::ClosingDelegate delegate1(spdy_stream2);
2063 spdy_stream1->SetDelegate(&delegate1);
2065 // Make |spdy_stream2| close |spdy_stream1|.
2066 test::ClosingDelegate delegate2(spdy_stream1);
2067 spdy_stream2->SetDelegate(&delegate2);
2069 scoped_ptr<SpdyHeaderBlock> headers(
2070 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2071 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2072 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2074 scoped_ptr<SpdyHeaderBlock> headers2(
2075 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2076 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2077 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2079 // Ensure that the streams have not yet been activated and assigned an id.
2080 EXPECT_EQ(0u, spdy_stream1->stream_id());
2081 EXPECT_EQ(0u, spdy_stream2->stream_id());
2083 data.RunFor(2);
2085 EXPECT_EQ(1u, spdy_stream1->stream_id());
2086 EXPECT_EQ(3u, spdy_stream2->stream_id());
2088 // Ensure we don't crash while closing the session.
2089 session->CloseSessionOnError(ERR_ABORTED, std::string());
2091 EXPECT_EQ(NULL, spdy_stream1.get());
2092 EXPECT_EQ(NULL, spdy_stream2.get());
2094 EXPECT_TRUE(delegate1.StreamIsClosed());
2095 EXPECT_TRUE(delegate2.StreamIsClosed());
2097 EXPECT_TRUE(session == NULL);
2100 // Delegate that closes a given session when the stream is closed.
2101 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2102 public:
2103 SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2104 const base::WeakPtr<SpdySession>& session_to_close)
2105 : StreamDelegateDoNothing(stream),
2106 session_to_close_(session_to_close) {}
2108 virtual ~SessionClosingDelegate() {}
2110 virtual void OnClose(int status) OVERRIDE {
2111 session_to_close_->CloseSessionOnError(ERR_ABORTED, "Aborted");
2114 private:
2115 base::WeakPtr<SpdySession> session_to_close_;
2118 // Close an activated stream that closes its session. Nothing should
2119 // blow up. This is a regression test for http://crbug.com/263691 .
2120 TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2121 session_deps_.host_resolver->set_synchronous_mode(true);
2123 MockConnect connect_data(SYNCHRONOUS, OK);
2125 scoped_ptr<SpdyFrame> req(
2126 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2127 MockWrite writes[] = {
2128 CreateMockWrite(*req, 0),
2131 MockRead reads[] = {
2132 MockRead(ASYNC, 0, 1) // EOF
2134 DeterministicSocketData data(reads, arraysize(reads),
2135 writes, arraysize(writes));
2136 data.set_connect_data(connect_data);
2137 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2139 CreateDeterministicNetworkSession();
2141 base::WeakPtr<SpdySession> session =
2142 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2144 GURL url(kDefaultURL);
2145 base::WeakPtr<SpdyStream> spdy_stream =
2146 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2147 session, url, MEDIUM, BoundNetLog());
2148 ASSERT_TRUE(spdy_stream.get() != NULL);
2149 EXPECT_EQ(0u, spdy_stream->stream_id());
2151 SessionClosingDelegate delegate(spdy_stream, session);
2152 spdy_stream->SetDelegate(&delegate);
2154 scoped_ptr<SpdyHeaderBlock> headers(
2155 spdy_util_.ConstructGetHeaderBlock(url.spec()));
2156 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2157 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2159 EXPECT_EQ(0u, spdy_stream->stream_id());
2161 data.RunFor(1);
2163 EXPECT_EQ(1u, spdy_stream->stream_id());
2165 // Ensure we don't crash while closing the stream (which closes the
2166 // session).
2167 spdy_stream->Cancel();
2169 EXPECT_EQ(NULL, spdy_stream.get());
2170 EXPECT_TRUE(delegate.StreamIsClosed());
2171 EXPECT_TRUE(session == NULL);
2174 TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2175 session_deps_.host_resolver->set_synchronous_mode(true);
2177 MockConnect connect_data(SYNCHRONOUS, OK);
2179 // No actual data will be sent.
2180 MockWrite writes[] = {
2181 MockWrite(ASYNC, 0, 1) // EOF
2184 MockRead reads[] = {
2185 MockRead(ASYNC, 0, 0) // EOF
2187 DeterministicSocketData data(reads, arraysize(reads),
2188 writes, arraysize(writes));
2189 data.set_connect_data(connect_data);
2190 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2192 // Load a cert that is valid for:
2193 // www.example.org
2194 // mail.example.org
2195 // www.example.com
2196 base::FilePath certs_dir = GetTestCertsDirectory();
2197 scoped_refptr<X509Certificate> test_cert(
2198 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2199 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert);
2201 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2202 ssl.cert = test_cert;
2203 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2205 CreateDeterministicNetworkSession();
2207 base::WeakPtr<SpdySession> session =
2208 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2210 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2211 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2212 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
2213 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2216 TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2217 session_deps_.host_resolver->set_synchronous_mode(true);
2219 MockConnect connect_data(SYNCHRONOUS, OK);
2221 // No actual data will be sent.
2222 MockWrite writes[] = {
2223 MockWrite(ASYNC, 0, 1) // EOF
2226 MockRead reads[] = {
2227 MockRead(ASYNC, 0, 0) // EOF
2229 DeterministicSocketData data(reads, arraysize(reads),
2230 writes, arraysize(writes));
2231 data.set_connect_data(connect_data);
2232 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2234 // Load a cert that is valid for:
2235 // www.example.org
2236 // mail.example.org
2237 // www.example.com
2238 base::FilePath certs_dir = GetTestCertsDirectory();
2239 scoped_refptr<X509Certificate> test_cert(
2240 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2241 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert);
2243 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2244 ssl.channel_id_sent = true;
2245 ssl.cert = test_cert;
2246 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2248 CreateDeterministicNetworkSession();
2250 base::WeakPtr<SpdySession> session =
2251 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2253 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2254 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2255 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2256 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2259 TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2260 // TODO(rtenneti): Define a helper class/methods and move the common code in
2261 // this file.
2262 MockConnect connect_data(SYNCHRONOUS, OK);
2264 SettingsMap new_settings;
2265 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2266 const uint32 max_concurrent_streams = 1;
2267 new_settings[kSpdySettingsIds1] =
2268 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2270 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
2271 scoped_ptr<SpdyFrame> req1(
2272 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2273 scoped_ptr<SpdyFrame> req2(
2274 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
2275 scoped_ptr<SpdyFrame> req3(
2276 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
2277 MockWrite writes[] = {
2278 CreateMockWrite(*settings_ack, 1),
2279 CreateMockWrite(*req1, 2),
2280 CreateMockWrite(*req2, 5),
2281 CreateMockWrite(*req3, 8),
2284 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2285 // streams to 1.
2286 scoped_ptr<SpdyFrame> settings_frame(
2287 spdy_util_.ConstructSpdySettings(new_settings));
2289 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2290 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2292 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2293 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2295 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
2296 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2298 MockRead reads[] = {
2299 CreateMockRead(*settings_frame),
2300 CreateMockRead(*resp1, 3),
2301 CreateMockRead(*body1, 4),
2302 CreateMockRead(*resp2, 6),
2303 CreateMockRead(*body2, 7),
2304 CreateMockRead(*resp3, 9),
2305 CreateMockRead(*body3, 10),
2306 MockRead(ASYNC, 0, 11) // EOF
2309 DeterministicSocketData data(reads, arraysize(reads),
2310 writes, arraysize(writes));
2311 data.set_connect_data(connect_data);
2312 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2314 CreateDeterministicNetworkSession();
2316 base::WeakPtr<SpdySession> session =
2317 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2319 // Read the settings frame.
2320 data.RunFor(1);
2322 GURL url1(kDefaultURL);
2323 base::WeakPtr<SpdyStream> spdy_stream1 =
2324 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2325 session, url1, LOWEST, BoundNetLog());
2326 ASSERT_TRUE(spdy_stream1.get() != NULL);
2327 EXPECT_EQ(0u, spdy_stream1->stream_id());
2328 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2329 spdy_stream1->SetDelegate(&delegate1);
2331 TestCompletionCallback callback2;
2332 GURL url2(kDefaultURL);
2333 SpdyStreamRequest request2;
2334 ASSERT_EQ(ERR_IO_PENDING,
2335 request2.StartRequest(
2336 SPDY_REQUEST_RESPONSE_STREAM,
2337 session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2339 TestCompletionCallback callback3;
2340 GURL url3(kDefaultURL);
2341 SpdyStreamRequest request3;
2342 ASSERT_EQ(ERR_IO_PENDING,
2343 request3.StartRequest(
2344 SPDY_REQUEST_RESPONSE_STREAM,
2345 session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2347 EXPECT_EQ(0u, session->num_active_streams());
2348 EXPECT_EQ(1u, session->num_created_streams());
2349 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2351 scoped_ptr<SpdyHeaderBlock> headers(
2352 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2353 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2354 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2356 // Run until 1st stream is activated and then closed.
2357 EXPECT_EQ(0u, delegate1.stream_id());
2358 data.RunFor(4);
2359 EXPECT_EQ(NULL, spdy_stream1.get());
2360 EXPECT_EQ(1u, delegate1.stream_id());
2362 EXPECT_EQ(0u, session->num_active_streams());
2363 EXPECT_EQ(0u, session->num_created_streams());
2364 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2366 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2367 // create the 2nd stream.
2368 base::MessageLoop::current()->RunUntilIdle();
2370 EXPECT_EQ(0u, session->num_active_streams());
2371 EXPECT_EQ(1u, session->num_created_streams());
2372 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2374 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2375 test::StreamDelegateDoNothing delegate2(stream2);
2376 stream2->SetDelegate(&delegate2);
2377 scoped_ptr<SpdyHeaderBlock> headers2(
2378 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2379 stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2380 EXPECT_TRUE(stream2->HasUrlFromHeaders());
2382 // Run until 2nd stream is activated and then closed.
2383 EXPECT_EQ(0u, delegate2.stream_id());
2384 data.RunFor(3);
2385 EXPECT_EQ(NULL, stream2.get());
2386 EXPECT_EQ(3u, delegate2.stream_id());
2388 EXPECT_EQ(0u, session->num_active_streams());
2389 EXPECT_EQ(0u, session->num_created_streams());
2390 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2392 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2393 // create the 3rd stream.
2394 base::MessageLoop::current()->RunUntilIdle();
2396 EXPECT_EQ(0u, session->num_active_streams());
2397 EXPECT_EQ(1u, session->num_created_streams());
2398 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2400 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2401 test::StreamDelegateDoNothing delegate3(stream3);
2402 stream3->SetDelegate(&delegate3);
2403 scoped_ptr<SpdyHeaderBlock> headers3(
2404 spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2405 stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2406 EXPECT_TRUE(stream3->HasUrlFromHeaders());
2408 // Run until 2nd stream is activated and then closed.
2409 EXPECT_EQ(0u, delegate3.stream_id());
2410 data.RunFor(3);
2411 EXPECT_EQ(NULL, stream3.get());
2412 EXPECT_EQ(5u, delegate3.stream_id());
2414 EXPECT_EQ(0u, session->num_active_streams());
2415 EXPECT_EQ(0u, session->num_created_streams());
2416 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2418 data.RunFor(1);
2421 TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2422 session_deps_.host_resolver->set_synchronous_mode(true);
2424 MockRead reads[] = {
2425 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2428 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2429 MockConnect connect_data(SYNCHRONOUS, OK);
2431 data.set_connect_data(connect_data);
2432 session_deps_.socket_factory->AddSocketDataProvider(&data);
2434 CreateNetworkSession();
2436 base::WeakPtr<SpdySession> session =
2437 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2439 // Leave room for only one more stream to be created.
2440 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2441 base::WeakPtr<SpdyStream> spdy_stream =
2442 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2443 session, test_url_, MEDIUM, BoundNetLog());
2444 ASSERT_TRUE(spdy_stream != NULL);
2447 GURL url1(kDefaultURL);
2448 base::WeakPtr<SpdyStream> spdy_stream1 =
2449 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2450 session, url1, LOWEST, BoundNetLog());
2451 ASSERT_TRUE(spdy_stream1.get() != NULL);
2452 EXPECT_EQ(0u, spdy_stream1->stream_id());
2454 TestCompletionCallback callback2;
2455 GURL url2(kDefaultURL);
2456 SpdyStreamRequest request2;
2457 ASSERT_EQ(ERR_IO_PENDING,
2458 request2.StartRequest(
2459 SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2460 callback2.callback()));
2462 TestCompletionCallback callback3;
2463 GURL url3(kDefaultURL);
2464 SpdyStreamRequest request3;
2465 ASSERT_EQ(ERR_IO_PENDING,
2466 request3.StartRequest(
2467 SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2468 callback3.callback()));
2470 EXPECT_EQ(0u, session->num_active_streams());
2471 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2472 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2474 // Cancel the first stream; this will allow the second stream to be created.
2475 EXPECT_TRUE(spdy_stream1.get() != NULL);
2476 spdy_stream1->Cancel();
2477 EXPECT_EQ(NULL, spdy_stream1.get());
2479 EXPECT_EQ(OK, callback2.WaitForResult());
2480 EXPECT_EQ(0u, session->num_active_streams());
2481 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2482 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2484 // Cancel the second stream; this will allow the third stream to be created.
2485 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2486 spdy_stream2->Cancel();
2487 EXPECT_EQ(NULL, spdy_stream2.get());
2489 EXPECT_EQ(OK, callback3.WaitForResult());
2490 EXPECT_EQ(0u, session->num_active_streams());
2491 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2492 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2494 // Cancel the third stream.
2495 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2496 spdy_stream3->Cancel();
2497 EXPECT_EQ(NULL, spdy_stream3.get());
2498 EXPECT_EQ(0u, session->num_active_streams());
2499 EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
2500 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2503 // Test that SpdySession::DoReadLoop reads data from the socket
2504 // without yielding. This test makes 32k - 1 bytes of data available
2505 // on the socket for reading. It then verifies that it has read all
2506 // the available data without yielding.
2507 TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2508 MockConnect connect_data(SYNCHRONOUS, OK);
2509 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2511 scoped_ptr<SpdyFrame> req1(
2512 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2513 MockWrite writes[] = {
2514 CreateMockWrite(*req1, 0),
2517 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2518 // (-spdy_data_frame_size).
2519 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2520 const int kPayloadSize =
2521 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2522 TestDataStream test_stream;
2523 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2524 char* payload_data = payload->data();
2525 test_stream.GetBytes(payload_data, kPayloadSize);
2527 scoped_ptr<SpdyFrame> partial_data_frame(
2528 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2529 scoped_ptr<SpdyFrame> finish_data_frame(
2530 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2532 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2534 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2535 // bytes.
2536 MockRead reads[] = {
2537 CreateMockRead(*resp1, 1),
2538 CreateMockRead(*partial_data_frame, 2),
2539 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2540 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2541 CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2542 MockRead(ASYNC, 0, 6) // EOF
2545 // Create SpdySession and SpdyStream and send the request.
2546 DeterministicSocketData data(reads, arraysize(reads),
2547 writes, arraysize(writes));
2548 data.set_connect_data(connect_data);
2549 session_deps_.host_resolver->set_synchronous_mode(true);
2550 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2552 CreateDeterministicNetworkSession();
2554 base::WeakPtr<SpdySession> session =
2555 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2557 GURL url1(kDefaultURL);
2558 base::WeakPtr<SpdyStream> spdy_stream1 =
2559 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2560 session, url1, MEDIUM, BoundNetLog());
2561 ASSERT_TRUE(spdy_stream1.get() != NULL);
2562 EXPECT_EQ(0u, spdy_stream1->stream_id());
2563 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2564 spdy_stream1->SetDelegate(&delegate1);
2566 scoped_ptr<SpdyHeaderBlock> headers1(
2567 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2568 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2569 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2571 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2572 // post a task.
2573 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2575 // Run until 1st read.
2576 EXPECT_EQ(0u, delegate1.stream_id());
2577 data.RunFor(2);
2578 EXPECT_EQ(1u, delegate1.stream_id());
2579 EXPECT_EQ(0u, observer.executed_count());
2581 // Read all the data and verify SpdySession::DoReadLoop has not
2582 // posted a task.
2583 data.RunFor(4);
2584 EXPECT_EQ(NULL, spdy_stream1.get());
2586 // Verify task observer's executed_count is zero, which indicates DoRead read
2587 // all the available data.
2588 EXPECT_EQ(0u, observer.executed_count());
2589 EXPECT_TRUE(data.at_write_eof());
2590 EXPECT_TRUE(data.at_read_eof());
2593 // Test that SpdySession::DoReadLoop yields while reading the
2594 // data. This test makes 32k + 1 bytes of data available on the socket
2595 // for reading. It then verifies that DoRead has yielded even though
2596 // there is data available for it to read (i.e, socket()->Read didn't
2597 // return ERR_IO_PENDING during socket reads).
2598 TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2599 MockConnect connect_data(SYNCHRONOUS, OK);
2600 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2602 scoped_ptr<SpdyFrame> req1(
2603 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2604 MockWrite writes[] = {
2605 CreateMockWrite(*req1, 0),
2608 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2609 // (-spdy_data_frame_size).
2610 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2611 const int kPayloadSize =
2612 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2613 TestDataStream test_stream;
2614 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2615 char* payload_data = payload->data();
2616 test_stream.GetBytes(payload_data, kPayloadSize);
2618 scoped_ptr<SpdyFrame> partial_data_frame(
2619 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2620 scoped_ptr<SpdyFrame> finish_data_frame(
2621 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2623 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2625 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2626 MockRead reads[] = {
2627 CreateMockRead(*resp1, 1),
2628 CreateMockRead(*partial_data_frame, 2),
2629 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2630 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2631 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2632 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2633 MockRead(ASYNC, 0, 7) // EOF
2636 // Create SpdySession and SpdyStream and send the request.
2637 DeterministicSocketData data(reads, arraysize(reads),
2638 writes, arraysize(writes));
2639 data.set_connect_data(connect_data);
2640 session_deps_.host_resolver->set_synchronous_mode(true);
2641 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2643 CreateDeterministicNetworkSession();
2645 base::WeakPtr<SpdySession> session =
2646 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2648 GURL url1(kDefaultURL);
2649 base::WeakPtr<SpdyStream> spdy_stream1 =
2650 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2651 session, url1, MEDIUM, BoundNetLog());
2652 ASSERT_TRUE(spdy_stream1.get() != NULL);
2653 EXPECT_EQ(0u, spdy_stream1->stream_id());
2654 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2655 spdy_stream1->SetDelegate(&delegate1);
2657 scoped_ptr<SpdyHeaderBlock> headers1(
2658 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2659 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2660 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2662 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2663 // task.
2664 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2666 // Run until 1st read.
2667 EXPECT_EQ(0u, delegate1.stream_id());
2668 data.RunFor(2);
2669 EXPECT_EQ(1u, delegate1.stream_id());
2670 EXPECT_EQ(0u, observer.executed_count());
2672 // Read all the data and verify SpdySession::DoReadLoop has posted a
2673 // task.
2674 data.RunFor(6);
2675 EXPECT_EQ(NULL, spdy_stream1.get());
2677 // Verify task observer's executed_count is 1, which indicates DoRead has
2678 // posted only one task and thus yielded though there is data available for it
2679 // to read.
2680 EXPECT_EQ(1u, observer.executed_count());
2681 EXPECT_TRUE(data.at_write_eof());
2682 EXPECT_TRUE(data.at_read_eof());
2685 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2686 // + async, by doing the following MockReads.
2688 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2689 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2691 // The above reads 26K synchronously. Since that is less that 32K, we
2692 // will attempt to read again. However, that DoRead() will return
2693 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2694 // yield. When we come back, DoRead() will read the results from the
2695 // async read, and rest of the data synchronously.
2696 TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2697 MockConnect connect_data(SYNCHRONOUS, OK);
2698 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2700 scoped_ptr<SpdyFrame> req1(
2701 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2702 MockWrite writes[] = {
2703 CreateMockWrite(*req1, 0),
2706 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2707 // (-spdy_data_frame_size).
2708 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2709 TestDataStream test_stream;
2710 const int kEightKPayloadSize =
2711 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2712 scoped_refptr<net::IOBuffer> eightk_payload(
2713 new net::IOBuffer(kEightKPayloadSize));
2714 char* eightk_payload_data = eightk_payload->data();
2715 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2717 // Build buffer of 2k size.
2718 TestDataStream test_stream2;
2719 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2720 scoped_refptr<net::IOBuffer> twok_payload(
2721 new net::IOBuffer(kTwoKPayloadSize));
2722 char* twok_payload_data = twok_payload->data();
2723 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2725 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2726 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2727 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2728 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2729 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2730 1, "h", 1, DATA_FLAG_FIN));
2732 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2734 MockRead reads[] = {
2735 CreateMockRead(*resp1, 1),
2736 CreateMockRead(*eightk_data_frame, 2),
2737 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
2738 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2739 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
2740 CreateMockRead(*eightk_data_frame, 6, ASYNC),
2741 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
2742 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2743 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2744 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
2745 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
2746 MockRead(ASYNC, 0, 12) // EOF
2749 // Create SpdySession and SpdyStream and send the request.
2750 DeterministicSocketData data(reads, arraysize(reads),
2751 writes, arraysize(writes));
2752 data.set_connect_data(connect_data);
2753 session_deps_.host_resolver->set_synchronous_mode(true);
2754 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2756 CreateDeterministicNetworkSession();
2758 base::WeakPtr<SpdySession> session =
2759 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2761 GURL url1(kDefaultURL);
2762 base::WeakPtr<SpdyStream> spdy_stream1 =
2763 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2764 session, url1, MEDIUM, BoundNetLog());
2765 ASSERT_TRUE(spdy_stream1.get() != NULL);
2766 EXPECT_EQ(0u, spdy_stream1->stream_id());
2767 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2768 spdy_stream1->SetDelegate(&delegate1);
2770 scoped_ptr<SpdyHeaderBlock> headers1(
2771 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2772 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2773 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2775 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2776 // posting of tasks.
2777 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2779 // Run until 1st read.
2780 EXPECT_EQ(0u, delegate1.stream_id());
2781 data.RunFor(2);
2782 EXPECT_EQ(1u, delegate1.stream_id());
2783 EXPECT_EQ(0u, observer.executed_count());
2785 // Read all the data and verify SpdySession::DoReadLoop has posted a
2786 // task.
2787 data.RunFor(12);
2788 EXPECT_EQ(NULL, spdy_stream1.get());
2790 // Verify task observer's executed_count is 1, which indicates DoRead has
2791 // posted only one task and thus yielded though there is data available for
2792 // it to read.
2793 EXPECT_EQ(1u, observer.executed_count());
2794 EXPECT_TRUE(data.at_write_eof());
2795 EXPECT_TRUE(data.at_read_eof());
2798 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2799 // nothing blows up.
2800 TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
2801 MockConnect connect_data(SYNCHRONOUS, OK);
2802 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2804 scoped_ptr<SpdyFrame> req1(
2805 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2806 MockWrite writes[] = {
2807 CreateMockWrite(*req1, 0),
2810 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2811 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2812 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
2814 MockRead reads[] = {
2815 CreateMockRead(*resp1, 1),
2816 CreateMockRead(*body1, 2),
2817 CreateMockRead(*goaway, 3),
2820 // Create SpdySession and SpdyStream and send the request.
2821 DeterministicSocketData data(reads, arraysize(reads),
2822 writes, arraysize(writes));
2823 data.set_connect_data(connect_data);
2824 session_deps_.host_resolver->set_synchronous_mode(true);
2825 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2827 CreateDeterministicNetworkSession();
2829 base::WeakPtr<SpdySession> session =
2830 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2832 GURL url1(kDefaultURL);
2833 base::WeakPtr<SpdyStream> spdy_stream1 =
2834 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2835 session, url1, MEDIUM, BoundNetLog());
2836 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2837 spdy_stream1->SetDelegate(&delegate1);
2838 ASSERT_TRUE(spdy_stream1.get() != NULL);
2839 EXPECT_EQ(0u, spdy_stream1->stream_id());
2841 scoped_ptr<SpdyHeaderBlock> headers1(
2842 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2843 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2844 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2846 // Run until 1st read.
2847 EXPECT_EQ(0u, spdy_stream1->stream_id());
2848 data.RunFor(1);
2849 EXPECT_EQ(1u, spdy_stream1->stream_id());
2851 // Run until GoAway.
2852 data.RunFor(3);
2853 EXPECT_EQ(NULL, spdy_stream1.get());
2854 EXPECT_TRUE(data.at_write_eof());
2855 EXPECT_TRUE(data.at_read_eof());
2856 EXPECT_TRUE(session == NULL);
2859 // Within this framework, a SpdySession should be initialized with
2860 // flow control disabled for protocol version 2, with flow control
2861 // enabled only for streams for protocol version 3, and with flow
2862 // control enabled for streams and sessions for higher versions.
2863 TEST_P(SpdySessionTest, ProtocolNegotiation) {
2864 session_deps_.host_resolver->set_synchronous_mode(true);
2866 MockConnect connect_data(SYNCHRONOUS, OK);
2867 MockRead reads[] = {
2868 MockRead(SYNCHRONOUS, 0, 0) // EOF
2870 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2871 data.set_connect_data(connect_data);
2872 session_deps_.socket_factory->AddSocketDataProvider(&data);
2874 CreateNetworkSession();
2875 base::WeakPtr<SpdySession> session =
2876 CreateFakeSpdySession(spdy_session_pool_, key_);
2878 EXPECT_EQ(spdy_util_.spdy_version(),
2879 session->buffered_spdy_framer_->protocol_version());
2880 if (GetParam() == kProtoDeprecatedSPDY2) {
2881 EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state());
2882 EXPECT_EQ(0, session->session_send_window_size_);
2883 EXPECT_EQ(0, session->session_recv_window_size_);
2884 } else if (GetParam() == kProtoSPDY3) {
2885 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
2886 EXPECT_EQ(0, session->session_send_window_size_);
2887 EXPECT_EQ(0, session->session_recv_window_size_);
2888 } else {
2889 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
2890 session->flow_control_state());
2891 EXPECT_EQ(kSpdySessionInitialWindowSize,
2892 session->session_send_window_size_);
2893 EXPECT_EQ(kSpdySessionInitialWindowSize,
2894 session->session_recv_window_size_);
2896 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2899 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2900 // pointers to the idle session are currently held.
2901 TEST_P(SpdySessionTest, CloseOneIdleConnection) {
2902 ClientSocketPoolManager::set_max_sockets_per_group(
2903 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2904 ClientSocketPoolManager::set_max_sockets_per_pool(
2905 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2907 MockConnect connect_data(SYNCHRONOUS, OK);
2908 MockRead reads[] = {
2909 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2911 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2912 data.set_connect_data(connect_data);
2913 session_deps_.socket_factory->AddSocketDataProvider(&data);
2914 session_deps_.socket_factory->AddSocketDataProvider(&data);
2916 CreateNetworkSession();
2918 TransportClientSocketPool* pool =
2919 http_session_->GetTransportSocketPool(
2920 HttpNetworkSession::NORMAL_SOCKET_POOL);
2922 // Create an idle SPDY session.
2923 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2924 PRIVACY_MODE_DISABLED);
2925 base::WeakPtr<SpdySession> session1 =
2926 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2927 EXPECT_FALSE(pool->IsStalled());
2929 // Trying to create a new connection should cause the pool to be stalled, and
2930 // post a task asynchronously to try and close the session.
2931 TestCompletionCallback callback2;
2932 HostPortPair host_port2("2.com", 80);
2933 scoped_refptr<TransportSocketParams> params2(
2934 new TransportSocketParams(host_port2, false, false,
2935 OnHostResolutionCallback()));
2936 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
2937 EXPECT_EQ(ERR_IO_PENDING,
2938 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
2939 callback2.callback(), pool, BoundNetLog()));
2940 EXPECT_TRUE(pool->IsStalled());
2942 // The socket pool should close the connection asynchronously and establish a
2943 // new connection.
2944 EXPECT_EQ(OK, callback2.WaitForResult());
2945 EXPECT_FALSE(pool->IsStalled());
2946 EXPECT_TRUE(session1 == NULL);
2949 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2950 // pointers to the idle session are currently held, in the case the SPDY session
2951 // has an alias.
2952 TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
2953 ClientSocketPoolManager::set_max_sockets_per_group(
2954 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2955 ClientSocketPoolManager::set_max_sockets_per_pool(
2956 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2958 MockConnect connect_data(SYNCHRONOUS, OK);
2959 MockRead reads[] = {
2960 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2962 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2963 data.set_connect_data(connect_data);
2964 session_deps_.socket_factory->AddSocketDataProvider(&data);
2965 session_deps_.socket_factory->AddSocketDataProvider(&data);
2967 session_deps_.host_resolver->set_synchronous_mode(true);
2968 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2969 "1.com", "192.168.0.2", std::string());
2970 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2971 "2.com", "192.168.0.2", std::string());
2972 // Not strictly needed.
2973 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2974 "3.com", "192.168.0.3", std::string());
2976 CreateNetworkSession();
2978 TransportClientSocketPool* pool =
2979 http_session_->GetTransportSocketPool(
2980 HttpNetworkSession::NORMAL_SOCKET_POOL);
2982 // Create an idle SPDY session.
2983 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2984 PRIVACY_MODE_DISABLED);
2985 base::WeakPtr<SpdySession> session1 =
2986 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2987 EXPECT_FALSE(pool->IsStalled());
2989 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
2990 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
2991 PRIVACY_MODE_DISABLED);
2992 HostResolver::RequestInfo info(key2.host_port_pair());
2993 AddressList addresses;
2994 // Pre-populate the DNS cache, since a synchronous resolution is required in
2995 // order to create the alias.
2996 session_deps_.host_resolver->Resolve(info,
2997 DEFAULT_PRIORITY,
2998 &addresses,
2999 CompletionCallback(),
3000 NULL,
3001 BoundNetLog());
3002 // Get a session for |key2|, which should return the session created earlier.
3003 base::WeakPtr<SpdySession> session2 =
3004 spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3005 ASSERT_EQ(session1.get(), session2.get());
3006 EXPECT_FALSE(pool->IsStalled());
3008 // Trying to create a new connection should cause the pool to be stalled, and
3009 // post a task asynchronously to try and close the session.
3010 TestCompletionCallback callback3;
3011 HostPortPair host_port3("3.com", 80);
3012 scoped_refptr<TransportSocketParams> params3(
3013 new TransportSocketParams(host_port3, false, false,
3014 OnHostResolutionCallback()));
3015 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3016 EXPECT_EQ(ERR_IO_PENDING,
3017 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3018 callback3.callback(), pool, BoundNetLog()));
3019 EXPECT_TRUE(pool->IsStalled());
3021 // The socket pool should close the connection asynchronously and establish a
3022 // new connection.
3023 EXPECT_EQ(OK, callback3.WaitForResult());
3024 EXPECT_FALSE(pool->IsStalled());
3025 EXPECT_TRUE(session1 == NULL);
3026 EXPECT_TRUE(session2 == NULL);
3029 // Tests that when a SPDY session becomes idle, it closes itself if there is
3030 // a lower layer pool stalled on the per-pool socket limit.
3031 TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3032 ClientSocketPoolManager::set_max_sockets_per_group(
3033 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3034 ClientSocketPoolManager::set_max_sockets_per_pool(
3035 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3037 MockConnect connect_data(SYNCHRONOUS, OK);
3038 MockRead reads[] = {
3039 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3041 scoped_ptr<SpdyFrame> req1(
3042 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3043 scoped_ptr<SpdyFrame> cancel1(
3044 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3045 MockWrite writes[] = {
3046 CreateMockWrite(*req1, 1),
3047 CreateMockWrite(*cancel1, 1),
3049 StaticSocketDataProvider data(reads, arraysize(reads),
3050 writes, arraysize(writes));
3051 data.set_connect_data(connect_data);
3052 session_deps_.socket_factory->AddSocketDataProvider(&data);
3054 MockRead http_reads[] = {
3055 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3057 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
3058 NULL, 0);
3059 http_data.set_connect_data(connect_data);
3060 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3063 CreateNetworkSession();
3065 TransportClientSocketPool* pool =
3066 http_session_->GetTransportSocketPool(
3067 HttpNetworkSession::NORMAL_SOCKET_POOL);
3069 // Create a SPDY session.
3070 GURL url1(kDefaultURL);
3071 SpdySessionKey key1(HostPortPair(url1.host(), 80),
3072 ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3073 base::WeakPtr<SpdySession> session1 =
3074 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3075 EXPECT_FALSE(pool->IsStalled());
3077 // Create a stream using the session, and send a request.
3079 TestCompletionCallback callback1;
3080 base::WeakPtr<SpdyStream> spdy_stream1 =
3081 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3082 session1, url1, DEFAULT_PRIORITY,
3083 BoundNetLog());
3084 ASSERT_TRUE(spdy_stream1.get());
3085 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3086 spdy_stream1->SetDelegate(&delegate1);
3088 scoped_ptr<SpdyHeaderBlock> headers1(
3089 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3090 EXPECT_EQ(ERR_IO_PENDING,
3091 spdy_stream1->SendRequestHeaders(
3092 headers1.Pass(), NO_MORE_DATA_TO_SEND));
3093 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3095 base::MessageLoop::current()->RunUntilIdle();
3097 // Trying to create a new connection should cause the pool to be stalled, and
3098 // post a task asynchronously to try and close the session.
3099 TestCompletionCallback callback2;
3100 HostPortPair host_port2("2.com", 80);
3101 scoped_refptr<TransportSocketParams> params2(
3102 new TransportSocketParams(host_port2, false, false,
3103 OnHostResolutionCallback()));
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 // Running the message loop should cause the socket pool to ask the SPDY
3111 // session to close an idle socket, but since the socket is in use, nothing
3112 // happens.
3113 base::RunLoop().RunUntilIdle();
3114 EXPECT_TRUE(pool->IsStalled());
3115 EXPECT_FALSE(callback2.have_result());
3117 // Cancelling the request should result in the session's socket being
3118 // closed, since the pool is stalled.
3119 ASSERT_TRUE(spdy_stream1.get());
3120 spdy_stream1->Cancel();
3121 base::RunLoop().RunUntilIdle();
3122 ASSERT_FALSE(pool->IsStalled());
3123 EXPECT_EQ(OK, callback2.WaitForResult());
3126 // Verify that SpdySessionKey and therefore SpdySession is different when
3127 // privacy mode is enabled or disabled.
3128 TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3129 CreateDeterministicNetworkSession();
3131 HostPortPair host_port_pair("www.google.com", 443);
3132 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3133 PRIVACY_MODE_ENABLED);
3134 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3135 PRIVACY_MODE_DISABLED);
3137 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3138 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3140 // Add SpdySession with PrivacyMode Enabled to the pool.
3141 base::WeakPtr<SpdySession> session_privacy_enabled =
3142 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3144 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3145 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3147 // Add SpdySession with PrivacyMode Disabled to the pool.
3148 base::WeakPtr<SpdySession> session_privacy_disabled =
3149 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3151 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3152 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3154 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3155 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3156 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3158 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3159 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3160 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3163 // Delegate that creates another stream when its stream is closed.
3164 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3165 public:
3166 StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3167 const base::WeakPtr<SpdySession>& session)
3168 : StreamDelegateDoNothing(stream),
3169 session_(session) {}
3171 virtual ~StreamCreatingDelegate() {}
3173 virtual void OnClose(int status) OVERRIDE {
3174 GURL url(kDefaultURL);
3175 ignore_result(
3176 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3177 session_, url, MEDIUM, BoundNetLog()));
3180 private:
3181 const base::WeakPtr<SpdySession> session_;
3184 // Create another stream in response to a stream being reset. Nothing
3185 // should blow up. This is a regression test for
3186 // http://crbug.com/263690 .
3187 TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3188 session_deps_.host_resolver->set_synchronous_mode(true);
3190 MockConnect connect_data(SYNCHRONOUS, OK);
3192 scoped_ptr<SpdyFrame> req(
3193 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3194 MockWrite writes[] = {
3195 CreateMockWrite(*req, 0),
3198 scoped_ptr<SpdyFrame> rst(
3199 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3200 MockRead reads[] = {
3201 CreateMockRead(*rst, 1),
3202 MockRead(ASYNC, 0, 2) // EOF
3204 DeterministicSocketData data(reads, arraysize(reads),
3205 writes, arraysize(writes));
3206 data.set_connect_data(connect_data);
3207 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3209 CreateDeterministicNetworkSession();
3211 base::WeakPtr<SpdySession> session =
3212 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3214 GURL url(kDefaultURL);
3215 base::WeakPtr<SpdyStream> spdy_stream =
3216 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3217 session, url, MEDIUM, BoundNetLog());
3218 ASSERT_TRUE(spdy_stream.get() != NULL);
3219 EXPECT_EQ(0u, spdy_stream->stream_id());
3221 StreamCreatingDelegate delegate(spdy_stream, session);
3222 spdy_stream->SetDelegate(&delegate);
3224 scoped_ptr<SpdyHeaderBlock> headers(
3225 spdy_util_.ConstructGetHeaderBlock(url.spec()));
3226 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3227 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3229 EXPECT_EQ(0u, spdy_stream->stream_id());
3231 data.RunFor(1);
3233 EXPECT_EQ(1u, spdy_stream->stream_id());
3235 // Cause the stream to be reset, which should cause another stream
3236 // to be created.
3237 data.RunFor(1);
3239 EXPECT_EQ(NULL, spdy_stream.get());
3240 EXPECT_TRUE(delegate.StreamIsClosed());
3241 EXPECT_EQ(0u, session->num_active_streams());
3242 EXPECT_EQ(1u, session->num_created_streams());
3245 // The tests below are only for SPDY/3 and above.
3247 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3248 if (GetParam() < kProtoSPDY3)
3249 return;
3251 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3252 // gets sent.
3253 SettingsMap new_settings;
3254 int32 window_size = 1;
3255 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3256 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3258 // Set up the socket so we read a SETTINGS frame that sets
3259 // INITIAL_WINDOW_SIZE.
3260 MockConnect connect_data(SYNCHRONOUS, OK);
3261 scoped_ptr<SpdyFrame> settings_frame(
3262 spdy_util_.ConstructSpdySettings(new_settings));
3263 MockRead reads[] = {
3264 CreateMockRead(*settings_frame, 0),
3265 MockRead(ASYNC, 0, 1) // EOF
3268 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3269 MockWrite writes[] = {
3270 CreateMockWrite(*settings_ack, 2),
3273 session_deps_.host_resolver->set_synchronous_mode(true);
3275 DeterministicSocketData data(reads, arraysize(reads),
3276 writes, arraysize(writes));
3277 data.set_connect_data(connect_data);
3278 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3280 CreateDeterministicNetworkSession();
3282 base::WeakPtr<SpdySession> session =
3283 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3284 base::WeakPtr<SpdyStream> spdy_stream1 =
3285 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3286 session, test_url_, MEDIUM, BoundNetLog());
3287 ASSERT_TRUE(spdy_stream1.get() != NULL);
3288 TestCompletionCallback callback1;
3289 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3291 data.RunFor(1); // Process the SETTINGS frame, but not the EOF
3292 base::MessageLoop::current()->RunUntilIdle();
3293 EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3294 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3296 // Release the first one, this will allow the second to be created.
3297 spdy_stream1->Cancel();
3298 EXPECT_EQ(NULL, spdy_stream1.get());
3300 base::WeakPtr<SpdyStream> spdy_stream2 =
3301 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3302 session, test_url_, MEDIUM, BoundNetLog());
3303 ASSERT_TRUE(spdy_stream2.get() != NULL);
3304 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3305 spdy_stream2->Cancel();
3306 EXPECT_EQ(NULL, spdy_stream2.get());
3309 // The tests below are only for SPDY/3.1 and above.
3311 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3312 // adjust the session receive window size for SPDY 3.1 and higher. In
3313 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3314 // sending a WINDOW_UPDATE frame for a large enough delta.
3315 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3316 if (GetParam() < kProtoSPDY31)
3317 return;
3319 session_deps_.host_resolver->set_synchronous_mode(true);
3321 const int32 delta_window_size = 100;
3323 MockConnect connect_data(SYNCHRONOUS, OK);
3324 MockRead reads[] = {
3325 MockRead(ASYNC, 0, 1) // EOF
3327 scoped_ptr<SpdyFrame> window_update(
3328 spdy_util_.ConstructSpdyWindowUpdate(
3329 kSessionFlowControlStreamId,
3330 kSpdySessionInitialWindowSize + delta_window_size));
3331 MockWrite writes[] = {
3332 CreateMockWrite(*window_update, 0),
3334 DeterministicSocketData data(reads, arraysize(reads),
3335 writes, arraysize(writes));
3336 data.set_connect_data(connect_data);
3337 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3339 CreateDeterministicNetworkSession();
3340 base::WeakPtr<SpdySession> session =
3341 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3342 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3343 session->flow_control_state());
3345 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3346 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3348 session->IncreaseRecvWindowSize(delta_window_size);
3349 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3350 session->session_recv_window_size_);
3351 EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3353 // Should trigger sending a WINDOW_UPDATE frame.
3354 session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize);
3355 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size +
3356 kSpdySessionInitialWindowSize,
3357 session->session_recv_window_size_);
3358 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3360 data.RunFor(1);
3362 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3363 session->in_io_loop_ = true;
3364 session->DecreaseRecvWindowSize(
3365 kSpdySessionInitialWindowSize + delta_window_size +
3366 kSpdySessionInitialWindowSize);
3367 session->in_io_loop_ = false;
3368 EXPECT_EQ(0, session->session_recv_window_size_);
3369 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3372 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3373 // adjust the session send window size when the "enable_spdy_31" flag
3374 // is set.
3375 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3376 if (GetParam() < kProtoSPDY31)
3377 return;
3379 session_deps_.host_resolver->set_synchronous_mode(true);
3381 MockConnect connect_data(SYNCHRONOUS, OK);
3382 MockRead reads[] = {
3383 MockRead(SYNCHRONOUS, 0, 0) // EOF
3385 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3386 data.set_connect_data(connect_data);
3387 session_deps_.socket_factory->AddSocketDataProvider(&data);
3389 CreateNetworkSession();
3390 base::WeakPtr<SpdySession> session =
3391 CreateFakeSpdySession(spdy_session_pool_, key_);
3392 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3393 session->flow_control_state());
3395 const int32 delta_window_size = 100;
3397 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3399 session->IncreaseSendWindowSize(delta_window_size);
3400 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3401 session->session_send_window_size_);
3403 session->DecreaseSendWindowSize(delta_window_size);
3404 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3407 // Incoming data for an inactive stream should not cause the session
3408 // receive window size to decrease, but it should cause the unacked
3409 // bytes to increase.
3410 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3411 if (GetParam() < kProtoSPDY31)
3412 return;
3414 session_deps_.host_resolver->set_synchronous_mode(true);
3416 MockConnect connect_data(SYNCHRONOUS, OK);
3417 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3418 MockRead reads[] = {
3419 CreateMockRead(*resp, 0),
3420 MockRead(ASYNC, 0, 1) // EOF
3422 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3423 data.set_connect_data(connect_data);
3424 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3426 CreateDeterministicNetworkSession();
3427 base::WeakPtr<SpdySession> session =
3428 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3429 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3430 session->flow_control_state());
3432 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3433 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3435 data.RunFor(1);
3437 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3438 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3440 data.RunFor(1);
3443 // A delegate that drops any received data.
3444 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3445 public:
3446 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3447 base::StringPiece data)
3448 : StreamDelegateSendImmediate(stream, data) {}
3450 virtual ~DropReceivedDataDelegate() {}
3452 // Drop any received data.
3453 virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) OVERRIDE {}
3456 // Send data back and forth but use a delegate that drops its received
3457 // data. The receive window should still increase to its original
3458 // value, i.e. we shouldn't "leak" receive window bytes.
3459 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3460 if (GetParam() < kProtoSPDY31)
3461 return;
3463 const char kStreamUrl[] = "http://www.google.com/";
3465 const int32 msg_data_size = 100;
3466 const std::string msg_data(msg_data_size, 'a');
3468 MockConnect connect_data(SYNCHRONOUS, OK);
3470 scoped_ptr<SpdyFrame> req(
3471 spdy_util_.ConstructSpdyPost(
3472 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3473 scoped_ptr<SpdyFrame> msg(
3474 spdy_util_.ConstructSpdyBodyFrame(
3475 1, msg_data.data(), msg_data_size, false));
3476 MockWrite writes[] = {
3477 CreateMockWrite(*req, 0),
3478 CreateMockWrite(*msg, 2),
3481 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3482 scoped_ptr<SpdyFrame> echo(
3483 spdy_util_.ConstructSpdyBodyFrame(
3484 1, msg_data.data(), msg_data_size, false));
3485 scoped_ptr<SpdyFrame> window_update(
3486 spdy_util_.ConstructSpdyWindowUpdate(
3487 kSessionFlowControlStreamId, msg_data_size));
3488 MockRead reads[] = {
3489 CreateMockRead(*resp, 1),
3490 CreateMockRead(*echo, 3),
3491 MockRead(ASYNC, 0, 4) // EOF
3494 // Create SpdySession and SpdyStream and send the request.
3495 DeterministicSocketData data(reads, arraysize(reads),
3496 writes, arraysize(writes));
3497 data.set_connect_data(connect_data);
3498 session_deps_.host_resolver->set_synchronous_mode(true);
3499 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3501 CreateDeterministicNetworkSession();
3503 base::WeakPtr<SpdySession> session =
3504 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3506 GURL url(kStreamUrl);
3507 base::WeakPtr<SpdyStream> stream =
3508 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3509 session, url, MEDIUM, BoundNetLog());
3510 ASSERT_TRUE(stream.get() != NULL);
3511 EXPECT_EQ(0u, stream->stream_id());
3513 DropReceivedDataDelegate delegate(stream, msg_data);
3514 stream->SetDelegate(&delegate);
3516 scoped_ptr<SpdyHeaderBlock> headers(
3517 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3518 EXPECT_EQ(ERR_IO_PENDING,
3519 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3520 EXPECT_TRUE(stream->HasUrlFromHeaders());
3522 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3523 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3525 data.RunFor(4);
3527 EXPECT_TRUE(data.at_write_eof());
3528 EXPECT_TRUE(data.at_read_eof());
3530 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3531 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3533 stream->Close();
3534 EXPECT_EQ(NULL, stream.get());
3536 EXPECT_EQ(OK, delegate.WaitForClose());
3538 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3539 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3542 // Send data back and forth but close the stream before its data frame
3543 // can be written to the socket. The send window should then increase
3544 // to its original value, i.e. we shouldn't "leak" send window bytes.
3545 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3546 if (GetParam() < kProtoSPDY31)
3547 return;
3549 const char kStreamUrl[] = "http://www.google.com/";
3551 const int32 msg_data_size = 100;
3552 const std::string msg_data(msg_data_size, 'a');
3554 MockConnect connect_data(SYNCHRONOUS, OK);
3556 scoped_ptr<SpdyFrame> req(
3557 spdy_util_.ConstructSpdyPost(
3558 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3559 MockWrite writes[] = {
3560 CreateMockWrite(*req, 0),
3563 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3564 MockRead reads[] = {
3565 CreateMockRead(*resp, 1),
3566 MockRead(ASYNC, 0, 2) // EOF
3569 // Create SpdySession and SpdyStream and send the request.
3570 DeterministicSocketData data(reads, arraysize(reads),
3571 writes, arraysize(writes));
3572 data.set_connect_data(connect_data);
3573 session_deps_.host_resolver->set_synchronous_mode(true);
3574 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3576 CreateDeterministicNetworkSession();
3578 base::WeakPtr<SpdySession> session =
3579 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3581 GURL url(kStreamUrl);
3582 base::WeakPtr<SpdyStream> stream =
3583 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3584 session, url, MEDIUM, BoundNetLog());
3585 ASSERT_TRUE(stream.get() != NULL);
3586 EXPECT_EQ(0u, stream->stream_id());
3588 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3589 stream->SetDelegate(&delegate);
3591 scoped_ptr<SpdyHeaderBlock> headers(
3592 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3593 EXPECT_EQ(ERR_IO_PENDING,
3594 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3595 EXPECT_TRUE(stream->HasUrlFromHeaders());
3597 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3599 data.RunFor(1);
3601 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3603 data.RunFor(1);
3605 EXPECT_TRUE(data.at_write_eof());
3606 EXPECT_TRUE(data.at_read_eof());
3608 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3609 session->session_send_window_size_);
3611 // Closing the stream should increase the session's send window.
3612 stream->Close();
3613 EXPECT_EQ(NULL, stream.get());
3615 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3617 EXPECT_EQ(OK, delegate.WaitForClose());
3620 // Send data back and forth; the send and receive windows should
3621 // change appropriately.
3622 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
3623 if (GetParam() < kProtoSPDY31)
3624 return;
3626 const char kStreamUrl[] = "http://www.google.com/";
3628 const int32 msg_data_size = 100;
3629 const std::string msg_data(msg_data_size, 'a');
3631 MockConnect connect_data(SYNCHRONOUS, OK);
3633 scoped_ptr<SpdyFrame> req(
3634 spdy_util_.ConstructSpdyPost(
3635 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3636 scoped_ptr<SpdyFrame> msg(
3637 spdy_util_.ConstructSpdyBodyFrame(
3638 1, msg_data.data(), msg_data_size, false));
3639 MockWrite writes[] = {
3640 CreateMockWrite(*req, 0),
3641 CreateMockWrite(*msg, 2),
3644 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3645 scoped_ptr<SpdyFrame> echo(
3646 spdy_util_.ConstructSpdyBodyFrame(
3647 1, msg_data.data(), msg_data_size, false));
3648 scoped_ptr<SpdyFrame> window_update(
3649 spdy_util_.ConstructSpdyWindowUpdate(
3650 kSessionFlowControlStreamId, msg_data_size));
3651 MockRead reads[] = {
3652 CreateMockRead(*resp, 1),
3653 CreateMockRead(*echo, 3),
3654 CreateMockRead(*window_update, 4),
3655 MockRead(ASYNC, 0, 5) // EOF
3658 // Create SpdySession and SpdyStream and send the request.
3659 DeterministicSocketData data(reads, arraysize(reads),
3660 writes, arraysize(writes));
3661 data.set_connect_data(connect_data);
3662 session_deps_.host_resolver->set_synchronous_mode(true);
3663 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3665 CreateDeterministicNetworkSession();
3667 base::WeakPtr<SpdySession> session =
3668 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3670 GURL url(kStreamUrl);
3671 base::WeakPtr<SpdyStream> stream =
3672 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3673 session, url, MEDIUM, BoundNetLog());
3674 ASSERT_TRUE(stream.get() != NULL);
3675 EXPECT_EQ(0u, stream->stream_id());
3677 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3678 stream->SetDelegate(&delegate);
3680 scoped_ptr<SpdyHeaderBlock> headers(
3681 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3682 EXPECT_EQ(ERR_IO_PENDING,
3683 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3684 EXPECT_TRUE(stream->HasUrlFromHeaders());
3686 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3687 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3688 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3690 data.RunFor(1);
3692 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3693 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3694 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3696 data.RunFor(1);
3698 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3699 session->session_send_window_size_);
3700 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3701 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3703 data.RunFor(1);
3705 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3706 session->session_send_window_size_);
3707 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3708 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3710 data.RunFor(1);
3712 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3713 session->session_send_window_size_);
3714 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3715 session->session_recv_window_size_);
3716 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3718 data.RunFor(1);
3720 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3721 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3722 session->session_recv_window_size_);
3723 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3725 EXPECT_TRUE(data.at_write_eof());
3726 EXPECT_TRUE(data.at_read_eof());
3728 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
3730 // Draining the delegate's read queue should increase the session's
3731 // receive window.
3732 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3733 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3734 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3736 stream->Close();
3737 EXPECT_EQ(NULL, stream.get());
3739 EXPECT_EQ(OK, delegate.WaitForClose());
3741 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3742 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3743 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3746 // Given a stall function and an unstall function, runs a test to make
3747 // sure that a stream resumes after unstall.
3748 void SpdySessionTest::RunResumeAfterUnstallTest(
3749 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
3750 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
3751 unstall_function) {
3752 const char kStreamUrl[] = "http://www.google.com/";
3753 GURL url(kStreamUrl);
3755 session_deps_.host_resolver->set_synchronous_mode(true);
3757 scoped_ptr<SpdyFrame> req(
3758 spdy_util_.ConstructSpdyPost(
3759 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3760 scoped_ptr<SpdyFrame> body(
3761 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3762 MockWrite writes[] = {
3763 CreateMockWrite(*req, 0),
3764 CreateMockWrite(*body, 1),
3767 scoped_ptr<SpdyFrame> resp(
3768 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3769 scoped_ptr<SpdyFrame> echo(
3770 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
3771 MockRead reads[] = {
3772 CreateMockRead(*resp, 2),
3773 MockRead(ASYNC, 0, 0, 3), // EOF
3776 DeterministicSocketData data(reads, arraysize(reads),
3777 writes, arraysize(writes));
3778 MockConnect connect_data(SYNCHRONOUS, OK);
3779 data.set_connect_data(connect_data);
3781 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3783 CreateDeterministicNetworkSession();
3784 base::WeakPtr<SpdySession> session =
3785 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3786 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3787 session->flow_control_state());
3789 base::WeakPtr<SpdyStream> stream =
3790 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3791 session, url, LOWEST, BoundNetLog());
3792 ASSERT_TRUE(stream.get() != NULL);
3794 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
3795 stream->SetDelegate(&delegate);
3797 EXPECT_FALSE(stream->HasUrlFromHeaders());
3798 EXPECT_FALSE(stream->send_stalled_by_flow_control());
3800 scoped_ptr<SpdyHeaderBlock> headers(
3801 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3802 EXPECT_EQ(ERR_IO_PENDING,
3803 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3804 EXPECT_TRUE(stream->HasUrlFromHeaders());
3805 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
3807 stall_function.Run(session.get(), stream.get());
3809 data.RunFor(1);
3811 EXPECT_TRUE(stream->send_stalled_by_flow_control());
3813 unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
3815 EXPECT_FALSE(stream->send_stalled_by_flow_control());
3817 data.RunFor(3);
3819 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
3821 EXPECT_TRUE(delegate.send_headers_completed());
3822 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
3823 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
3824 EXPECT_TRUE(data.at_write_eof());
3827 // Run the resume-after-unstall test with all possible stall and
3828 // unstall sequences.
3830 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
3831 if (GetParam() < kProtoSPDY31)
3832 return;
3834 RunResumeAfterUnstallTest(
3835 base::Bind(&SpdySessionTest::StallSessionOnly,
3836 base::Unretained(this)),
3837 base::Bind(&SpdySessionTest::UnstallSessionOnly,
3838 base::Unretained(this)));
3841 // Equivalent to
3842 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
3843 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
3844 if (GetParam() < kProtoSPDY31)
3845 return;
3847 RunResumeAfterUnstallTest(
3848 base::Bind(&SpdySessionTest::StallStreamOnly,
3849 base::Unretained(this)),
3850 base::Bind(&SpdySessionTest::UnstallStreamOnly,
3851 base::Unretained(this)));
3854 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
3855 if (GetParam() < kProtoSPDY31)
3856 return;
3858 RunResumeAfterUnstallTest(
3859 base::Bind(&SpdySessionTest::StallSessionStream,
3860 base::Unretained(this)),
3861 base::Bind(&SpdySessionTest::UnstallSessionStream,
3862 base::Unretained(this)));
3865 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
3866 if (GetParam() < kProtoSPDY31)
3867 return;
3869 RunResumeAfterUnstallTest(
3870 base::Bind(&SpdySessionTest::StallStreamSession,
3871 base::Unretained(this)),
3872 base::Bind(&SpdySessionTest::UnstallSessionStream,
3873 base::Unretained(this)));
3876 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
3877 if (GetParam() < kProtoSPDY31)
3878 return;
3880 RunResumeAfterUnstallTest(
3881 base::Bind(&SpdySessionTest::StallStreamSession,
3882 base::Unretained(this)),
3883 base::Bind(&SpdySessionTest::UnstallStreamSession,
3884 base::Unretained(this)));
3887 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
3888 if (GetParam() < kProtoSPDY31)
3889 return;
3891 RunResumeAfterUnstallTest(
3892 base::Bind(&SpdySessionTest::StallSessionStream,
3893 base::Unretained(this)),
3894 base::Bind(&SpdySessionTest::UnstallStreamSession,
3895 base::Unretained(this)));
3898 // Cause a stall by reducing the flow control send window to 0. The
3899 // streams should resume in priority order when that window is then
3900 // increased.
3901 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
3902 if (GetParam() < kProtoSPDY31)
3903 return;
3905 const char kStreamUrl[] = "http://www.google.com/";
3906 GURL url(kStreamUrl);
3908 session_deps_.host_resolver->set_synchronous_mode(true);
3910 scoped_ptr<SpdyFrame> req1(
3911 spdy_util_.ConstructSpdyPost(
3912 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3913 scoped_ptr<SpdyFrame> req2(
3914 spdy_util_.ConstructSpdyPost(
3915 kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
3916 scoped_ptr<SpdyFrame> body1(
3917 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3918 scoped_ptr<SpdyFrame> body2(
3919 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
3920 MockWrite writes[] = {
3921 CreateMockWrite(*req1, 0),
3922 CreateMockWrite(*req2, 1),
3923 CreateMockWrite(*body2, 2),
3924 CreateMockWrite(*body1, 3),
3927 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3928 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3929 MockRead reads[] = {
3930 CreateMockRead(*resp1, 4),
3931 CreateMockRead(*resp2, 5),
3932 MockRead(ASYNC, 0, 0, 6), // EOF
3935 DeterministicSocketData data(reads, arraysize(reads),
3936 writes, arraysize(writes));
3937 MockConnect connect_data(SYNCHRONOUS, OK);
3938 data.set_connect_data(connect_data);
3940 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3942 CreateDeterministicNetworkSession();
3943 base::WeakPtr<SpdySession> session =
3944 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3945 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3946 session->flow_control_state());
3948 base::WeakPtr<SpdyStream> stream1 =
3949 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3950 session, url, LOWEST, BoundNetLog());
3951 ASSERT_TRUE(stream1.get() != NULL);
3953 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
3954 stream1->SetDelegate(&delegate1);
3956 EXPECT_FALSE(stream1->HasUrlFromHeaders());
3958 base::WeakPtr<SpdyStream> stream2 =
3959 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3960 session, url, MEDIUM, BoundNetLog());
3961 ASSERT_TRUE(stream2.get() != NULL);
3963 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
3964 stream2->SetDelegate(&delegate2);
3966 EXPECT_FALSE(stream2->HasUrlFromHeaders());
3968 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
3969 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3971 StallSessionSend(session.get());
3973 scoped_ptr<SpdyHeaderBlock> headers1(
3974 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3975 EXPECT_EQ(ERR_IO_PENDING,
3976 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
3977 EXPECT_TRUE(stream1->HasUrlFromHeaders());
3978 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
3980 data.RunFor(1);
3981 EXPECT_EQ(1u, stream1->stream_id());
3982 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
3984 scoped_ptr<SpdyHeaderBlock> headers2(
3985 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3986 EXPECT_EQ(ERR_IO_PENDING,
3987 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
3988 EXPECT_TRUE(stream2->HasUrlFromHeaders());
3989 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
3991 data.RunFor(1);
3992 EXPECT_EQ(3u, stream2->stream_id());
3993 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
3995 // This should unstall only stream2.
3996 UnstallSessionSend(session.get(), kBodyDataSize);
3998 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
3999 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4001 data.RunFor(1);
4003 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4004 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4006 // This should then unstall stream1.
4007 UnstallSessionSend(session.get(), kBodyDataSize);
4009 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4010 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4012 data.RunFor(4);
4014 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4015 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4017 EXPECT_TRUE(delegate1.send_headers_completed());
4018 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4019 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4021 EXPECT_TRUE(delegate2.send_headers_completed());
4022 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4023 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4025 EXPECT_TRUE(data.at_write_eof());
4028 // Delegate that closes a given stream after sending its body.
4029 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4030 public:
4031 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4032 base::StringPiece data)
4033 : StreamDelegateWithBody(stream, data) {}
4035 virtual ~StreamClosingDelegate() {}
4037 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4038 stream_to_close_ = stream_to_close;
4041 virtual void OnDataSent() OVERRIDE {
4042 test::StreamDelegateWithBody::OnDataSent();
4043 if (stream_to_close_.get()) {
4044 stream_to_close_->Close();
4045 EXPECT_EQ(NULL, stream_to_close_.get());
4049 private:
4050 base::WeakPtr<SpdyStream> stream_to_close_;
4053 // Cause a stall by reducing the flow control send window to
4054 // 0. Unstalling the session should properly handle deleted streams.
4055 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4056 if (GetParam() < kProtoSPDY31)
4057 return;
4059 const char kStreamUrl[] = "http://www.google.com/";
4060 GURL url(kStreamUrl);
4062 session_deps_.host_resolver->set_synchronous_mode(true);
4064 scoped_ptr<SpdyFrame> req1(
4065 spdy_util_.ConstructSpdyPost(
4066 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4067 scoped_ptr<SpdyFrame> req2(
4068 spdy_util_.ConstructSpdyPost(
4069 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4070 scoped_ptr<SpdyFrame> req3(
4071 spdy_util_.ConstructSpdyPost(
4072 kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
4073 scoped_ptr<SpdyFrame> body2(
4074 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4075 MockWrite writes[] = {
4076 CreateMockWrite(*req1, 0),
4077 CreateMockWrite(*req2, 1),
4078 CreateMockWrite(*req3, 2),
4079 CreateMockWrite(*body2, 3),
4082 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4083 MockRead reads[] = {
4084 CreateMockRead(*resp2, 4),
4085 MockRead(ASYNC, 0, 0, 5), // EOF
4088 DeterministicSocketData data(reads, arraysize(reads),
4089 writes, arraysize(writes));
4090 MockConnect connect_data(SYNCHRONOUS, OK);
4091 data.set_connect_data(connect_data);
4093 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4095 CreateDeterministicNetworkSession();
4096 base::WeakPtr<SpdySession> session =
4097 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4098 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4099 session->flow_control_state());
4101 base::WeakPtr<SpdyStream> stream1 =
4102 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4103 session, url, LOWEST, BoundNetLog());
4104 ASSERT_TRUE(stream1.get() != NULL);
4106 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4107 stream1->SetDelegate(&delegate1);
4109 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4111 base::WeakPtr<SpdyStream> stream2 =
4112 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4113 session, url, LOWEST, BoundNetLog());
4114 ASSERT_TRUE(stream2.get() != NULL);
4116 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4117 stream2->SetDelegate(&delegate2);
4119 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4121 base::WeakPtr<SpdyStream> stream3 =
4122 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4123 session, url, LOWEST, BoundNetLog());
4124 ASSERT_TRUE(stream3.get() != NULL);
4126 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4127 stream3->SetDelegate(&delegate3);
4129 EXPECT_FALSE(stream3->HasUrlFromHeaders());
4131 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4132 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4133 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4135 StallSessionSend(session.get());
4137 scoped_ptr<SpdyHeaderBlock> headers1(
4138 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4139 EXPECT_EQ(ERR_IO_PENDING,
4140 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4141 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4142 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4144 data.RunFor(1);
4145 EXPECT_EQ(1u, stream1->stream_id());
4146 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4148 scoped_ptr<SpdyHeaderBlock> headers2(
4149 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4150 EXPECT_EQ(ERR_IO_PENDING,
4151 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4152 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4153 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4155 data.RunFor(1);
4156 EXPECT_EQ(3u, stream2->stream_id());
4157 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4159 scoped_ptr<SpdyHeaderBlock> headers3(
4160 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4161 EXPECT_EQ(ERR_IO_PENDING,
4162 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4163 EXPECT_TRUE(stream3->HasUrlFromHeaders());
4164 EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4166 data.RunFor(1);
4167 EXPECT_EQ(5u, stream3->stream_id());
4168 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4170 SpdyStreamId stream_id1 = stream1->stream_id();
4171 SpdyStreamId stream_id2 = stream2->stream_id();
4172 SpdyStreamId stream_id3 = stream3->stream_id();
4174 // Close stream1 preemptively.
4175 session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4176 EXPECT_EQ(NULL, stream1.get());
4178 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4179 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4180 EXPECT_TRUE(session->IsStreamActive(stream_id3));
4182 // Unstall stream2, which should then close stream3.
4183 delegate2.set_stream_to_close(stream3);
4184 UnstallSessionSend(session.get(), kBodyDataSize);
4186 data.RunFor(1);
4187 EXPECT_EQ(NULL, stream3.get());
4189 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4190 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4191 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4192 EXPECT_FALSE(session->IsStreamActive(stream_id3));
4194 data.RunFor(2);
4195 EXPECT_EQ(NULL, stream2.get());
4197 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4198 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4199 EXPECT_EQ(OK, delegate3.WaitForClose());
4201 EXPECT_TRUE(delegate1.send_headers_completed());
4202 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4204 EXPECT_TRUE(delegate2.send_headers_completed());
4205 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4206 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4208 EXPECT_TRUE(delegate3.send_headers_completed());
4209 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4211 EXPECT_TRUE(data.at_write_eof());
4214 // Cause a stall by reducing the flow control send window to
4215 // 0. Unstalling the session should properly handle the session itself
4216 // being closed.
4217 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4218 if (GetParam() < kProtoSPDY31)
4219 return;
4221 const char kStreamUrl[] = "http://www.google.com/";
4222 GURL url(kStreamUrl);
4224 session_deps_.host_resolver->set_synchronous_mode(true);
4226 scoped_ptr<SpdyFrame> req1(
4227 spdy_util_.ConstructSpdyPost(
4228 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4229 scoped_ptr<SpdyFrame> req2(
4230 spdy_util_.ConstructSpdyPost(
4231 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4232 scoped_ptr<SpdyFrame> body1(
4233 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4234 MockWrite writes[] = {
4235 CreateMockWrite(*req1, 0),
4236 CreateMockWrite(*req2, 1),
4239 MockRead reads[] = {
4240 MockRead(ASYNC, 0, 0, 2), // EOF
4243 DeterministicSocketData data(reads, arraysize(reads),
4244 writes, arraysize(writes));
4245 MockConnect connect_data(SYNCHRONOUS, OK);
4246 data.set_connect_data(connect_data);
4248 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4250 CreateDeterministicNetworkSession();
4251 base::WeakPtr<SpdySession> session =
4252 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4253 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4254 session->flow_control_state());
4256 base::WeakPtr<SpdyStream> stream1 =
4257 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4258 session, url, LOWEST, BoundNetLog());
4259 ASSERT_TRUE(stream1.get() != NULL);
4261 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4262 stream1->SetDelegate(&delegate1);
4264 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4266 base::WeakPtr<SpdyStream> stream2 =
4267 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4268 session, url, LOWEST, BoundNetLog());
4269 ASSERT_TRUE(stream2.get() != NULL);
4271 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4272 stream2->SetDelegate(&delegate2);
4274 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4276 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4277 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4279 StallSessionSend(session.get());
4281 scoped_ptr<SpdyHeaderBlock> headers1(
4282 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4283 EXPECT_EQ(ERR_IO_PENDING,
4284 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4285 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4286 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4288 data.RunFor(1);
4289 EXPECT_EQ(1u, stream1->stream_id());
4290 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4292 scoped_ptr<SpdyHeaderBlock> headers2(
4293 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4294 EXPECT_EQ(ERR_IO_PENDING,
4295 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4296 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4297 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4299 data.RunFor(1);
4300 EXPECT_EQ(3u, stream2->stream_id());
4301 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4303 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4305 // Unstall stream1.
4306 UnstallSessionSend(session.get(), kBodyDataSize);
4308 // Close the session (since we can't do it from within the delegate
4309 // method, since it's in the stream's loop).
4310 session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4311 EXPECT_TRUE(session == NULL);
4313 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4315 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4316 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4318 EXPECT_TRUE(delegate1.send_headers_completed());
4319 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4321 EXPECT_TRUE(delegate2.send_headers_completed());
4322 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4324 EXPECT_TRUE(data.at_write_eof());
4327 TEST(MapFramerErrorToProtocolError, MapsValues) {
4328 CHECK_EQ(SPDY_ERROR_INVALID_CONTROL_FRAME,
4329 MapFramerErrorToProtocolError(
4330 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4331 CHECK_EQ(SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4332 MapFramerErrorToProtocolError(
4333 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4334 CHECK_EQ(SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
4335 MapFramerErrorToProtocolError(
4336 SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
4337 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
4338 MapFramerErrorToProtocolError(
4339 SpdyFramer::SPDY_UNEXPECTED_FRAME));
4342 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
4343 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
4344 MapRstStreamStatusToProtocolError(
4345 RST_STREAM_PROTOCOL_ERROR));
4346 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
4347 MapRstStreamStatusToProtocolError(
4348 RST_STREAM_FRAME_SIZE_ERROR));
4349 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
4350 MapRstStreamStatusToProtocolError(
4351 RST_STREAM_ENHANCE_YOUR_CALM));
4354 } // namespace net