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.
4
5 #include "net/spdy/spdy_session.h"
6
7 #include "base/base64.h"
8 #include "base/bind.h"
9 #include "base/callback.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/test/histogram_tester.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/ip_endpoint.h"
15 #include "net/base/net_log_unittest.h"
16 #include "net/base/request_priority.h"
17 #include "net/base/test_data_directory.h"
18 #include "net/base/test_data_stream.h"
19 #include "net/socket/client_socket_pool_manager.h"
20 #include "net/socket/next_proto.h"
21 #include "net/socket/socket_test_util.h"
22 #include "net/spdy/spdy_http_utils.h"
23 #include "net/spdy/spdy_session_pool.h"
24 #include "net/spdy/spdy_session_test_util.h"
25 #include "net/spdy/spdy_stream.h"
26 #include "net/spdy/spdy_stream_test_util.h"
27 #include "net/spdy/spdy_test_util_common.h"
28 #include "net/spdy/spdy_test_utils.h"
29 #include "net/test/cert_test_util.h"
30 #include "testing/platform_test.h"
31
32 namespace net {
33
34 namespace {
35
36 static const char kTestUrl[] = "http://www.example.org/";
37 static const char kTestHost[] = "www.example.org";
38 static const int kTestPort = 80;
39
40 const char kBodyData[] = "Body data";
41 const size_t kBodyDataSize = arraysize(kBodyData);
42 const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize);
43
44 static base::TimeDelta g_time_delta;
TheNearFuture()45 base::TimeTicks TheNearFuture() {
46 return base::TimeTicks::Now() + g_time_delta;
47 }
48
49 } // namespace
50
51 class SpdySessionTest : public PlatformTest,
52 public ::testing::WithParamInterface<NextProto> {
53 public:
54 // Functions used with RunResumeAfterUnstallTest().
55
StallSessionOnly(SpdySession * session,SpdyStream * stream)56 void StallSessionOnly(SpdySession* session, SpdyStream* stream) {
57 StallSessionSend(session);
58 }
59
StallStreamOnly(SpdySession * session,SpdyStream * stream)60 void StallStreamOnly(SpdySession* session, SpdyStream* stream) {
61 StallStreamSend(stream);
62 }
63
StallSessionStream(SpdySession * session,SpdyStream * stream)64 void StallSessionStream(SpdySession* session, SpdyStream* stream) {
65 StallSessionSend(session);
66 StallStreamSend(stream);
67 }
68
StallStreamSession(SpdySession * session,SpdyStream * stream)69 void StallStreamSession(SpdySession* session, SpdyStream* stream) {
70 StallStreamSend(stream);
71 StallSessionSend(session);
72 }
73
UnstallSessionOnly(SpdySession * session,SpdyStream * stream,int32 delta_window_size)74 void UnstallSessionOnly(SpdySession* session,
75 SpdyStream* stream,
76 int32 delta_window_size) {
77 UnstallSessionSend(session, delta_window_size);
78 }
79
UnstallStreamOnly(SpdySession * session,SpdyStream * stream,int32 delta_window_size)80 void UnstallStreamOnly(SpdySession* session,
81 SpdyStream* stream,
82 int32 delta_window_size) {
83 UnstallStreamSend(stream, delta_window_size);
84 }
85
UnstallSessionStream(SpdySession * session,SpdyStream * stream,int32 delta_window_size)86 void UnstallSessionStream(SpdySession* session,
87 SpdyStream* stream,
88 int32 delta_window_size) {
89 UnstallSessionSend(session, delta_window_size);
90 UnstallStreamSend(stream, delta_window_size);
91 }
92
UnstallStreamSession(SpdySession * session,SpdyStream * stream,int32 delta_window_size)93 void UnstallStreamSession(SpdySession* session,
94 SpdyStream* stream,
95 int32 delta_window_size) {
96 UnstallStreamSend(stream, delta_window_size);
97 UnstallSessionSend(session, delta_window_size);
98 }
99
100 protected:
SpdySessionTest()101 SpdySessionTest()
102 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
103 HttpNetworkSession::NORMAL_SOCKET_POOL)),
104 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
105 HttpNetworkSession::NORMAL_SOCKET_POOL)),
106 spdy_util_(GetParam()),
107 session_deps_(GetParam()),
108 spdy_session_pool_(NULL),
109 test_url_(kTestUrl),
110 test_host_port_pair_(kTestHost, kTestPort),
111 key_(test_host_port_pair_, ProxyServer::Direct(),
112 PRIVACY_MODE_DISABLED) {
113 }
114
~SpdySessionTest()115 virtual ~SpdySessionTest() {
116 // Important to restore the per-pool limit first, since the pool limit must
117 // always be greater than group limit, and the tests reduce both limits.
118 ClientSocketPoolManager::set_max_sockets_per_pool(
119 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
120 ClientSocketPoolManager::set_max_sockets_per_group(
121 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
122 }
123
SetUp()124 virtual void SetUp() OVERRIDE {
125 g_time_delta = base::TimeDelta();
126 }
127
CreateDeterministicNetworkSession()128 void CreateDeterministicNetworkSession() {
129 http_session_ =
130 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
131 spdy_session_pool_ = http_session_->spdy_session_pool();
132 }
133
CreateNetworkSession()134 void CreateNetworkSession() {
135 http_session_ =
136 SpdySessionDependencies::SpdyCreateSession(&session_deps_);
137 spdy_session_pool_ = http_session_->spdy_session_pool();
138 }
139
StallSessionSend(SpdySession * session)140 void StallSessionSend(SpdySession* session) {
141 // Reduce the send window size to 0 to stall.
142 while (session->session_send_window_size_ > 0) {
143 session->DecreaseSendWindowSize(
144 std::min(kMaxSpdyFrameChunkSize, session->session_send_window_size_));
145 }
146 }
147
UnstallSessionSend(SpdySession * session,int32 delta_window_size)148 void UnstallSessionSend(SpdySession* session, int32 delta_window_size) {
149 session->IncreaseSendWindowSize(delta_window_size);
150 }
151
StallStreamSend(SpdyStream * stream)152 void StallStreamSend(SpdyStream* stream) {
153 // Reduce the send window size to 0 to stall.
154 while (stream->send_window_size() > 0) {
155 stream->DecreaseSendWindowSize(
156 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
157 }
158 }
159
UnstallStreamSend(SpdyStream * stream,int32 delta_window_size)160 void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) {
161 stream->IncreaseSendWindowSize(delta_window_size);
162 }
163
164 void RunResumeAfterUnstallTest(
165 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
166 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
167 unstall_function);
168
169 // Original socket limits. Some tests set these. Safest to always restore
170 // them once each test has been run.
171 int old_max_group_sockets_;
172 int old_max_pool_sockets_;
173
174 SpdyTestUtil spdy_util_;
175 SpdySessionDependencies session_deps_;
176 scoped_refptr<HttpNetworkSession> http_session_;
177 SpdySessionPool* spdy_session_pool_;
178 GURL test_url_;
179 HostPortPair test_host_port_pair_;
180 SpdySessionKey key_;
181 };
182
183 INSTANTIATE_TEST_CASE_P(
184 NextProto,
185 SpdySessionTest,
186 testing::Values(kProtoDeprecatedSPDY2,
187 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
188
189 // Try to create a SPDY session that will fail during
190 // initialization. Nothing should blow up.
TEST_P(SpdySessionTest,InitialReadError)191 TEST_P(SpdySessionTest, InitialReadError) {
192 CreateDeterministicNetworkSession();
193
194 base::WeakPtr<SpdySession> session = TryCreateFakeSpdySessionExpectingFailure(
195 spdy_session_pool_, key_, ERR_CONNECTION_CLOSED);
196 EXPECT_TRUE(session);
197 // Flush the read.
198 base::RunLoop().RunUntilIdle();
199 EXPECT_FALSE(session);
200 }
201
202 namespace {
203
204 // A helper class that vends a callback that, when fired, destroys a
205 // given SpdyStreamRequest.
206 class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
207 public:
StreamRequestDestroyingCallback()208 StreamRequestDestroyingCallback() {}
209
~StreamRequestDestroyingCallback()210 virtual ~StreamRequestDestroyingCallback() {}
211
SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request)212 void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) {
213 request_ = request.Pass();
214 }
215
MakeCallback()216 CompletionCallback MakeCallback() {
217 return base::Bind(&StreamRequestDestroyingCallback::OnComplete,
218 base::Unretained(this));
219 }
220
221 private:
OnComplete(int result)222 void OnComplete(int result) {
223 request_.reset();
224 SetResult(result);
225 }
226
227 scoped_ptr<SpdyStreamRequest> request_;
228 };
229
230 } // namespace
231
232 // Request kInitialMaxConcurrentStreams streams. Request two more
233 // streams, but have the callback for one destroy the second stream
234 // request. Close the session. Nothing should blow up. This is a
235 // regression test for http://crbug.com/250841 .
TEST_P(SpdySessionTest,PendingStreamCancellingAnother)236 TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
237 session_deps_.host_resolver->set_synchronous_mode(true);
238
239 MockRead reads[] = {MockRead(ASYNC, 0, 0), };
240
241 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
242 MockConnect connect_data(SYNCHRONOUS, OK);
243 data.set_connect_data(connect_data);
244 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
245
246 CreateDeterministicNetworkSession();
247
248 base::WeakPtr<SpdySession> session =
249 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
250
251 // Create the maximum number of concurrent streams.
252 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
253 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
254 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog());
255 ASSERT_TRUE(spdy_stream != NULL);
256 }
257
258 SpdyStreamRequest request1;
259 scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest);
260
261 StreamRequestDestroyingCallback callback1;
262 ASSERT_EQ(ERR_IO_PENDING,
263 request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM,
264 session,
265 test_url_,
266 MEDIUM,
267 BoundNetLog(),
268 callback1.MakeCallback()));
269
270 // |callback2| is never called.
271 TestCompletionCallback callback2;
272 ASSERT_EQ(ERR_IO_PENDING,
273 request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM,
274 session,
275 test_url_,
276 MEDIUM,
277 BoundNetLog(),
278 callback2.callback()));
279
280 callback1.SetRequestToDestroy(request2.Pass());
281
282 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
283
284 EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
285 }
286
287 // A session receiving a GOAWAY frame with no active streams should close.
TEST_P(SpdySessionTest,GoAwayWithNoActiveStreams)288 TEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
289 session_deps_.host_resolver->set_synchronous_mode(true);
290
291 MockConnect connect_data(SYNCHRONOUS, OK);
292 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
293 MockRead reads[] = {
294 CreateMockRead(*goaway, 0),
295 };
296 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
297 data.set_connect_data(connect_data);
298 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
299
300 CreateDeterministicNetworkSession();
301
302 base::WeakPtr<SpdySession> session =
303 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
304
305 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
306
307 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
308
309 // Read and process the GOAWAY frame.
310 data.RunFor(1);
311 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
312 base::RunLoop().RunUntilIdle();
313 EXPECT_TRUE(session == NULL);
314 }
315
316 // A session receiving a GOAWAY frame immediately with no active
317 // streams should then close.
TEST_P(SpdySessionTest,GoAwayImmediatelyWithNoActiveStreams)318 TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
319 session_deps_.host_resolver->set_synchronous_mode(true);
320
321 MockConnect connect_data(SYNCHRONOUS, OK);
322 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
323 MockRead reads[] = {
324 CreateMockRead(*goaway, 0, SYNCHRONOUS),
325 };
326 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
327 data.set_connect_data(connect_data);
328 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
329
330 CreateDeterministicNetworkSession();
331
332 data.StopAfter(1);
333
334 base::WeakPtr<SpdySession> session =
335 TryCreateInsecureSpdySessionExpectingFailure(
336 http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
337 base::RunLoop().RunUntilIdle();
338
339 EXPECT_FALSE(session);
340 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
341 }
342
343 // A session receiving a GOAWAY frame with active streams should close
344 // when the last active stream is closed.
TEST_P(SpdySessionTest,GoAwayWithActiveStreams)345 TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
346 session_deps_.host_resolver->set_synchronous_mode(true);
347
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
353 };
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),
361 };
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);
366
367 CreateDeterministicNetworkSession();
368
369 base::WeakPtr<SpdySession> session =
370 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
371
372 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
373
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);
380
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);
386
387 scoped_ptr<SpdyHeaderBlock> headers(
388 spdy_util_.ConstructGetHeaderBlock(url.spec()));
389 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
390
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());
395
396 data.RunFor(2);
397
398 EXPECT_EQ(1u, spdy_stream1->stream_id());
399 EXPECT_EQ(3u, spdy_stream2->stream_id());
400
401 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
402
403 // Read and process the GOAWAY frame.
404 data.RunFor(1);
405
406 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
407
408 EXPECT_FALSE(session->IsStreamActive(3));
409 EXPECT_EQ(NULL, spdy_stream2.get());
410 EXPECT_TRUE(session->IsStreamActive(1));
411
412 EXPECT_TRUE(session->IsGoingAway());
413
414 // Should close the session.
415 spdy_stream1->Close();
416 EXPECT_EQ(NULL, spdy_stream1.get());
417
418 base::MessageLoop::current()->RunUntilIdle();
419 EXPECT_TRUE(session == NULL);
420 }
421
422 // Have a session receive two GOAWAY frames, with the last one causing
423 // the last active stream to be closed. The session should then be
424 // closed after the second GOAWAY frame.
TEST_P(SpdySessionTest,GoAwayTwice)425 TEST_P(SpdySessionTest, GoAwayTwice) {
426 session_deps_.host_resolver->set_synchronous_mode(true);
427
428 MockConnect connect_data(SYNCHRONOUS, OK);
429 scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
430 scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
431 MockRead reads[] = {
432 CreateMockRead(*goaway1, 2),
433 CreateMockRead(*goaway2, 3),
434 MockRead(ASYNC, 0, 4) // EOF
435 };
436 scoped_ptr<SpdyFrame> req1(
437 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
438 scoped_ptr<SpdyFrame> req2(
439 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
440 MockWrite writes[] = {
441 CreateMockWrite(*req1, 0),
442 CreateMockWrite(*req2, 1),
443 };
444 DeterministicSocketData data(reads, arraysize(reads),
445 writes, arraysize(writes));
446 data.set_connect_data(connect_data);
447 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
448
449 CreateDeterministicNetworkSession();
450
451 base::WeakPtr<SpdySession> session =
452 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
453
454 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
455
456 GURL url(kDefaultURL);
457 base::WeakPtr<SpdyStream> spdy_stream1 =
458 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
459 session, url, MEDIUM, BoundNetLog());
460 test::StreamDelegateDoNothing delegate1(spdy_stream1);
461 spdy_stream1->SetDelegate(&delegate1);
462
463 base::WeakPtr<SpdyStream> spdy_stream2 =
464 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
465 session, url, MEDIUM, BoundNetLog());
466 test::StreamDelegateDoNothing delegate2(spdy_stream2);
467 spdy_stream2->SetDelegate(&delegate2);
468
469 scoped_ptr<SpdyHeaderBlock> headers(
470 spdy_util_.ConstructGetHeaderBlock(url.spec()));
471 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
472
473 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
474 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
475 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
476 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
477
478 data.RunFor(2);
479
480 EXPECT_EQ(1u, spdy_stream1->stream_id());
481 EXPECT_EQ(3u, spdy_stream2->stream_id());
482
483 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
484
485 // Read and process the first GOAWAY frame.
486 data.RunFor(1);
487
488 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
489
490 EXPECT_FALSE(session->IsStreamActive(3));
491 EXPECT_EQ(NULL, spdy_stream2.get());
492 EXPECT_TRUE(session->IsStreamActive(1));
493 EXPECT_TRUE(session->IsGoingAway());
494
495 // Read and process the second GOAWAY frame, which should close the
496 // session.
497 data.RunFor(1);
498 base::MessageLoop::current()->RunUntilIdle();
499 EXPECT_TRUE(session == NULL);
500 }
501
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).
TEST_P(SpdySessionTest,GoAwayWithActiveStreamsThenClose)505 TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
506 session_deps_.host_resolver->set_synchronous_mode(true);
507
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
513 };
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),
521 };
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);
526
527 CreateDeterministicNetworkSession();
528
529 base::WeakPtr<SpdySession> session =
530 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
531
532 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
533
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);
540
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);
546
547 scoped_ptr<SpdyHeaderBlock> headers(
548 spdy_util_.ConstructGetHeaderBlock(url.spec()));
549 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
550
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());
555
556 data.RunFor(2);
557
558 EXPECT_EQ(1u, spdy_stream1->stream_id());
559 EXPECT_EQ(3u, spdy_stream2->stream_id());
560
561 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
562
563 // Read and process the GOAWAY frame.
564 data.RunFor(1);
565
566 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
567
568 EXPECT_FALSE(session->IsStreamActive(3));
569 EXPECT_EQ(NULL, spdy_stream2.get());
570 EXPECT_TRUE(session->IsStreamActive(1));
571 EXPECT_TRUE(session->IsGoingAway());
572
573 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
574 EXPECT_EQ(NULL, spdy_stream1.get());
575
576 base::MessageLoop::current()->RunUntilIdle();
577 EXPECT_TRUE(session == NULL);
578 }
579
580 // Process a joint read buffer which causes the session to begin draining, and
581 // then processes a GOAWAY. The session should gracefully drain. Regression test
582 // for crbug.com/379469
TEST_P(SpdySessionTest,GoAwayWhileDraining)583 TEST_P(SpdySessionTest, GoAwayWhileDraining) {
584 session_deps_.host_resolver->set_synchronous_mode(true);
585
586 scoped_ptr<SpdyFrame> req(
587 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
588 MockWrite writes[] = {
589 CreateMockWrite(*req, 0),
590 };
591
592 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
593 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
594 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
595 size_t joint_size = goaway->size() * 2 + body->size();
596
597 // Compose interleaved |goaway| and |body| frames into a single read.
598 scoped_ptr<char[]> buffer(new char[joint_size]);
599 {
600 size_t out = 0;
601 memcpy(&buffer[out], goaway->data(), goaway->size());
602 out += goaway->size();
603 memcpy(&buffer[out], body->data(), body->size());
604 out += body->size();
605 memcpy(&buffer[out], goaway->data(), goaway->size());
606 out += goaway->size();
607 ASSERT_EQ(out, joint_size);
608 }
609 SpdyFrame joint_frames(buffer.get(), joint_size, false);
610
611 MockRead reads[] = {
612 CreateMockRead(*resp, 1), CreateMockRead(joint_frames, 2),
613 MockRead(ASYNC, 0, 3) // EOF
614 };
615
616 MockConnect connect_data(SYNCHRONOUS, OK);
617 DeterministicSocketData data(
618 reads, arraysize(reads), writes, arraysize(writes));
619 data.set_connect_data(connect_data);
620 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
621
622 CreateDeterministicNetworkSession();
623 base::WeakPtr<SpdySession> session =
624 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
625
626 GURL url(kDefaultURL);
627 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
628 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
629 test::StreamDelegateDoNothing delegate(spdy_stream);
630 spdy_stream->SetDelegate(&delegate);
631
632 scoped_ptr<SpdyHeaderBlock> headers(
633 spdy_util_.ConstructGetHeaderBlock(url.spec()));
634 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
635 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
636
637 data.RunFor(3);
638 base::MessageLoop::current()->RunUntilIdle();
639
640 // Stream and session closed gracefully.
641 EXPECT_TRUE(delegate.StreamIsClosed());
642 EXPECT_EQ(OK, delegate.WaitForClose());
643 EXPECT_EQ(kUploadData, delegate.TakeReceivedData());
644 EXPECT_TRUE(session == NULL);
645 }
646
647 // Try to create a stream after receiving a GOAWAY frame. It should
648 // fail.
TEST_P(SpdySessionTest,CreateStreamAfterGoAway)649 TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
650 session_deps_.host_resolver->set_synchronous_mode(true);
651
652 MockConnect connect_data(SYNCHRONOUS, OK);
653 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
654 MockRead reads[] = {
655 CreateMockRead(*goaway, 1),
656 MockRead(ASYNC, 0, 2) // EOF
657 };
658 scoped_ptr<SpdyFrame> req(
659 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
660 MockWrite writes[] = {
661 CreateMockWrite(*req, 0),
662 };
663 DeterministicSocketData data(reads, arraysize(reads),
664 writes, arraysize(writes));
665 data.set_connect_data(connect_data);
666 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
667
668 CreateDeterministicNetworkSession();
669
670 base::WeakPtr<SpdySession> session =
671 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
672
673 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
674
675 GURL url(kDefaultURL);
676 base::WeakPtr<SpdyStream> spdy_stream =
677 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
678 session, url, MEDIUM, BoundNetLog());
679 test::StreamDelegateDoNothing delegate(spdy_stream);
680 spdy_stream->SetDelegate(&delegate);
681
682 scoped_ptr<SpdyHeaderBlock> headers(
683 spdy_util_.ConstructGetHeaderBlock(url.spec()));
684 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
685 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
686
687 data.RunFor(1);
688
689 EXPECT_EQ(1u, spdy_stream->stream_id());
690
691 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
692
693 // Read and process the GOAWAY frame.
694 data.RunFor(1);
695
696 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
697 EXPECT_TRUE(session->IsStreamActive(1));
698
699 SpdyStreamRequest stream_request;
700 int rv = stream_request.StartRequest(
701 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog(),
702 CompletionCallback());
703 EXPECT_EQ(ERR_FAILED, rv);
704
705 // Read and process EOF.
706 data.RunFor(1);
707
708 EXPECT_TRUE(session == NULL);
709 }
710
711 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
712 // the stream being refused.
TEST_P(SpdySessionTest,SynStreamAfterGoAway)713 TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
714 session_deps_.host_resolver->set_synchronous_mode(true);
715
716 MockConnect connect_data(SYNCHRONOUS, OK);
717 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
718 scoped_ptr<SpdyFrame>
719 push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kDefaultURL));
720 MockRead reads[] = {
721 CreateMockRead(*goaway, 1),
722 CreateMockRead(*push, 2),
723 MockRead(ASYNC, 0, 4) // EOF
724 };
725 scoped_ptr<SpdyFrame> req(
726 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
727 scoped_ptr<SpdyFrame> rst(
728 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
729 MockWrite writes[] = {
730 CreateMockWrite(*req, 0),
731 CreateMockWrite(*rst, 3)
732 };
733 DeterministicSocketData data(reads, arraysize(reads),
734 writes, arraysize(writes));
735 data.set_connect_data(connect_data);
736 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
737
738 CreateDeterministicNetworkSession();
739
740 base::WeakPtr<SpdySession> session =
741 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
742
743 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
744
745 GURL url(kDefaultURL);
746 base::WeakPtr<SpdyStream> spdy_stream =
747 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
748 session, url, MEDIUM, BoundNetLog());
749 test::StreamDelegateDoNothing delegate(spdy_stream);
750 spdy_stream->SetDelegate(&delegate);
751
752 scoped_ptr<SpdyHeaderBlock> headers(
753 spdy_util_.ConstructGetHeaderBlock(url.spec()));
754 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
755 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
756
757 data.RunFor(1);
758
759 EXPECT_EQ(1u, spdy_stream->stream_id());
760
761 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
762
763 // Read and process the GOAWAY frame.
764 data.RunFor(1);
765
766 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
767 EXPECT_TRUE(session->IsStreamActive(1));
768
769 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
770 // and EOF.
771 data.RunFor(3);
772 base::MessageLoop::current()->RunUntilIdle();
773 EXPECT_TRUE(session == NULL);
774 }
775
776 // A session observing a network change with active streams should close
777 // when the last active stream is closed.
TEST_P(SpdySessionTest,NetworkChangeWithActiveStreams)778 TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
779 session_deps_.host_resolver->set_synchronous_mode(true);
780
781 MockConnect connect_data(SYNCHRONOUS, OK);
782 MockRead reads[] = {
783 MockRead(ASYNC, 0, 1) // EOF
784 };
785 scoped_ptr<SpdyFrame> req1(
786 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
787 MockWrite writes[] = {
788 CreateMockWrite(*req1, 0),
789 };
790 DeterministicSocketData data(reads, arraysize(reads),
791 writes, arraysize(writes));
792 data.set_connect_data(connect_data);
793 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
794
795 CreateDeterministicNetworkSession();
796
797 base::WeakPtr<SpdySession> session =
798 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
799
800 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
801
802 base::WeakPtr<SpdyStream> spdy_stream =
803 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session,
804 GURL(kDefaultURL), MEDIUM, BoundNetLog());
805 test::StreamDelegateDoNothing delegate(spdy_stream);
806 spdy_stream->SetDelegate(&delegate);
807
808 scoped_ptr<SpdyHeaderBlock> headers(
809 spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
810
811 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
812 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
813
814 data.RunFor(1);
815
816 EXPECT_EQ(1u, spdy_stream->stream_id());
817
818 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
819
820 spdy_session_pool_->OnIPAddressChanged();
821
822 // The SpdySessionPool behavior differs based on how the OSs reacts to
823 // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
824 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
825 // For OSs where the TCP connections will close upon relevant network
826 // changes, SpdySessionPool doesn't need to force them to close, so in these
827 // cases verify the session has become unavailable but remains open and the
828 // pre-existing stream is still active.
829 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
830
831 EXPECT_TRUE(session->IsGoingAway());
832
833 EXPECT_TRUE(session->IsStreamActive(1));
834
835 // Should close the session.
836 spdy_stream->Close();
837 #endif
838 EXPECT_EQ(NULL, spdy_stream.get());
839
840 base::MessageLoop::current()->RunUntilIdle();
841 EXPECT_TRUE(session == NULL);
842 }
843
TEST_P(SpdySessionTest,ClientPing)844 TEST_P(SpdySessionTest, ClientPing) {
845 session_deps_.enable_ping = true;
846 session_deps_.host_resolver->set_synchronous_mode(true);
847
848 MockConnect connect_data(SYNCHRONOUS, OK);
849 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
850 MockRead reads[] = {
851 CreateMockRead(*read_ping, 1),
852 MockRead(ASYNC, 0, 0, 2) // EOF
853 };
854 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
855 MockWrite writes[] = {
856 CreateMockWrite(*write_ping, 0),
857 };
858 DeterministicSocketData data(
859 reads, arraysize(reads), writes, arraysize(writes));
860 data.set_connect_data(connect_data);
861 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
862
863 CreateDeterministicNetworkSession();
864
865 base::WeakPtr<SpdySession> session =
866 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
867
868 base::WeakPtr<SpdyStream> spdy_stream1 =
869 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
870 session, test_url_, MEDIUM, BoundNetLog());
871 ASSERT_TRUE(spdy_stream1.get() != NULL);
872 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
873 spdy_stream1->SetDelegate(&delegate);
874
875 base::TimeTicks before_ping_time = base::TimeTicks::Now();
876
877 session->set_connection_at_risk_of_loss_time(
878 base::TimeDelta::FromSeconds(-1));
879 session->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
880
881 session->SendPrefacePingIfNoneInFlight();
882
883 data.RunFor(2);
884
885 session->CheckPingStatus(before_ping_time);
886
887 EXPECT_EQ(0, session->pings_in_flight());
888 EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1));
889 EXPECT_FALSE(session->check_ping_status_pending());
890 EXPECT_GE(session->last_activity_time(), before_ping_time);
891
892 data.RunFor(1);
893
894 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
895
896 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
897 EXPECT_TRUE(session == NULL);
898 }
899
TEST_P(SpdySessionTest,ServerPing)900 TEST_P(SpdySessionTest, ServerPing) {
901 session_deps_.host_resolver->set_synchronous_mode(true);
902
903 MockConnect connect_data(SYNCHRONOUS, OK);
904 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
905 MockRead reads[] = {
906 CreateMockRead(*read_ping),
907 MockRead(SYNCHRONOUS, 0, 0) // EOF
908 };
909 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
910 MockWrite writes[] = {
911 CreateMockWrite(*write_ping),
912 };
913 StaticSocketDataProvider data(
914 reads, arraysize(reads), writes, arraysize(writes));
915 data.set_connect_data(connect_data);
916 session_deps_.socket_factory->AddSocketDataProvider(&data);
917
918 CreateNetworkSession();
919
920 base::WeakPtr<SpdySession> session =
921 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
922
923 base::WeakPtr<SpdyStream> spdy_stream1 =
924 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
925 session, test_url_, MEDIUM, BoundNetLog());
926 ASSERT_TRUE(spdy_stream1.get() != NULL);
927 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
928 spdy_stream1->SetDelegate(&delegate);
929
930 // Flush the read completion task.
931 base::MessageLoop::current()->RunUntilIdle();
932
933 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
934
935 EXPECT_TRUE(session == NULL);
936 EXPECT_EQ(NULL, spdy_stream1.get());
937 }
938
939 // Cause a ping to be sent out while producing a write. The write loop
940 // should handle this properly, i.e. another DoWriteLoop task should
941 // not be posted. This is a regression test for
942 // http://crbug.com/261043 .
TEST_P(SpdySessionTest,PingAndWriteLoop)943 TEST_P(SpdySessionTest, PingAndWriteLoop) {
944 session_deps_.enable_ping = true;
945 session_deps_.time_func = TheNearFuture;
946
947 MockConnect connect_data(SYNCHRONOUS, OK);
948 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
949 scoped_ptr<SpdyFrame> req(
950 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
951 MockWrite writes[] = {
952 CreateMockWrite(*req, 0),
953 CreateMockWrite(*write_ping, 1),
954 };
955
956 MockRead reads[] = {
957 MockRead(ASYNC, 0, 2) // EOF
958 };
959
960 session_deps_.host_resolver->set_synchronous_mode(true);
961
962 DeterministicSocketData data(reads, arraysize(reads),
963 writes, arraysize(writes));
964 data.set_connect_data(connect_data);
965 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
966
967 CreateDeterministicNetworkSession();
968
969 base::WeakPtr<SpdySession> session =
970 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
971
972 GURL url(kDefaultURL);
973 base::WeakPtr<SpdyStream> spdy_stream =
974 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
975 session, url, LOWEST, BoundNetLog());
976 test::StreamDelegateDoNothing delegate(spdy_stream);
977 spdy_stream->SetDelegate(&delegate);
978
979 scoped_ptr<SpdyHeaderBlock> headers(
980 spdy_util_.ConstructGetHeaderBlock(url.spec()));
981 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
982
983 // Shift time so that a ping will be sent out.
984 g_time_delta = base::TimeDelta::FromSeconds(11);
985
986 data.RunFor(2);
987
988 session->CloseSessionOnError(ERR_ABORTED, "Aborting");
989 }
990
TEST_P(SpdySessionTest,StreamIdSpaceExhausted)991 TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
992 const SpdyStreamId kLastStreamId = 0x7fffffff;
993 session_deps_.host_resolver->set_synchronous_mode(true);
994
995 // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
996 // fixed to allow for two stream ID assignments, and three concurrent
997 // streams. Four streams are started, and two are activated. Verify the
998 // session goes away, and that the created (but not activated) and
999 // stalled streams are aborted. Also verify the activated streams complete,
1000 // at which point the session closes.
1001
1002 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
1003 NULL, 0, false, kLastStreamId - 2, MEDIUM, true));
1004 scoped_ptr<SpdyFrame> req2(
1005 spdy_util_.ConstructSpdyGet(NULL, 0, false, kLastStreamId, MEDIUM, true));
1006
1007 MockWrite writes[] = {
1008 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
1009 };
1010
1011 scoped_ptr<SpdyFrame> resp1(
1012 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId - 2));
1013 scoped_ptr<SpdyFrame> resp2(
1014 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId));
1015
1016 scoped_ptr<SpdyFrame> body1(
1017 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
1018 scoped_ptr<SpdyFrame> body2(
1019 spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
1020
1021 MockRead reads[] = {
1022 CreateMockRead(*resp1, 2), CreateMockRead(*resp2, 3),
1023 CreateMockRead(*body1, 4), CreateMockRead(*body2, 5),
1024 MockRead(ASYNC, 0, 6) // EOF
1025 };
1026
1027 DeterministicSocketData data(
1028 reads, arraysize(reads), writes, arraysize(writes));
1029
1030 MockConnect connect_data(SYNCHRONOUS, OK);
1031 data.set_connect_data(connect_data);
1032 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1033
1034 CreateDeterministicNetworkSession();
1035 base::WeakPtr<SpdySession> session =
1036 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1037
1038 // Fix stream_hi_water_mark_ to allow for two stream activations.
1039 session->stream_hi_water_mark_ = kLastStreamId - 2;
1040 // Fix max_concurrent_streams to allow for three stream creations.
1041 session->max_concurrent_streams_ = 3;
1042
1043 // Create three streams synchronously, and begin a fourth (which is stalled).
1044 GURL url(kDefaultURL);
1045 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1046 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1047 test::StreamDelegateDoNothing delegate1(stream1);
1048 stream1->SetDelegate(&delegate1);
1049
1050 base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
1051 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1052 test::StreamDelegateDoNothing delegate2(stream2);
1053 stream2->SetDelegate(&delegate2);
1054
1055 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1056 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1057 test::StreamDelegateDoNothing delegate3(stream3);
1058 stream3->SetDelegate(&delegate3);
1059
1060 SpdyStreamRequest request4;
1061 TestCompletionCallback callback4;
1062 EXPECT_EQ(ERR_IO_PENDING,
1063 request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1064 session,
1065 url,
1066 MEDIUM,
1067 BoundNetLog(),
1068 callback4.callback()));
1069
1070 // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1071 EXPECT_EQ(0u, session->num_active_streams());
1072 EXPECT_EQ(3u, session->num_created_streams());
1073 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1074
1075 // Activate stream 1. One ID remains available.
1076 stream1->SendRequestHeaders(
1077 scoped_ptr<SpdyHeaderBlock>(
1078 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1079 NO_MORE_DATA_TO_SEND);
1080 data.RunFor(1);
1081
1082 EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1083 EXPECT_EQ(1u, session->num_active_streams());
1084 EXPECT_EQ(2u, session->num_created_streams());
1085 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1086
1087 // Activate stream 2. ID space is exhausted.
1088 stream2->SendRequestHeaders(
1089 scoped_ptr<SpdyHeaderBlock>(
1090 spdy_util_.ConstructGetHeaderBlock(url.spec())),
1091 NO_MORE_DATA_TO_SEND);
1092 data.RunFor(1);
1093
1094 // Active streams remain active.
1095 EXPECT_EQ(kLastStreamId, stream2->stream_id());
1096 EXPECT_EQ(2u, session->num_active_streams());
1097
1098 // Session is going away. Created and stalled streams were aborted.
1099 EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session->availability_state_);
1100 EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose());
1101 EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult());
1102 EXPECT_EQ(0u, session->num_created_streams());
1103 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1104
1105 // Read responses on remaining active streams.
1106 data.RunFor(4);
1107 EXPECT_EQ(OK, delegate1.WaitForClose());
1108 EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1109 EXPECT_EQ(OK, delegate2.WaitForClose());
1110 EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1111
1112 // Session was destroyed.
1113 base::MessageLoop::current()->RunUntilIdle();
1114 EXPECT_FALSE(session.get());
1115 }
1116
1117 // Verifies that an unstalled pending stream creation racing with a new stream
1118 // creation doesn't violate the maximum stream concurrency. Regression test for
1119 // crbug.com/373858.
TEST_P(SpdySessionTest,UnstallRacesWithStreamCreation)1120 TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) {
1121 session_deps_.host_resolver->set_synchronous_mode(true);
1122
1123 MockRead reads[] = {
1124 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1125 };
1126
1127 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1128
1129 MockConnect connect_data(SYNCHRONOUS, OK);
1130 data.set_connect_data(connect_data);
1131 session_deps_.socket_factory->AddSocketDataProvider(&data);
1132
1133 CreateNetworkSession();
1134 base::WeakPtr<SpdySession> session =
1135 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1136
1137 // Fix max_concurrent_streams to allow for one open stream.
1138 session->max_concurrent_streams_ = 1;
1139
1140 // Create two streams: one synchronously, and one which stalls.
1141 GURL url(kDefaultURL);
1142 base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1143 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1144
1145 SpdyStreamRequest request2;
1146 TestCompletionCallback callback2;
1147 EXPECT_EQ(ERR_IO_PENDING,
1148 request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1149 session,
1150 url,
1151 MEDIUM,
1152 BoundNetLog(),
1153 callback2.callback()));
1154
1155 EXPECT_EQ(1u, session->num_created_streams());
1156 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1157
1158 // Cancel the first stream. A callback to unstall the second stream was
1159 // posted. Don't run it yet.
1160 stream1->Cancel();
1161
1162 EXPECT_EQ(0u, session->num_created_streams());
1163 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1164
1165 // Create a third stream prior to the second stream's callback.
1166 base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1167 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1168
1169 EXPECT_EQ(1u, session->num_created_streams());
1170 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1171
1172 // NOW run the message loop. The unstalled stream will re-stall itself.
1173 base::MessageLoop::current()->RunUntilIdle();
1174 EXPECT_EQ(1u, session->num_created_streams());
1175 EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1176
1177 // Cancel the third stream and run the message loop. Verify that the second
1178 // stream creation now completes.
1179 stream3->Cancel();
1180 base::MessageLoop::current()->RunUntilIdle();
1181
1182 EXPECT_EQ(1u, session->num_created_streams());
1183 EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1184 EXPECT_EQ(OK, callback2.WaitForResult());
1185 }
1186
TEST_P(SpdySessionTest,DeleteExpiredPushStreams)1187 TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
1188 session_deps_.host_resolver->set_synchronous_mode(true);
1189 session_deps_.time_func = TheNearFuture;
1190
1191 scoped_ptr<SpdyFrame> req(
1192 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1193 scoped_ptr<SpdyFrame> rst(
1194 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
1195
1196 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
1197 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
1198 scoped_ptr<SpdyFrame> push_a_body(
1199 spdy_util_.ConstructSpdyBodyFrame(2, false));
1200 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
1201 NULL, 0, 4, 1, "http://www.google.com/b.dat"));
1202 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)};
1203 MockRead reads[] = {
1204 CreateMockRead(*push_a, 1), CreateMockRead(*push_a_body, 2),
1205 CreateMockRead(*push_b, 3), MockRead(ASYNC, 0, 5), // EOF
1206 };
1207 DeterministicSocketData data(
1208 reads, arraysize(reads), writes, arraysize(writes));
1209
1210 MockConnect connect_data(SYNCHRONOUS, OK);
1211 data.set_connect_data(connect_data);
1212 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1213
1214 CreateDeterministicNetworkSession();
1215 base::WeakPtr<SpdySession> session =
1216 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1217
1218 // Process the principal request, and the first push stream request & body.
1219 GURL url(kDefaultURL);
1220 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1221 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1222 test::StreamDelegateDoNothing delegate(spdy_stream);
1223 spdy_stream->SetDelegate(&delegate);
1224
1225 scoped_ptr<SpdyHeaderBlock> headers(
1226 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1227 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1228
1229 data.RunFor(3);
1230
1231 // Verify that there is one unclaimed push stream.
1232 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1233 SpdySession::PushedStreamMap::iterator iter =
1234 session->unclaimed_pushed_streams_.find(
1235 GURL("http://www.google.com/a.dat"));
1236 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1237
1238 if (session->flow_control_state_ ==
1239 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1240 // Unclaimed push body consumed bytes from the session window.
1241 EXPECT_EQ(kSpdySessionInitialWindowSize - kUploadDataSize,
1242 session->session_recv_window_size_);
1243 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
1244 }
1245
1246 // Shift time to expire the push stream. Read the second SYN_STREAM,
1247 // and verify a RST_STREAM was written.
1248 g_time_delta = base::TimeDelta::FromSeconds(301);
1249 data.RunFor(2);
1250
1251 // Verify that the second pushed stream evicted the first pushed stream.
1252 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1253 iter = session->unclaimed_pushed_streams_.find(
1254 GURL("http://www.google.com/b.dat"));
1255 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1256
1257 if (session->flow_control_state_ ==
1258 SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1259 // Verify that the session window reclaimed the evicted stream body.
1260 EXPECT_EQ(kSpdySessionInitialWindowSize,
1261 session->session_recv_window_size_);
1262 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
1263 }
1264
1265 // Read and process EOF.
1266 data.RunFor(1);
1267 base::MessageLoop::current()->RunUntilIdle();
1268 EXPECT_TRUE(session == NULL);
1269 }
1270
TEST_P(SpdySessionTest,FailedPing)1271 TEST_P(SpdySessionTest, FailedPing) {
1272 session_deps_.host_resolver->set_synchronous_mode(true);
1273
1274 MockConnect connect_data(SYNCHRONOUS, OK);
1275 MockRead reads[] = {
1276 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1277 };
1278 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
1279 scoped_ptr<SpdyFrame> goaway(
1280 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping."));
1281 MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)};
1282 StaticSocketDataProvider data(
1283 reads, arraysize(reads), writes, arraysize(writes));
1284 data.set_connect_data(connect_data);
1285 session_deps_.socket_factory->AddSocketDataProvider(&data);
1286
1287 CreateNetworkSession();
1288
1289 base::WeakPtr<SpdySession> session =
1290 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1291
1292 base::WeakPtr<SpdyStream> spdy_stream1 =
1293 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1294 session, test_url_, MEDIUM, BoundNetLog());
1295 ASSERT_TRUE(spdy_stream1.get() != NULL);
1296 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
1297 spdy_stream1->SetDelegate(&delegate);
1298
1299 session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1300 session->set_hung_interval(base::TimeDelta::FromSeconds(0));
1301
1302 // Send a PING frame.
1303 session->WritePingFrame(1, false);
1304 EXPECT_LT(0, session->pings_in_flight());
1305 EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1));
1306 EXPECT_TRUE(session->check_ping_status_pending());
1307
1308 // Assert session is not closed.
1309 EXPECT_TRUE(session->IsAvailable());
1310 EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams());
1311 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1312
1313 // We set last time we have received any data in 1 sec less than now.
1314 // CheckPingStatus will trigger timeout because hung interval is zero.
1315 base::TimeTicks now = base::TimeTicks::Now();
1316 session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
1317 session->CheckPingStatus(now);
1318 base::MessageLoop::current()->RunUntilIdle();
1319
1320 EXPECT_TRUE(session == NULL);
1321 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1322 EXPECT_EQ(NULL, spdy_stream1.get());
1323 }
1324
1325 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1326 // settings frame increasing the max concurrent streams by 1. Make
1327 // sure nothing blows up. This is a regression test for
1328 // http://crbug.com/57331 .
TEST_P(SpdySessionTest,OnSettings)1329 TEST_P(SpdySessionTest, OnSettings) {
1330 session_deps_.host_resolver->set_synchronous_mode(true);
1331
1332 const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1333
1334 SettingsMap new_settings;
1335 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1336 new_settings[kSpdySettingsIds] =
1337 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1338 scoped_ptr<SpdyFrame> settings_frame(
1339 spdy_util_.ConstructSpdySettings(new_settings));
1340 MockRead reads[] = {
1341 CreateMockRead(*settings_frame, 0),
1342 MockRead(ASYNC, 0, 1),
1343 };
1344
1345 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1346 MockWrite writes[] = {
1347 CreateMockWrite(*settings_ack, 2),
1348 };
1349
1350 DeterministicSocketData data(reads, arraysize(reads),
1351 writes, arraysize(writes));
1352 MockConnect connect_data(SYNCHRONOUS, OK);
1353 data.set_connect_data(connect_data);
1354 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1355
1356 CreateDeterministicNetworkSession();
1357
1358 base::WeakPtr<SpdySession> session =
1359 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1360
1361 // Create the maximum number of concurrent streams.
1362 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1363 base::WeakPtr<SpdyStream> spdy_stream =
1364 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1365 session, test_url_, MEDIUM, BoundNetLog());
1366 ASSERT_TRUE(spdy_stream != NULL);
1367 }
1368
1369 StreamReleaserCallback stream_releaser;
1370 SpdyStreamRequest request;
1371 ASSERT_EQ(ERR_IO_PENDING,
1372 request.StartRequest(
1373 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1374 BoundNetLog(),
1375 stream_releaser.MakeCallback(&request)));
1376
1377 data.RunFor(1);
1378
1379 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1380
1381 data.RunFor(1);
1382 if (spdy_util_.spdy_version() >= SPDY4) {
1383 // Allow the SETTINGS+ACK to write, so the session finishes draining.
1384 data.RunFor(1);
1385 }
1386 base::MessageLoop::current()->RunUntilIdle();
1387 EXPECT_TRUE(session == NULL);
1388 }
1389
1390 // Start with a persisted value for max concurrent streams. Receive a
1391 // settings frame increasing the max concurrent streams by 1 and which
1392 // also clears the persisted data. Verify that persisted data is
1393 // correct.
TEST_P(SpdySessionTest,ClearSettings)1394 TEST_P(SpdySessionTest, ClearSettings) {
1395 if (spdy_util_.spdy_version() >= SPDY4) {
1396 // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1397 // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4.
1398 return;
1399 }
1400 session_deps_.host_resolver->set_synchronous_mode(true);
1401
1402 SettingsMap new_settings;
1403 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1404 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1405 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1406 scoped_ptr<SpdyFrame> settings_frame(
1407 spdy_util_.ConstructSpdySettings(new_settings));
1408 uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1409 test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1410 MockRead reads[] = {
1411 CreateMockRead(*settings_frame, 0),
1412 MockRead(ASYNC, 0, 1),
1413 };
1414
1415 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
1416 MockConnect connect_data(SYNCHRONOUS, OK);
1417 data.set_connect_data(connect_data);
1418 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1419
1420 CreateDeterministicNetworkSession();
1421
1422 // Initialize the SpdySetting with the default.
1423 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1424 test_host_port_pair_,
1425 SETTINGS_MAX_CONCURRENT_STREAMS,
1426 SETTINGS_FLAG_PLEASE_PERSIST,
1427 kInitialMaxConcurrentStreams);
1428
1429 EXPECT_FALSE(
1430 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1431 test_host_port_pair_).empty());
1432
1433 base::WeakPtr<SpdySession> session =
1434 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1435
1436 // Create the maximum number of concurrent streams.
1437 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1438 base::WeakPtr<SpdyStream> spdy_stream =
1439 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1440 session, test_url_, MEDIUM, BoundNetLog());
1441 ASSERT_TRUE(spdy_stream != NULL);
1442 }
1443
1444 StreamReleaserCallback stream_releaser;
1445
1446 SpdyStreamRequest request;
1447 ASSERT_EQ(ERR_IO_PENDING,
1448 request.StartRequest(
1449 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1450 BoundNetLog(),
1451 stream_releaser.MakeCallback(&request)));
1452
1453 data.RunFor(1);
1454
1455 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1456
1457 // Make sure that persisted data is cleared.
1458 EXPECT_TRUE(
1459 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1460 test_host_port_pair_).empty());
1461
1462 // Make sure session's max_concurrent_streams is correct.
1463 EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1464 session->max_concurrent_streams());
1465
1466 data.RunFor(1);
1467 EXPECT_TRUE(session == NULL);
1468 }
1469
1470 // Start with max concurrent streams set to 1. Request two streams.
1471 // When the first completes, have the callback close its stream, which
1472 // should trigger the second stream creation. Then cancel that one
1473 // immediately. Don't crash. This is a regression test for
1474 // http://crbug.com/63532 .
TEST_P(SpdySessionTest,CancelPendingCreateStream)1475 TEST_P(SpdySessionTest, CancelPendingCreateStream) {
1476 session_deps_.host_resolver->set_synchronous_mode(true);
1477
1478 MockRead reads[] = {
1479 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1480 };
1481
1482 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1483 MockConnect connect_data(SYNCHRONOUS, OK);
1484
1485 data.set_connect_data(connect_data);
1486 session_deps_.socket_factory->AddSocketDataProvider(&data);
1487
1488 CreateNetworkSession();
1489
1490 // Initialize the SpdySetting with 1 max concurrent streams.
1491 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1492 test_host_port_pair_,
1493 SETTINGS_MAX_CONCURRENT_STREAMS,
1494 SETTINGS_FLAG_PLEASE_PERSIST,
1495 1);
1496
1497 base::WeakPtr<SpdySession> session =
1498 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1499
1500 // Leave room for only one more stream to be created.
1501 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1502 base::WeakPtr<SpdyStream> spdy_stream =
1503 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1504 session, test_url_, MEDIUM, BoundNetLog());
1505 ASSERT_TRUE(spdy_stream != NULL);
1506 }
1507
1508 // Create 2 more streams. First will succeed. Second will be pending.
1509 base::WeakPtr<SpdyStream> spdy_stream1 =
1510 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1511 session, test_url_, MEDIUM, BoundNetLog());
1512 ASSERT_TRUE(spdy_stream1.get() != NULL);
1513
1514 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1515 // a valgrind error if the callback is invoked when it's not supposed to be.
1516 scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
1517
1518 SpdyStreamRequest request;
1519 ASSERT_EQ(ERR_IO_PENDING,
1520 request.StartRequest(
1521 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1522 BoundNetLog(),
1523 callback->callback()));
1524
1525 // Release the first one, this will allow the second to be created.
1526 spdy_stream1->Cancel();
1527 EXPECT_EQ(NULL, spdy_stream1.get());
1528
1529 request.CancelRequest();
1530 callback.reset();
1531
1532 // Should not crash when running the pending callback.
1533 base::MessageLoop::current()->RunUntilIdle();
1534 }
1535
TEST_P(SpdySessionTest,SendInitialDataOnNewSession)1536 TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
1537 session_deps_.host_resolver->set_synchronous_mode(true);
1538
1539 MockRead reads[] = {
1540 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1541 };
1542
1543 SettingsMap settings;
1544 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
1545 const SpdySettingsIds kSpdySettingsIds2 = SETTINGS_INITIAL_WINDOW_SIZE;
1546 const uint32 kInitialRecvWindowSize = 10 * 1024 * 1024;
1547 settings[kSpdySettingsIds1] =
1548 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
1549 if (spdy_util_.spdy_version() >= SPDY3) {
1550 settings[kSpdySettingsIds2] =
1551 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialRecvWindowSize);
1552 }
1553 MockConnect connect_data(SYNCHRONOUS, OK);
1554 scoped_ptr<SpdyFrame> settings_frame(
1555 spdy_util_.ConstructSpdySettings(settings));
1556 scoped_ptr<SpdyFrame> initial_window_update(
1557 spdy_util_.ConstructSpdyWindowUpdate(
1558 kSessionFlowControlStreamId,
1559 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
1560 std::vector<MockWrite> writes;
1561 if (GetParam() == kProtoSPDY4) {
1562 writes.push_back(
1563 MockWrite(ASYNC,
1564 kHttp2ConnectionHeaderPrefix,
1565 kHttp2ConnectionHeaderPrefixSize));
1566 }
1567 writes.push_back(CreateMockWrite(*settings_frame));
1568 if (GetParam() >= kProtoSPDY31) {
1569 writes.push_back(CreateMockWrite(*initial_window_update));
1570 };
1571
1572 SettingsMap server_settings;
1573 const uint32 initial_max_concurrent_streams = 1;
1574 server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1575 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1576 initial_max_concurrent_streams);
1577 scoped_ptr<SpdyFrame> server_settings_frame(
1578 spdy_util_.ConstructSpdySettings(server_settings));
1579 if (GetParam() <= kProtoSPDY31) {
1580 writes.push_back(CreateMockWrite(*server_settings_frame));
1581 }
1582
1583 session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize;
1584
1585 StaticSocketDataProvider data(reads, arraysize(reads),
1586 vector_as_array(&writes), writes.size());
1587 data.set_connect_data(connect_data);
1588 session_deps_.socket_factory->AddSocketDataProvider(&data);
1589
1590 CreateNetworkSession();
1591
1592 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1593 test_host_port_pair_,
1594 SETTINGS_MAX_CONCURRENT_STREAMS,
1595 SETTINGS_FLAG_PLEASE_PERSIST,
1596 initial_max_concurrent_streams);
1597
1598 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1599 pool_peer.SetEnableSendingInitialData(true);
1600
1601 base::WeakPtr<SpdySession> session =
1602 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1603
1604 base::MessageLoop::current()->RunUntilIdle();
1605 EXPECT_TRUE(data.at_write_eof());
1606 }
1607
TEST_P(SpdySessionTest,ClearSettingsStorageOnIPAddressChanged)1608 TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
1609 CreateNetworkSession();
1610
1611 base::WeakPtr<HttpServerProperties> test_http_server_properties =
1612 spdy_session_pool_->http_server_properties();
1613 SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
1614 test_http_server_properties->SetSpdySetting(
1615 test_host_port_pair_,
1616 SETTINGS_MAX_CONCURRENT_STREAMS,
1617 SETTINGS_FLAG_PLEASE_PERSIST,
1618 2);
1619 EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
1620 test_host_port_pair_).size());
1621 spdy_session_pool_->OnIPAddressChanged();
1622 EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
1623 test_host_port_pair_).size());
1624 }
1625
TEST_P(SpdySessionTest,Initialize)1626 TEST_P(SpdySessionTest, Initialize) {
1627 CapturingBoundNetLog log;
1628 session_deps_.net_log = log.bound().net_log();
1629 session_deps_.host_resolver->set_synchronous_mode(true);
1630
1631 MockConnect connect_data(SYNCHRONOUS, OK);
1632 MockRead reads[] = {
1633 MockRead(ASYNC, 0, 0) // EOF
1634 };
1635
1636 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1637 data.set_connect_data(connect_data);
1638 session_deps_.socket_factory->AddSocketDataProvider(&data);
1639
1640 CreateNetworkSession();
1641
1642 base::WeakPtr<SpdySession> session =
1643 CreateInsecureSpdySession(http_session_, key_, log.bound());
1644 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1645
1646 // Flush the read completion task.
1647 base::MessageLoop::current()->RunUntilIdle();
1648
1649 net::CapturingNetLog::CapturedEntryList entries;
1650 log.GetEntries(&entries);
1651 EXPECT_LT(0u, entries.size());
1652
1653 // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly.
1654 int pos = net::ExpectLogContainsSomewhere(
1655 entries, 0,
1656 net::NetLog::TYPE_SPDY_SESSION_INITIALIZED,
1657 net::NetLog::PHASE_NONE);
1658 EXPECT_LT(0, pos);
1659
1660 CapturingNetLog::CapturedEntry entry = entries[pos];
1661 NetLog::Source socket_source;
1662 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1663 &socket_source));
1664 EXPECT_TRUE(socket_source.IsValid());
1665 EXPECT_NE(log.bound().source().id, socket_source.id);
1666 }
1667
TEST_P(SpdySessionTest,NetLogOnSessionGoaway)1668 TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
1669 session_deps_.host_resolver->set_synchronous_mode(true);
1670
1671 MockConnect connect_data(SYNCHRONOUS, OK);
1672 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
1673 MockRead reads[] = {
1674 CreateMockRead(*goaway),
1675 MockRead(SYNCHRONOUS, 0, 0) // EOF
1676 };
1677
1678 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1679 data.set_connect_data(connect_data);
1680 session_deps_.socket_factory->AddSocketDataProvider(&data);
1681
1682 CreateNetworkSession();
1683
1684 CapturingBoundNetLog log;
1685 base::WeakPtr<SpdySession> session =
1686 CreateInsecureSpdySession(http_session_, key_, log.bound());
1687 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1688
1689 // Flush the read completion task.
1690 base::MessageLoop::current()->RunUntilIdle();
1691
1692 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1693 EXPECT_TRUE(session == NULL);
1694
1695 // Check that the NetLog was filled reasonably.
1696 net::CapturingNetLog::CapturedEntryList entries;
1697 log.GetEntries(&entries);
1698 EXPECT_LT(0u, entries.size());
1699
1700 // Check that we logged SPDY_SESSION_CLOSE correctly.
1701 int pos = net::ExpectLogContainsSomewhere(
1702 entries, 0,
1703 net::NetLog::TYPE_SPDY_SESSION_CLOSE,
1704 net::NetLog::PHASE_NONE);
1705
1706 if (pos < static_cast<int>(entries.size())) {
1707 CapturingNetLog::CapturedEntry entry = entries[pos];
1708 int error_code = 0;
1709 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1710 EXPECT_EQ(OK, error_code);
1711 } else {
1712 ADD_FAILURE();
1713 }
1714 }
1715
TEST_P(SpdySessionTest,NetLogOnSessionEOF)1716 TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1717 session_deps_.host_resolver->set_synchronous_mode(true);
1718
1719 MockConnect connect_data(SYNCHRONOUS, OK);
1720 MockRead reads[] = {
1721 MockRead(SYNCHRONOUS, 0, 0) // EOF
1722 };
1723
1724 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1725 data.set_connect_data(connect_data);
1726 session_deps_.socket_factory->AddSocketDataProvider(&data);
1727
1728 CreateNetworkSession();
1729
1730 CapturingBoundNetLog log;
1731 base::WeakPtr<SpdySession> session =
1732 CreateInsecureSpdySession(http_session_, key_, log.bound());
1733 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1734
1735 // Flush the read completion task.
1736 base::MessageLoop::current()->RunUntilIdle();
1737
1738 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1739 EXPECT_TRUE(session == NULL);
1740
1741 // Check that the NetLog was filled reasonably.
1742 net::CapturingNetLog::CapturedEntryList entries;
1743 log.GetEntries(&entries);
1744 EXPECT_LT(0u, entries.size());
1745
1746 // Check that we logged SPDY_SESSION_CLOSE correctly.
1747 int pos =
1748 net::ExpectLogContainsSomewhere(entries,
1749 0,
1750 net::NetLog::TYPE_SPDY_SESSION_CLOSE,
1751 net::NetLog::PHASE_NONE);
1752
1753 if (pos < static_cast<int>(entries.size())) {
1754 CapturingNetLog::CapturedEntry entry = entries[pos];
1755 int error_code = 0;
1756 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1757 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1758 } else {
1759 ADD_FAILURE();
1760 }
1761 }
1762
TEST_P(SpdySessionTest,SynCompressionHistograms)1763 TEST_P(SpdySessionTest, SynCompressionHistograms) {
1764 session_deps_.enable_compression = true;
1765
1766 scoped_ptr<SpdyFrame> req(
1767 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, MEDIUM, true));
1768 MockWrite writes[] = {
1769 CreateMockWrite(*req, 0),
1770 };
1771 MockRead reads[] = {
1772 MockRead(ASYNC, 0, 1) // EOF
1773 };
1774 DeterministicSocketData data(reads, arraysize(reads),
1775 writes, arraysize(writes));
1776 MockConnect connect_data(SYNCHRONOUS, OK);
1777 data.set_connect_data(connect_data);
1778 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1779
1780 CreateDeterministicNetworkSession();
1781 base::WeakPtr<SpdySession> session =
1782 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1783
1784 GURL url(kDefaultURL);
1785 base::WeakPtr<SpdyStream> spdy_stream =
1786 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1787 session, url, MEDIUM, BoundNetLog());
1788 test::StreamDelegateDoNothing delegate(spdy_stream);
1789 spdy_stream->SetDelegate(&delegate);
1790
1791 scoped_ptr<SpdyHeaderBlock> headers(
1792 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1793 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1794 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1795
1796 // Write request headers & capture resulting histogram update.
1797 base::HistogramTester histogram_tester;
1798
1799 data.RunFor(1);
1800 // Regression test of compression performance under the request fixture.
1801 switch (spdy_util_.spdy_version()) {
1802 case SPDY2:
1803 histogram_tester.ExpectBucketCount(
1804 "Net.SpdySynStreamCompressionPercentage", 0, 1);
1805 break;
1806 case SPDY3:
1807 histogram_tester.ExpectBucketCount(
1808 "Net.SpdySynStreamCompressionPercentage", 30, 1);
1809 break;
1810 case SPDY4:
1811 histogram_tester.ExpectBucketCount(
1812 "Net.SpdySynStreamCompressionPercentage", 82, 1);
1813 break;
1814 case SPDY5:
1815 histogram_tester.ExpectBucketCount(
1816 "Net.SpdySynStreamCompressionPercentage", 82, 1);
1817 break;
1818 default:
1819 NOTREACHED();
1820 }
1821
1822 // Read and process EOF.
1823 data.RunFor(1);
1824 base::MessageLoop::current()->RunUntilIdle();
1825 EXPECT_TRUE(session == NULL);
1826 }
1827
1828 // Queue up a low-priority SYN_STREAM followed by a high-priority
1829 // one. The high priority one should still send first and receive
1830 // first.
TEST_P(SpdySessionTest,OutOfOrderSynStreams)1831 TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1832 // Construct the request.
1833 MockConnect connect_data(SYNCHRONOUS, OK);
1834 scoped_ptr<SpdyFrame> req_highest(
1835 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true));
1836 scoped_ptr<SpdyFrame> req_lowest(
1837 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1838 MockWrite writes[] = {
1839 CreateMockWrite(*req_highest, 0),
1840 CreateMockWrite(*req_lowest, 1),
1841 };
1842
1843 scoped_ptr<SpdyFrame> resp_highest(
1844 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1845 scoped_ptr<SpdyFrame> body_highest(
1846 spdy_util_.ConstructSpdyBodyFrame(1, true));
1847 scoped_ptr<SpdyFrame> resp_lowest(
1848 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1849 scoped_ptr<SpdyFrame> body_lowest(
1850 spdy_util_.ConstructSpdyBodyFrame(3, true));
1851 MockRead reads[] = {
1852 CreateMockRead(*resp_highest, 2),
1853 CreateMockRead(*body_highest, 3),
1854 CreateMockRead(*resp_lowest, 4),
1855 CreateMockRead(*body_lowest, 5),
1856 MockRead(ASYNC, 0, 6) // EOF
1857 };
1858
1859 session_deps_.host_resolver->set_synchronous_mode(true);
1860
1861 DeterministicSocketData data(reads, arraysize(reads),
1862 writes, arraysize(writes));
1863 data.set_connect_data(connect_data);
1864 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1865
1866 CreateDeterministicNetworkSession();
1867
1868 base::WeakPtr<SpdySession> session =
1869 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1870
1871 GURL url(kDefaultURL);
1872
1873 base::WeakPtr<SpdyStream> spdy_stream_lowest =
1874 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1875 session, url, LOWEST, BoundNetLog());
1876 ASSERT_TRUE(spdy_stream_lowest);
1877 EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1878 test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1879 spdy_stream_lowest->SetDelegate(&delegate_lowest);
1880
1881 base::WeakPtr<SpdyStream> spdy_stream_highest =
1882 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1883 session, url, HIGHEST, BoundNetLog());
1884 ASSERT_TRUE(spdy_stream_highest);
1885 EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1886 test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1887 spdy_stream_highest->SetDelegate(&delegate_highest);
1888
1889 // Queue the lower priority one first.
1890
1891 scoped_ptr<SpdyHeaderBlock> headers_lowest(
1892 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1893 spdy_stream_lowest->SendRequestHeaders(
1894 headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1895 EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1896
1897 scoped_ptr<SpdyHeaderBlock> headers_highest(
1898 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1899 spdy_stream_highest->SendRequestHeaders(
1900 headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1901 EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1902
1903 data.RunFor(7);
1904
1905 EXPECT_FALSE(spdy_stream_lowest);
1906 EXPECT_FALSE(spdy_stream_highest);
1907 EXPECT_EQ(3u, delegate_lowest.stream_id());
1908 EXPECT_EQ(1u, delegate_highest.stream_id());
1909 }
1910
TEST_P(SpdySessionTest,CancelStream)1911 TEST_P(SpdySessionTest, CancelStream) {
1912 MockConnect connect_data(SYNCHRONOUS, OK);
1913 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1914 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1915 scoped_ptr<SpdyFrame> req2(
1916 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1917 MockWrite writes[] = {
1918 CreateMockWrite(*req2, 0),
1919 };
1920
1921 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1922 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1923 MockRead reads[] = {
1924 CreateMockRead(*resp2, 1),
1925 CreateMockRead(*body2, 2),
1926 MockRead(ASYNC, 0, 3) // EOF
1927 };
1928
1929 session_deps_.host_resolver->set_synchronous_mode(true);
1930
1931 DeterministicSocketData data(reads, arraysize(reads),
1932 writes, arraysize(writes));
1933 data.set_connect_data(connect_data);
1934 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1935
1936 CreateDeterministicNetworkSession();
1937
1938 base::WeakPtr<SpdySession> session =
1939 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1940
1941 GURL url1(kDefaultURL);
1942 base::WeakPtr<SpdyStream> spdy_stream1 =
1943 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1944 session, url1, HIGHEST, BoundNetLog());
1945 ASSERT_TRUE(spdy_stream1.get() != NULL);
1946 EXPECT_EQ(0u, spdy_stream1->stream_id());
1947 test::StreamDelegateDoNothing delegate1(spdy_stream1);
1948 spdy_stream1->SetDelegate(&delegate1);
1949
1950 GURL url2(kDefaultURL);
1951 base::WeakPtr<SpdyStream> spdy_stream2 =
1952 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1953 session, url2, LOWEST, BoundNetLog());
1954 ASSERT_TRUE(spdy_stream2.get() != NULL);
1955 EXPECT_EQ(0u, spdy_stream2->stream_id());
1956 test::StreamDelegateDoNothing delegate2(spdy_stream2);
1957 spdy_stream2->SetDelegate(&delegate2);
1958
1959 scoped_ptr<SpdyHeaderBlock> headers(
1960 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1961 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1962 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1963
1964 scoped_ptr<SpdyHeaderBlock> headers2(
1965 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1966 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1967 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1968
1969 EXPECT_EQ(0u, spdy_stream1->stream_id());
1970
1971 spdy_stream1->Cancel();
1972 EXPECT_EQ(NULL, spdy_stream1.get());
1973
1974 EXPECT_EQ(0u, delegate1.stream_id());
1975
1976 data.RunFor(1);
1977
1978 EXPECT_EQ(0u, delegate1.stream_id());
1979 EXPECT_EQ(1u, delegate2.stream_id());
1980
1981 spdy_stream2->Cancel();
1982 EXPECT_EQ(NULL, spdy_stream2.get());
1983 }
1984
1985 // Create two streams that are set to re-close themselves on close,
1986 // and then close the session. Nothing should blow up. Also a
1987 // regression test for http://crbug.com/139518 .
TEST_P(SpdySessionTest,CloseSessionWithTwoCreatedSelfClosingStreams)1988 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1989 session_deps_.host_resolver->set_synchronous_mode(true);
1990
1991 MockConnect connect_data(SYNCHRONOUS, OK);
1992
1993 // No actual data will be sent.
1994 MockWrite writes[] = {
1995 MockWrite(ASYNC, 0, 1) // EOF
1996 };
1997
1998 MockRead reads[] = {
1999 MockRead(ASYNC, 0, 0) // EOF
2000 };
2001 DeterministicSocketData data(reads, arraysize(reads),
2002 writes, arraysize(writes));
2003 data.set_connect_data(connect_data);
2004 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2005
2006 CreateDeterministicNetworkSession();
2007
2008 base::WeakPtr<SpdySession> session =
2009 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2010
2011 GURL url1(kDefaultURL);
2012 base::WeakPtr<SpdyStream> spdy_stream1 =
2013 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2014 session, url1, HIGHEST, BoundNetLog());
2015 ASSERT_TRUE(spdy_stream1.get() != NULL);
2016 EXPECT_EQ(0u, spdy_stream1->stream_id());
2017
2018 GURL url2(kDefaultURL);
2019 base::WeakPtr<SpdyStream> spdy_stream2 =
2020 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2021 session, url2, LOWEST, BoundNetLog());
2022 ASSERT_TRUE(spdy_stream2.get() != NULL);
2023 EXPECT_EQ(0u, spdy_stream2->stream_id());
2024
2025 test::ClosingDelegate delegate1(spdy_stream1);
2026 spdy_stream1->SetDelegate(&delegate1);
2027
2028 test::ClosingDelegate delegate2(spdy_stream2);
2029 spdy_stream2->SetDelegate(&delegate2);
2030
2031 scoped_ptr<SpdyHeaderBlock> headers(
2032 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2033 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2034 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2035
2036 scoped_ptr<SpdyHeaderBlock> headers2(
2037 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2038 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2039 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2040
2041 // Ensure that the streams have not yet been activated and assigned an id.
2042 EXPECT_EQ(0u, spdy_stream1->stream_id());
2043 EXPECT_EQ(0u, spdy_stream2->stream_id());
2044
2045 // Ensure we don't crash while closing the session.
2046 session->CloseSessionOnError(ERR_ABORTED, std::string());
2047
2048 EXPECT_EQ(NULL, spdy_stream1.get());
2049 EXPECT_EQ(NULL, spdy_stream2.get());
2050
2051 EXPECT_TRUE(delegate1.StreamIsClosed());
2052 EXPECT_TRUE(delegate2.StreamIsClosed());
2053
2054 base::MessageLoop::current()->RunUntilIdle();
2055 EXPECT_TRUE(session == NULL);
2056 }
2057
2058 // Create two streams that are set to close each other on close, and
2059 // then close the session. Nothing should blow up.
TEST_P(SpdySessionTest,CloseSessionWithTwoCreatedMutuallyClosingStreams)2060 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
2061 session_deps_.host_resolver->set_synchronous_mode(true);
2062
2063 MockConnect connect_data(SYNCHRONOUS, OK);
2064
2065 // No actual data will be sent.
2066 MockWrite writes[] = {
2067 MockWrite(ASYNC, 0, 1) // EOF
2068 };
2069
2070 MockRead reads[] = {
2071 MockRead(ASYNC, 0, 0) // EOF
2072 };
2073 DeterministicSocketData data(reads, arraysize(reads),
2074 writes, arraysize(writes));
2075 data.set_connect_data(connect_data);
2076 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2077
2078 CreateDeterministicNetworkSession();
2079
2080 base::WeakPtr<SpdySession> session =
2081 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2082
2083 GURL url1(kDefaultURL);
2084 base::WeakPtr<SpdyStream> spdy_stream1 =
2085 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2086 session, url1, HIGHEST, BoundNetLog());
2087 ASSERT_TRUE(spdy_stream1.get() != NULL);
2088 EXPECT_EQ(0u, spdy_stream1->stream_id());
2089
2090 GURL url2(kDefaultURL);
2091 base::WeakPtr<SpdyStream> spdy_stream2 =
2092 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2093 session, url2, LOWEST, BoundNetLog());
2094 ASSERT_TRUE(spdy_stream2.get() != NULL);
2095 EXPECT_EQ(0u, spdy_stream2->stream_id());
2096
2097 // Make |spdy_stream1| close |spdy_stream2|.
2098 test::ClosingDelegate delegate1(spdy_stream2);
2099 spdy_stream1->SetDelegate(&delegate1);
2100
2101 // Make |spdy_stream2| close |spdy_stream1|.
2102 test::ClosingDelegate delegate2(spdy_stream1);
2103 spdy_stream2->SetDelegate(&delegate2);
2104
2105 scoped_ptr<SpdyHeaderBlock> headers(
2106 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2107 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2108 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2109
2110 scoped_ptr<SpdyHeaderBlock> headers2(
2111 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2112 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2113 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2114
2115 // Ensure that the streams have not yet been activated and assigned an id.
2116 EXPECT_EQ(0u, spdy_stream1->stream_id());
2117 EXPECT_EQ(0u, spdy_stream2->stream_id());
2118
2119 // Ensure we don't crash while closing the session.
2120 session->CloseSessionOnError(ERR_ABORTED, std::string());
2121
2122 EXPECT_EQ(NULL, spdy_stream1.get());
2123 EXPECT_EQ(NULL, spdy_stream2.get());
2124
2125 EXPECT_TRUE(delegate1.StreamIsClosed());
2126 EXPECT_TRUE(delegate2.StreamIsClosed());
2127
2128 base::MessageLoop::current()->RunUntilIdle();
2129 EXPECT_TRUE(session == NULL);
2130 }
2131
2132 // Create two streams that are set to re-close themselves on close,
2133 // activate them, and then close the session. Nothing should blow up.
TEST_P(SpdySessionTest,CloseSessionWithTwoActivatedSelfClosingStreams)2134 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
2135 session_deps_.host_resolver->set_synchronous_mode(true);
2136
2137 MockConnect connect_data(SYNCHRONOUS, OK);
2138
2139 scoped_ptr<SpdyFrame> req1(
2140 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2141 scoped_ptr<SpdyFrame> req2(
2142 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2143 MockWrite writes[] = {
2144 CreateMockWrite(*req1, 0),
2145 CreateMockWrite(*req2, 1),
2146 };
2147
2148 MockRead reads[] = {
2149 MockRead(ASYNC, 0, 2) // EOF
2150 };
2151
2152 DeterministicSocketData data(reads, arraysize(reads),
2153 writes, arraysize(writes));
2154 data.set_connect_data(connect_data);
2155 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2156
2157 CreateDeterministicNetworkSession();
2158
2159 base::WeakPtr<SpdySession> session =
2160 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2161
2162 GURL url1(kDefaultURL);
2163 base::WeakPtr<SpdyStream> spdy_stream1 =
2164 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2165 session, url1, MEDIUM, BoundNetLog());
2166 ASSERT_TRUE(spdy_stream1.get() != NULL);
2167 EXPECT_EQ(0u, spdy_stream1->stream_id());
2168
2169 GURL url2(kDefaultURL);
2170 base::WeakPtr<SpdyStream> spdy_stream2 =
2171 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2172 session, url2, MEDIUM, BoundNetLog());
2173 ASSERT_TRUE(spdy_stream2.get() != NULL);
2174 EXPECT_EQ(0u, spdy_stream2->stream_id());
2175
2176 test::ClosingDelegate delegate1(spdy_stream1);
2177 spdy_stream1->SetDelegate(&delegate1);
2178
2179 test::ClosingDelegate delegate2(spdy_stream2);
2180 spdy_stream2->SetDelegate(&delegate2);
2181
2182 scoped_ptr<SpdyHeaderBlock> headers(
2183 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2184 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2185 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2186
2187 scoped_ptr<SpdyHeaderBlock> headers2(
2188 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2189 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2190 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2191
2192 // Ensure that the streams have not yet been activated and assigned an id.
2193 EXPECT_EQ(0u, spdy_stream1->stream_id());
2194 EXPECT_EQ(0u, spdy_stream2->stream_id());
2195
2196 data.RunFor(2);
2197
2198 EXPECT_EQ(1u, spdy_stream1->stream_id());
2199 EXPECT_EQ(3u, spdy_stream2->stream_id());
2200
2201 // Ensure we don't crash while closing the session.
2202 session->CloseSessionOnError(ERR_ABORTED, std::string());
2203
2204 EXPECT_EQ(NULL, spdy_stream1.get());
2205 EXPECT_EQ(NULL, spdy_stream2.get());
2206
2207 EXPECT_TRUE(delegate1.StreamIsClosed());
2208 EXPECT_TRUE(delegate2.StreamIsClosed());
2209
2210 base::MessageLoop::current()->RunUntilIdle();
2211 EXPECT_TRUE(session == NULL);
2212 }
2213
2214 // Create two streams that are set to close each other on close,
2215 // activate them, and then close the session. Nothing should blow up.
TEST_P(SpdySessionTest,CloseSessionWithTwoActivatedMutuallyClosingStreams)2216 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2217 session_deps_.host_resolver->set_synchronous_mode(true);
2218
2219 MockConnect connect_data(SYNCHRONOUS, OK);
2220
2221 scoped_ptr<SpdyFrame> req1(
2222 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2223 scoped_ptr<SpdyFrame> req2(
2224 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2225 MockWrite writes[] = {
2226 CreateMockWrite(*req1, 0),
2227 CreateMockWrite(*req2, 1),
2228 };
2229
2230 MockRead reads[] = {
2231 MockRead(ASYNC, 0, 2) // EOF
2232 };
2233
2234 DeterministicSocketData data(reads, arraysize(reads),
2235 writes, arraysize(writes));
2236 data.set_connect_data(connect_data);
2237 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2238
2239 CreateDeterministicNetworkSession();
2240
2241 base::WeakPtr<SpdySession> session =
2242 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2243
2244 GURL url1(kDefaultURL);
2245 base::WeakPtr<SpdyStream> spdy_stream1 =
2246 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2247 session, url1, MEDIUM, BoundNetLog());
2248 ASSERT_TRUE(spdy_stream1.get() != NULL);
2249 EXPECT_EQ(0u, spdy_stream1->stream_id());
2250
2251 GURL url2(kDefaultURL);
2252 base::WeakPtr<SpdyStream> spdy_stream2 =
2253 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2254 session, url2, MEDIUM, BoundNetLog());
2255 ASSERT_TRUE(spdy_stream2.get() != NULL);
2256 EXPECT_EQ(0u, spdy_stream2->stream_id());
2257
2258 // Make |spdy_stream1| close |spdy_stream2|.
2259 test::ClosingDelegate delegate1(spdy_stream2);
2260 spdy_stream1->SetDelegate(&delegate1);
2261
2262 // Make |spdy_stream2| close |spdy_stream1|.
2263 test::ClosingDelegate delegate2(spdy_stream1);
2264 spdy_stream2->SetDelegate(&delegate2);
2265
2266 scoped_ptr<SpdyHeaderBlock> headers(
2267 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2268 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2269 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2270
2271 scoped_ptr<SpdyHeaderBlock> headers2(
2272 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2273 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2274 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2275
2276 // Ensure that the streams have not yet been activated and assigned an id.
2277 EXPECT_EQ(0u, spdy_stream1->stream_id());
2278 EXPECT_EQ(0u, spdy_stream2->stream_id());
2279
2280 data.RunFor(2);
2281
2282 EXPECT_EQ(1u, spdy_stream1->stream_id());
2283 EXPECT_EQ(3u, spdy_stream2->stream_id());
2284
2285 // Ensure we don't crash while closing the session.
2286 session->CloseSessionOnError(ERR_ABORTED, std::string());
2287
2288 EXPECT_EQ(NULL, spdy_stream1.get());
2289 EXPECT_EQ(NULL, spdy_stream2.get());
2290
2291 EXPECT_TRUE(delegate1.StreamIsClosed());
2292 EXPECT_TRUE(delegate2.StreamIsClosed());
2293
2294 base::MessageLoop::current()->RunUntilIdle();
2295 EXPECT_TRUE(session == NULL);
2296 }
2297
2298 // Delegate that closes a given session when the stream is closed.
2299 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2300 public:
SessionClosingDelegate(const base::WeakPtr<SpdyStream> & stream,const base::WeakPtr<SpdySession> & session_to_close)2301 SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2302 const base::WeakPtr<SpdySession>& session_to_close)
2303 : StreamDelegateDoNothing(stream),
2304 session_to_close_(session_to_close) {}
2305
~SessionClosingDelegate()2306 virtual ~SessionClosingDelegate() {}
2307
OnClose(int status)2308 virtual void OnClose(int status) OVERRIDE {
2309 session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2310 }
2311
2312 private:
2313 base::WeakPtr<SpdySession> session_to_close_;
2314 };
2315
2316 // Close an activated stream that closes its session. Nothing should
2317 // blow up. This is a regression test for http://crbug.com/263691 .
TEST_P(SpdySessionTest,CloseActivatedStreamThatClosesSession)2318 TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2319 session_deps_.host_resolver->set_synchronous_mode(true);
2320
2321 MockConnect connect_data(SYNCHRONOUS, OK);
2322
2323 scoped_ptr<SpdyFrame> req(
2324 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2325 scoped_ptr<SpdyFrame> rst(
2326 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2327 scoped_ptr<SpdyFrame> goaway(
2328 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2329 // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2330 // despite being queued second.
2331 MockWrite writes[] = {
2332 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 1),
2333 CreateMockWrite(*rst, 2),
2334 };
2335
2336 MockRead reads[] = {
2337 MockRead(ASYNC, 0, 3) // EOF
2338 };
2339 DeterministicSocketData data(reads, arraysize(reads),
2340 writes, arraysize(writes));
2341 data.set_connect_data(connect_data);
2342 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2343
2344 CreateDeterministicNetworkSession();
2345
2346 base::WeakPtr<SpdySession> session =
2347 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2348
2349 GURL url(kDefaultURL);
2350 base::WeakPtr<SpdyStream> spdy_stream =
2351 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2352 session, url, MEDIUM, BoundNetLog());
2353 ASSERT_TRUE(spdy_stream.get() != NULL);
2354 EXPECT_EQ(0u, spdy_stream->stream_id());
2355
2356 SessionClosingDelegate delegate(spdy_stream, session);
2357 spdy_stream->SetDelegate(&delegate);
2358
2359 scoped_ptr<SpdyHeaderBlock> headers(
2360 spdy_util_.ConstructGetHeaderBlock(url.spec()));
2361 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2362 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2363
2364 EXPECT_EQ(0u, spdy_stream->stream_id());
2365
2366 data.RunFor(1);
2367
2368 EXPECT_EQ(1u, spdy_stream->stream_id());
2369
2370 // Ensure we don't crash while closing the stream (which closes the
2371 // session).
2372 spdy_stream->Cancel();
2373
2374 EXPECT_EQ(NULL, spdy_stream.get());
2375 EXPECT_TRUE(delegate.StreamIsClosed());
2376
2377 data.RunFor(2); // Write the RST_STREAM & GOAWAY.
2378 base::MessageLoop::current()->RunUntilIdle();
2379 EXPECT_TRUE(session == NULL);
2380 }
2381
TEST_P(SpdySessionTest,VerifyDomainAuthentication)2382 TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2383 session_deps_.host_resolver->set_synchronous_mode(true);
2384
2385 MockConnect connect_data(SYNCHRONOUS, OK);
2386
2387 // No actual data will be sent.
2388 MockWrite writes[] = {
2389 MockWrite(ASYNC, 0, 1) // EOF
2390 };
2391
2392 MockRead reads[] = {
2393 MockRead(ASYNC, 0, 0) // EOF
2394 };
2395 DeterministicSocketData data(reads, arraysize(reads),
2396 writes, arraysize(writes));
2397 data.set_connect_data(connect_data);
2398 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2399
2400 // Load a cert that is valid for:
2401 // www.example.org
2402 // mail.example.org
2403 // www.example.com
2404 base::FilePath certs_dir = GetTestCertsDirectory();
2405 scoped_refptr<X509Certificate> test_cert(
2406 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2407 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2408
2409 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2410 ssl.cert = test_cert;
2411 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2412
2413 CreateDeterministicNetworkSession();
2414
2415 base::WeakPtr<SpdySession> session =
2416 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2417
2418 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2419 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2420 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
2421 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2422 }
2423
TEST_P(SpdySessionTest,ConnectionPooledWithTlsChannelId)2424 TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2425 session_deps_.host_resolver->set_synchronous_mode(true);
2426
2427 MockConnect connect_data(SYNCHRONOUS, OK);
2428
2429 // No actual data will be sent.
2430 MockWrite writes[] = {
2431 MockWrite(ASYNC, 0, 1) // EOF
2432 };
2433
2434 MockRead reads[] = {
2435 MockRead(ASYNC, 0, 0) // EOF
2436 };
2437 DeterministicSocketData data(reads, arraysize(reads),
2438 writes, arraysize(writes));
2439 data.set_connect_data(connect_data);
2440 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2441
2442 // Load a cert that is valid for:
2443 // www.example.org
2444 // mail.example.org
2445 // www.example.com
2446 base::FilePath certs_dir = GetTestCertsDirectory();
2447 scoped_refptr<X509Certificate> test_cert(
2448 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2449 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2450
2451 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2452 ssl.channel_id_sent = true;
2453 ssl.cert = test_cert;
2454 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2455
2456 CreateDeterministicNetworkSession();
2457
2458 base::WeakPtr<SpdySession> session =
2459 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2460
2461 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2462 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2463 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2464 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2465 }
2466
TEST_P(SpdySessionTest,CloseTwoStalledCreateStream)2467 TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2468 // TODO(rtenneti): Define a helper class/methods and move the common code in
2469 // this file.
2470 MockConnect connect_data(SYNCHRONOUS, OK);
2471
2472 SettingsMap new_settings;
2473 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2474 const uint32 max_concurrent_streams = 1;
2475 new_settings[kSpdySettingsIds1] =
2476 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2477
2478 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
2479 scoped_ptr<SpdyFrame> req1(
2480 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2481 scoped_ptr<SpdyFrame> req2(
2482 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
2483 scoped_ptr<SpdyFrame> req3(
2484 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
2485 MockWrite writes[] = {
2486 CreateMockWrite(*settings_ack, 1),
2487 CreateMockWrite(*req1, 2),
2488 CreateMockWrite(*req2, 5),
2489 CreateMockWrite(*req3, 8),
2490 };
2491
2492 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2493 // streams to 1.
2494 scoped_ptr<SpdyFrame> settings_frame(
2495 spdy_util_.ConstructSpdySettings(new_settings));
2496
2497 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2498 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2499
2500 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2501 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2502
2503 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
2504 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2505
2506 MockRead reads[] = {
2507 CreateMockRead(*settings_frame),
2508 CreateMockRead(*resp1, 3),
2509 CreateMockRead(*body1, 4),
2510 CreateMockRead(*resp2, 6),
2511 CreateMockRead(*body2, 7),
2512 CreateMockRead(*resp3, 9),
2513 CreateMockRead(*body3, 10),
2514 MockRead(ASYNC, 0, 11) // EOF
2515 };
2516
2517 DeterministicSocketData data(reads, arraysize(reads),
2518 writes, arraysize(writes));
2519 data.set_connect_data(connect_data);
2520 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2521
2522 CreateDeterministicNetworkSession();
2523
2524 base::WeakPtr<SpdySession> session =
2525 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2526
2527 // Read the settings frame.
2528 data.RunFor(1);
2529
2530 GURL url1(kDefaultURL);
2531 base::WeakPtr<SpdyStream> spdy_stream1 =
2532 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2533 session, url1, LOWEST, BoundNetLog());
2534 ASSERT_TRUE(spdy_stream1.get() != NULL);
2535 EXPECT_EQ(0u, spdy_stream1->stream_id());
2536 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2537 spdy_stream1->SetDelegate(&delegate1);
2538
2539 TestCompletionCallback callback2;
2540 GURL url2(kDefaultURL);
2541 SpdyStreamRequest request2;
2542 ASSERT_EQ(ERR_IO_PENDING,
2543 request2.StartRequest(
2544 SPDY_REQUEST_RESPONSE_STREAM,
2545 session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2546
2547 TestCompletionCallback callback3;
2548 GURL url3(kDefaultURL);
2549 SpdyStreamRequest request3;
2550 ASSERT_EQ(ERR_IO_PENDING,
2551 request3.StartRequest(
2552 SPDY_REQUEST_RESPONSE_STREAM,
2553 session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2554
2555 EXPECT_EQ(0u, session->num_active_streams());
2556 EXPECT_EQ(1u, session->num_created_streams());
2557 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2558
2559 scoped_ptr<SpdyHeaderBlock> headers(
2560 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2561 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2562 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2563
2564 // Run until 1st stream is activated and then closed.
2565 EXPECT_EQ(0u, delegate1.stream_id());
2566 data.RunFor(4);
2567 EXPECT_EQ(NULL, spdy_stream1.get());
2568 EXPECT_EQ(1u, delegate1.stream_id());
2569
2570 EXPECT_EQ(0u, session->num_active_streams());
2571 EXPECT_EQ(0u, session->num_created_streams());
2572 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2573
2574 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2575 // create the 2nd stream.
2576 base::MessageLoop::current()->RunUntilIdle();
2577
2578 EXPECT_EQ(0u, session->num_active_streams());
2579 EXPECT_EQ(1u, session->num_created_streams());
2580 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2581
2582 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2583 test::StreamDelegateDoNothing delegate2(stream2);
2584 stream2->SetDelegate(&delegate2);
2585 scoped_ptr<SpdyHeaderBlock> headers2(
2586 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2587 stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2588 EXPECT_TRUE(stream2->HasUrlFromHeaders());
2589
2590 // Run until 2nd stream is activated and then closed.
2591 EXPECT_EQ(0u, delegate2.stream_id());
2592 data.RunFor(3);
2593 EXPECT_EQ(NULL, stream2.get());
2594 EXPECT_EQ(3u, delegate2.stream_id());
2595
2596 EXPECT_EQ(0u, session->num_active_streams());
2597 EXPECT_EQ(0u, session->num_created_streams());
2598 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2599
2600 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2601 // create the 3rd stream.
2602 base::MessageLoop::current()->RunUntilIdle();
2603
2604 EXPECT_EQ(0u, session->num_active_streams());
2605 EXPECT_EQ(1u, session->num_created_streams());
2606 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2607
2608 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2609 test::StreamDelegateDoNothing delegate3(stream3);
2610 stream3->SetDelegate(&delegate3);
2611 scoped_ptr<SpdyHeaderBlock> headers3(
2612 spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2613 stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2614 EXPECT_TRUE(stream3->HasUrlFromHeaders());
2615
2616 // Run until 2nd stream is activated and then closed.
2617 EXPECT_EQ(0u, delegate3.stream_id());
2618 data.RunFor(3);
2619 EXPECT_EQ(NULL, stream3.get());
2620 EXPECT_EQ(5u, delegate3.stream_id());
2621
2622 EXPECT_EQ(0u, session->num_active_streams());
2623 EXPECT_EQ(0u, session->num_created_streams());
2624 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2625
2626 data.RunFor(1);
2627 }
2628
TEST_P(SpdySessionTest,CancelTwoStalledCreateStream)2629 TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2630 session_deps_.host_resolver->set_synchronous_mode(true);
2631
2632 MockRead reads[] = {
2633 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2634 };
2635
2636 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2637 MockConnect connect_data(SYNCHRONOUS, OK);
2638
2639 data.set_connect_data(connect_data);
2640 session_deps_.socket_factory->AddSocketDataProvider(&data);
2641
2642 CreateNetworkSession();
2643
2644 base::WeakPtr<SpdySession> session =
2645 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2646
2647 // Leave room for only one more stream to be created.
2648 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2649 base::WeakPtr<SpdyStream> spdy_stream =
2650 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2651 session, test_url_, MEDIUM, BoundNetLog());
2652 ASSERT_TRUE(spdy_stream != NULL);
2653 }
2654
2655 GURL url1(kDefaultURL);
2656 base::WeakPtr<SpdyStream> spdy_stream1 =
2657 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2658 session, url1, LOWEST, BoundNetLog());
2659 ASSERT_TRUE(spdy_stream1.get() != NULL);
2660 EXPECT_EQ(0u, spdy_stream1->stream_id());
2661
2662 TestCompletionCallback callback2;
2663 GURL url2(kDefaultURL);
2664 SpdyStreamRequest request2;
2665 ASSERT_EQ(ERR_IO_PENDING,
2666 request2.StartRequest(
2667 SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2668 callback2.callback()));
2669
2670 TestCompletionCallback callback3;
2671 GURL url3(kDefaultURL);
2672 SpdyStreamRequest request3;
2673 ASSERT_EQ(ERR_IO_PENDING,
2674 request3.StartRequest(
2675 SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2676 callback3.callback()));
2677
2678 EXPECT_EQ(0u, session->num_active_streams());
2679 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2680 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2681
2682 // Cancel the first stream; this will allow the second stream to be created.
2683 EXPECT_TRUE(spdy_stream1.get() != NULL);
2684 spdy_stream1->Cancel();
2685 EXPECT_EQ(NULL, spdy_stream1.get());
2686
2687 EXPECT_EQ(OK, callback2.WaitForResult());
2688 EXPECT_EQ(0u, session->num_active_streams());
2689 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2690 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2691
2692 // Cancel the second stream; this will allow the third stream to be created.
2693 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2694 spdy_stream2->Cancel();
2695 EXPECT_EQ(NULL, spdy_stream2.get());
2696
2697 EXPECT_EQ(OK, callback3.WaitForResult());
2698 EXPECT_EQ(0u, session->num_active_streams());
2699 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2700 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2701
2702 // Cancel the third stream.
2703 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2704 spdy_stream3->Cancel();
2705 EXPECT_EQ(NULL, spdy_stream3.get());
2706 EXPECT_EQ(0u, session->num_active_streams());
2707 EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
2708 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2709 }
2710
2711 // Test that SpdySession::DoReadLoop reads data from the socket
2712 // without yielding. This test makes 32k - 1 bytes of data available
2713 // on the socket for reading. It then verifies that it has read all
2714 // the available data without yielding.
TEST_P(SpdySessionTest,ReadDataWithoutYielding)2715 TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2716 MockConnect connect_data(SYNCHRONOUS, OK);
2717 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2718
2719 scoped_ptr<SpdyFrame> req1(
2720 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2721 MockWrite writes[] = {
2722 CreateMockWrite(*req1, 0),
2723 };
2724
2725 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2726 // (-spdy_data_frame_size).
2727 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2728 const int kPayloadSize =
2729 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2730 TestDataStream test_stream;
2731 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2732 char* payload_data = payload->data();
2733 test_stream.GetBytes(payload_data, kPayloadSize);
2734
2735 scoped_ptr<SpdyFrame> partial_data_frame(
2736 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2737 scoped_ptr<SpdyFrame> finish_data_frame(
2738 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2739
2740 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2741
2742 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2743 // bytes.
2744 MockRead reads[] = {
2745 CreateMockRead(*resp1, 1),
2746 CreateMockRead(*partial_data_frame, 2),
2747 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2748 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2749 CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2750 MockRead(ASYNC, 0, 6) // EOF
2751 };
2752
2753 // Create SpdySession and SpdyStream and send the request.
2754 DeterministicSocketData data(reads, arraysize(reads),
2755 writes, arraysize(writes));
2756 data.set_connect_data(connect_data);
2757 session_deps_.host_resolver->set_synchronous_mode(true);
2758 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2759
2760 CreateDeterministicNetworkSession();
2761
2762 base::WeakPtr<SpdySession> session =
2763 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2764
2765 GURL url1(kDefaultURL);
2766 base::WeakPtr<SpdyStream> spdy_stream1 =
2767 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2768 session, url1, MEDIUM, BoundNetLog());
2769 ASSERT_TRUE(spdy_stream1.get() != NULL);
2770 EXPECT_EQ(0u, spdy_stream1->stream_id());
2771 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2772 spdy_stream1->SetDelegate(&delegate1);
2773
2774 scoped_ptr<SpdyHeaderBlock> headers1(
2775 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2776 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2777 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2778
2779 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2780 // post a task.
2781 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2782
2783 // Run until 1st read.
2784 EXPECT_EQ(0u, delegate1.stream_id());
2785 data.RunFor(2);
2786 EXPECT_EQ(1u, delegate1.stream_id());
2787 EXPECT_EQ(0u, observer.executed_count());
2788
2789 // Read all the data and verify SpdySession::DoReadLoop has not
2790 // posted a task.
2791 data.RunFor(4);
2792 EXPECT_EQ(NULL, spdy_stream1.get());
2793
2794 // Verify task observer's executed_count is zero, which indicates DoRead read
2795 // all the available data.
2796 EXPECT_EQ(0u, observer.executed_count());
2797 EXPECT_TRUE(data.at_write_eof());
2798 EXPECT_TRUE(data.at_read_eof());
2799 }
2800
2801 // Test that SpdySession::DoReadLoop yields while reading the
2802 // data. This test makes 32k + 1 bytes of data available on the socket
2803 // for reading. It then verifies that DoRead has yielded even though
2804 // there is data available for it to read (i.e, socket()->Read didn't
2805 // return ERR_IO_PENDING during socket reads).
TEST_P(SpdySessionTest,TestYieldingDuringReadData)2806 TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2807 MockConnect connect_data(SYNCHRONOUS, OK);
2808 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2809
2810 scoped_ptr<SpdyFrame> req1(
2811 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2812 MockWrite writes[] = {
2813 CreateMockWrite(*req1, 0),
2814 };
2815
2816 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2817 // (-spdy_data_frame_size).
2818 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2819 const int kPayloadSize =
2820 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2821 TestDataStream test_stream;
2822 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2823 char* payload_data = payload->data();
2824 test_stream.GetBytes(payload_data, kPayloadSize);
2825
2826 scoped_ptr<SpdyFrame> partial_data_frame(
2827 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2828 scoped_ptr<SpdyFrame> finish_data_frame(
2829 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2830
2831 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2832
2833 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2834 MockRead reads[] = {
2835 CreateMockRead(*resp1, 1),
2836 CreateMockRead(*partial_data_frame, 2),
2837 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2838 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2839 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2840 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2841 MockRead(ASYNC, 0, 7) // EOF
2842 };
2843
2844 // Create SpdySession and SpdyStream and send the request.
2845 DeterministicSocketData data(reads, arraysize(reads),
2846 writes, arraysize(writes));
2847 data.set_connect_data(connect_data);
2848 session_deps_.host_resolver->set_synchronous_mode(true);
2849 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2850
2851 CreateDeterministicNetworkSession();
2852
2853 base::WeakPtr<SpdySession> session =
2854 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2855
2856 GURL url1(kDefaultURL);
2857 base::WeakPtr<SpdyStream> spdy_stream1 =
2858 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2859 session, url1, MEDIUM, BoundNetLog());
2860 ASSERT_TRUE(spdy_stream1.get() != NULL);
2861 EXPECT_EQ(0u, spdy_stream1->stream_id());
2862 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2863 spdy_stream1->SetDelegate(&delegate1);
2864
2865 scoped_ptr<SpdyHeaderBlock> headers1(
2866 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2867 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2868 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2869
2870 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2871 // task.
2872 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2873
2874 // Run until 1st read.
2875 EXPECT_EQ(0u, delegate1.stream_id());
2876 data.RunFor(2);
2877 EXPECT_EQ(1u, delegate1.stream_id());
2878 EXPECT_EQ(0u, observer.executed_count());
2879
2880 // Read all the data and verify SpdySession::DoReadLoop has posted a
2881 // task.
2882 data.RunFor(6);
2883 EXPECT_EQ(NULL, spdy_stream1.get());
2884
2885 // Verify task observer's executed_count is 1, which indicates DoRead has
2886 // posted only one task and thus yielded though there is data available for it
2887 // to read.
2888 EXPECT_EQ(1u, observer.executed_count());
2889 EXPECT_TRUE(data.at_write_eof());
2890 EXPECT_TRUE(data.at_read_eof());
2891 }
2892
2893 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2894 // + async, by doing the following MockReads.
2895 //
2896 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2897 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2898 //
2899 // The above reads 26K synchronously. Since that is less that 32K, we
2900 // will attempt to read again. However, that DoRead() will return
2901 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2902 // yield. When we come back, DoRead() will read the results from the
2903 // async read, and rest of the data synchronously.
TEST_P(SpdySessionTest,TestYieldingDuringAsyncReadData)2904 TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2905 MockConnect connect_data(SYNCHRONOUS, OK);
2906 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2907
2908 scoped_ptr<SpdyFrame> req1(
2909 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2910 MockWrite writes[] = {
2911 CreateMockWrite(*req1, 0),
2912 };
2913
2914 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2915 // (-spdy_data_frame_size).
2916 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2917 TestDataStream test_stream;
2918 const int kEightKPayloadSize =
2919 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2920 scoped_refptr<net::IOBuffer> eightk_payload(
2921 new net::IOBuffer(kEightKPayloadSize));
2922 char* eightk_payload_data = eightk_payload->data();
2923 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2924
2925 // Build buffer of 2k size.
2926 TestDataStream test_stream2;
2927 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2928 scoped_refptr<net::IOBuffer> twok_payload(
2929 new net::IOBuffer(kTwoKPayloadSize));
2930 char* twok_payload_data = twok_payload->data();
2931 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2932
2933 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2934 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2935 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2936 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2937 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2938 1, "h", 1, DATA_FLAG_FIN));
2939
2940 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2941
2942 MockRead reads[] = {
2943 CreateMockRead(*resp1, 1),
2944 CreateMockRead(*eightk_data_frame, 2),
2945 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
2946 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2947 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
2948 CreateMockRead(*eightk_data_frame, 6, ASYNC),
2949 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
2950 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2951 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2952 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
2953 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
2954 MockRead(ASYNC, 0, 12) // EOF
2955 };
2956
2957 // Create SpdySession and SpdyStream and send the request.
2958 DeterministicSocketData data(reads, arraysize(reads),
2959 writes, arraysize(writes));
2960 data.set_connect_data(connect_data);
2961 session_deps_.host_resolver->set_synchronous_mode(true);
2962 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2963
2964 CreateDeterministicNetworkSession();
2965
2966 base::WeakPtr<SpdySession> session =
2967 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2968
2969 GURL url1(kDefaultURL);
2970 base::WeakPtr<SpdyStream> spdy_stream1 =
2971 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2972 session, url1, MEDIUM, BoundNetLog());
2973 ASSERT_TRUE(spdy_stream1.get() != NULL);
2974 EXPECT_EQ(0u, spdy_stream1->stream_id());
2975 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2976 spdy_stream1->SetDelegate(&delegate1);
2977
2978 scoped_ptr<SpdyHeaderBlock> headers1(
2979 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2980 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2981 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2982
2983 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2984 // posting of tasks.
2985 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2986
2987 // Run until 1st read.
2988 EXPECT_EQ(0u, delegate1.stream_id());
2989 data.RunFor(2);
2990 EXPECT_EQ(1u, delegate1.stream_id());
2991 EXPECT_EQ(0u, observer.executed_count());
2992
2993 // Read all the data and verify SpdySession::DoReadLoop has posted a
2994 // task.
2995 data.RunFor(12);
2996 EXPECT_EQ(NULL, spdy_stream1.get());
2997
2998 // Verify task observer's executed_count is 1, which indicates DoRead has
2999 // posted only one task and thus yielded though there is data available for
3000 // it to read.
3001 EXPECT_EQ(1u, observer.executed_count());
3002 EXPECT_TRUE(data.at_write_eof());
3003 EXPECT_TRUE(data.at_read_eof());
3004 }
3005
3006 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
3007 // nothing blows up.
TEST_P(SpdySessionTest,GoAwayWhileInDoReadLoop)3008 TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
3009 MockConnect connect_data(SYNCHRONOUS, OK);
3010 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3011
3012 scoped_ptr<SpdyFrame> req1(
3013 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3014 MockWrite writes[] = {
3015 CreateMockWrite(*req1, 0),
3016 };
3017
3018 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3019 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
3020 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
3021
3022 MockRead reads[] = {
3023 CreateMockRead(*resp1, 1),
3024 CreateMockRead(*body1, 2),
3025 CreateMockRead(*goaway, 3),
3026 };
3027
3028 // Create SpdySession and SpdyStream and send the request.
3029 DeterministicSocketData data(reads, arraysize(reads),
3030 writes, arraysize(writes));
3031 data.set_connect_data(connect_data);
3032 session_deps_.host_resolver->set_synchronous_mode(true);
3033 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3034
3035 CreateDeterministicNetworkSession();
3036
3037 base::WeakPtr<SpdySession> session =
3038 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3039
3040 GURL url1(kDefaultURL);
3041 base::WeakPtr<SpdyStream> spdy_stream1 =
3042 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3043 session, url1, MEDIUM, BoundNetLog());
3044 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3045 spdy_stream1->SetDelegate(&delegate1);
3046 ASSERT_TRUE(spdy_stream1.get() != NULL);
3047 EXPECT_EQ(0u, spdy_stream1->stream_id());
3048
3049 scoped_ptr<SpdyHeaderBlock> headers1(
3050 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3051 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
3052 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3053
3054 // Run until 1st read.
3055 EXPECT_EQ(0u, spdy_stream1->stream_id());
3056 data.RunFor(1);
3057 EXPECT_EQ(1u, spdy_stream1->stream_id());
3058
3059 // Run until GoAway.
3060 data.RunFor(3);
3061 EXPECT_EQ(NULL, spdy_stream1.get());
3062 EXPECT_TRUE(data.at_write_eof());
3063 EXPECT_TRUE(data.at_read_eof());
3064 EXPECT_TRUE(session == NULL);
3065 }
3066
3067 // Within this framework, a SpdySession should be initialized with
3068 // flow control disabled for protocol version 2, with flow control
3069 // enabled only for streams for protocol version 3, and with flow
3070 // control enabled for streams and sessions for higher versions.
TEST_P(SpdySessionTest,ProtocolNegotiation)3071 TEST_P(SpdySessionTest, ProtocolNegotiation) {
3072 session_deps_.host_resolver->set_synchronous_mode(true);
3073
3074 MockConnect connect_data(SYNCHRONOUS, OK);
3075 MockRead reads[] = {
3076 MockRead(SYNCHRONOUS, 0, 0) // EOF
3077 };
3078 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3079 data.set_connect_data(connect_data);
3080 session_deps_.socket_factory->AddSocketDataProvider(&data);
3081
3082 CreateNetworkSession();
3083 base::WeakPtr<SpdySession> session =
3084 CreateFakeSpdySession(spdy_session_pool_, key_);
3085
3086 EXPECT_EQ(spdy_util_.spdy_version(),
3087 session->buffered_spdy_framer_->protocol_version());
3088 if (GetParam() == kProtoDeprecatedSPDY2) {
3089 EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state());
3090 EXPECT_EQ(0, session->session_send_window_size_);
3091 EXPECT_EQ(0, session->session_recv_window_size_);
3092 } else if (GetParam() == kProtoSPDY3) {
3093 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
3094 EXPECT_EQ(0, session->session_send_window_size_);
3095 EXPECT_EQ(0, session->session_recv_window_size_);
3096 } else {
3097 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3098 session->flow_control_state());
3099 EXPECT_EQ(kSpdySessionInitialWindowSize,
3100 session->session_send_window_size_);
3101 EXPECT_EQ(kSpdySessionInitialWindowSize,
3102 session->session_recv_window_size_);
3103 }
3104 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3105 }
3106
3107 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3108 // pointers to the idle session are currently held.
TEST_P(SpdySessionTest,CloseOneIdleConnection)3109 TEST_P(SpdySessionTest, CloseOneIdleConnection) {
3110 ClientSocketPoolManager::set_max_sockets_per_group(
3111 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3112 ClientSocketPoolManager::set_max_sockets_per_pool(
3113 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3114
3115 MockConnect connect_data(SYNCHRONOUS, OK);
3116 MockRead reads[] = {
3117 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3118 };
3119 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3120 data.set_connect_data(connect_data);
3121 session_deps_.socket_factory->AddSocketDataProvider(&data);
3122 session_deps_.socket_factory->AddSocketDataProvider(&data);
3123
3124 CreateNetworkSession();
3125
3126 TransportClientSocketPool* pool =
3127 http_session_->GetTransportSocketPool(
3128 HttpNetworkSession::NORMAL_SOCKET_POOL);
3129
3130 // Create an idle SPDY session.
3131 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3132 PRIVACY_MODE_DISABLED);
3133 base::WeakPtr<SpdySession> session1 =
3134 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3135 EXPECT_FALSE(pool->IsStalled());
3136
3137 // Trying to create a new connection should cause the pool to be stalled, and
3138 // post a task asynchronously to try and close the session.
3139 TestCompletionCallback callback2;
3140 HostPortPair host_port2("2.com", 80);
3141 scoped_refptr<TransportSocketParams> params2(
3142 new TransportSocketParams(
3143 host_port2, false, false, OnHostResolutionCallback(),
3144 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3145 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3146 EXPECT_EQ(ERR_IO_PENDING,
3147 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3148 callback2.callback(), pool, BoundNetLog()));
3149 EXPECT_TRUE(pool->IsStalled());
3150
3151 // The socket pool should close the connection asynchronously and establish a
3152 // new connection.
3153 EXPECT_EQ(OK, callback2.WaitForResult());
3154 EXPECT_FALSE(pool->IsStalled());
3155 EXPECT_TRUE(session1 == NULL);
3156 }
3157
3158 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3159 // pointers to the idle session are currently held, in the case the SPDY session
3160 // has an alias.
TEST_P(SpdySessionTest,CloseOneIdleConnectionWithAlias)3161 TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
3162 ClientSocketPoolManager::set_max_sockets_per_group(
3163 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3164 ClientSocketPoolManager::set_max_sockets_per_pool(
3165 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3166
3167 MockConnect connect_data(SYNCHRONOUS, OK);
3168 MockRead reads[] = {
3169 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3170 };
3171 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3172 data.set_connect_data(connect_data);
3173 session_deps_.socket_factory->AddSocketDataProvider(&data);
3174 session_deps_.socket_factory->AddSocketDataProvider(&data);
3175
3176 session_deps_.host_resolver->set_synchronous_mode(true);
3177 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3178 "1.com", "192.168.0.2", std::string());
3179 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3180 "2.com", "192.168.0.2", std::string());
3181 // Not strictly needed.
3182 session_deps_.host_resolver->rules()->AddIPLiteralRule(
3183 "3.com", "192.168.0.3", std::string());
3184
3185 CreateNetworkSession();
3186
3187 TransportClientSocketPool* pool =
3188 http_session_->GetTransportSocketPool(
3189 HttpNetworkSession::NORMAL_SOCKET_POOL);
3190
3191 // Create an idle SPDY session.
3192 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3193 PRIVACY_MODE_DISABLED);
3194 base::WeakPtr<SpdySession> session1 =
3195 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3196 EXPECT_FALSE(pool->IsStalled());
3197
3198 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3199 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3200 PRIVACY_MODE_DISABLED);
3201 HostResolver::RequestInfo info(key2.host_port_pair());
3202 AddressList addresses;
3203 // Pre-populate the DNS cache, since a synchronous resolution is required in
3204 // order to create the alias.
3205 session_deps_.host_resolver->Resolve(info,
3206 DEFAULT_PRIORITY,
3207 &addresses,
3208 CompletionCallback(),
3209 NULL,
3210 BoundNetLog());
3211 // Get a session for |key2|, which should return the session created earlier.
3212 base::WeakPtr<SpdySession> session2 =
3213 spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3214 ASSERT_EQ(session1.get(), session2.get());
3215 EXPECT_FALSE(pool->IsStalled());
3216
3217 // Trying to create a new connection should cause the pool to be stalled, and
3218 // post a task asynchronously to try and close the session.
3219 TestCompletionCallback callback3;
3220 HostPortPair host_port3("3.com", 80);
3221 scoped_refptr<TransportSocketParams> params3(
3222 new TransportSocketParams(
3223 host_port3, false, false, OnHostResolutionCallback(),
3224 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3225 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3226 EXPECT_EQ(ERR_IO_PENDING,
3227 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3228 callback3.callback(), pool, BoundNetLog()));
3229 EXPECT_TRUE(pool->IsStalled());
3230
3231 // The socket pool should close the connection asynchronously and establish a
3232 // new connection.
3233 EXPECT_EQ(OK, callback3.WaitForResult());
3234 EXPECT_FALSE(pool->IsStalled());
3235 EXPECT_TRUE(session1 == NULL);
3236 EXPECT_TRUE(session2 == NULL);
3237 }
3238
3239 // Tests that when a SPDY session becomes idle, it closes itself if there is
3240 // a lower layer pool stalled on the per-pool socket limit.
TEST_P(SpdySessionTest,CloseSessionOnIdleWhenPoolStalled)3241 TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3242 ClientSocketPoolManager::set_max_sockets_per_group(
3243 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3244 ClientSocketPoolManager::set_max_sockets_per_pool(
3245 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3246
3247 MockConnect connect_data(SYNCHRONOUS, OK);
3248 MockRead reads[] = {
3249 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3250 };
3251 scoped_ptr<SpdyFrame> req1(
3252 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3253 scoped_ptr<SpdyFrame> cancel1(
3254 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3255 MockWrite writes[] = {
3256 CreateMockWrite(*req1, 1),
3257 CreateMockWrite(*cancel1, 1),
3258 };
3259 StaticSocketDataProvider data(reads, arraysize(reads),
3260 writes, arraysize(writes));
3261 data.set_connect_data(connect_data);
3262 session_deps_.socket_factory->AddSocketDataProvider(&data);
3263
3264 MockRead http_reads[] = {
3265 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
3266 };
3267 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
3268 NULL, 0);
3269 http_data.set_connect_data(connect_data);
3270 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3271
3272
3273 CreateNetworkSession();
3274
3275 TransportClientSocketPool* pool =
3276 http_session_->GetTransportSocketPool(
3277 HttpNetworkSession::NORMAL_SOCKET_POOL);
3278
3279 // Create a SPDY session.
3280 GURL url1(kDefaultURL);
3281 SpdySessionKey key1(HostPortPair(url1.host(), 80),
3282 ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3283 base::WeakPtr<SpdySession> session1 =
3284 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3285 EXPECT_FALSE(pool->IsStalled());
3286
3287 // Create a stream using the session, and send a request.
3288
3289 TestCompletionCallback callback1;
3290 base::WeakPtr<SpdyStream> spdy_stream1 =
3291 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3292 session1, url1, DEFAULT_PRIORITY,
3293 BoundNetLog());
3294 ASSERT_TRUE(spdy_stream1.get());
3295 test::StreamDelegateDoNothing delegate1(spdy_stream1);
3296 spdy_stream1->SetDelegate(&delegate1);
3297
3298 scoped_ptr<SpdyHeaderBlock> headers1(
3299 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3300 EXPECT_EQ(ERR_IO_PENDING,
3301 spdy_stream1->SendRequestHeaders(
3302 headers1.Pass(), NO_MORE_DATA_TO_SEND));
3303 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3304
3305 base::MessageLoop::current()->RunUntilIdle();
3306
3307 // Trying to create a new connection should cause the pool to be stalled, and
3308 // post a task asynchronously to try and close the session.
3309 TestCompletionCallback callback2;
3310 HostPortPair host_port2("2.com", 80);
3311 scoped_refptr<TransportSocketParams> params2(
3312 new TransportSocketParams(
3313 host_port2, false, false, OnHostResolutionCallback(),
3314 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3315 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3316 EXPECT_EQ(ERR_IO_PENDING,
3317 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3318 callback2.callback(), pool, BoundNetLog()));
3319 EXPECT_TRUE(pool->IsStalled());
3320
3321 // Running the message loop should cause the socket pool to ask the SPDY
3322 // session to close an idle socket, but since the socket is in use, nothing
3323 // happens.
3324 base::RunLoop().RunUntilIdle();
3325 EXPECT_TRUE(pool->IsStalled());
3326 EXPECT_FALSE(callback2.have_result());
3327
3328 // Cancelling the request should result in the session's socket being
3329 // closed, since the pool is stalled.
3330 ASSERT_TRUE(spdy_stream1.get());
3331 spdy_stream1->Cancel();
3332 base::RunLoop().RunUntilIdle();
3333 ASSERT_FALSE(pool->IsStalled());
3334 EXPECT_EQ(OK, callback2.WaitForResult());
3335 }
3336
3337 // Verify that SpdySessionKey and therefore SpdySession is different when
3338 // privacy mode is enabled or disabled.
TEST_P(SpdySessionTest,SpdySessionKeyPrivacyMode)3339 TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3340 CreateDeterministicNetworkSession();
3341
3342 HostPortPair host_port_pair("www.google.com", 443);
3343 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3344 PRIVACY_MODE_ENABLED);
3345 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3346 PRIVACY_MODE_DISABLED);
3347
3348 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3349 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3350
3351 // Add SpdySession with PrivacyMode Enabled to the pool.
3352 base::WeakPtr<SpdySession> session_privacy_enabled =
3353 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3354
3355 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3356 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3357
3358 // Add SpdySession with PrivacyMode Disabled to the pool.
3359 base::WeakPtr<SpdySession> session_privacy_disabled =
3360 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3361
3362 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3363 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3364
3365 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3366 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3367 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3368
3369 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3370 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3371 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3372 }
3373
3374 // Delegate that creates another stream when its stream is closed.
3375 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3376 public:
StreamCreatingDelegate(const base::WeakPtr<SpdyStream> & stream,const base::WeakPtr<SpdySession> & session)3377 StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3378 const base::WeakPtr<SpdySession>& session)
3379 : StreamDelegateDoNothing(stream),
3380 session_(session) {}
3381
~StreamCreatingDelegate()3382 virtual ~StreamCreatingDelegate() {}
3383
OnClose(int status)3384 virtual void OnClose(int status) OVERRIDE {
3385 GURL url(kDefaultURL);
3386 ignore_result(
3387 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3388 session_, url, MEDIUM, BoundNetLog()));
3389 }
3390
3391 private:
3392 const base::WeakPtr<SpdySession> session_;
3393 };
3394
3395 // Create another stream in response to a stream being reset. Nothing
3396 // should blow up. This is a regression test for
3397 // http://crbug.com/263690 .
TEST_P(SpdySessionTest,CreateStreamOnStreamReset)3398 TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3399 session_deps_.host_resolver->set_synchronous_mode(true);
3400
3401 MockConnect connect_data(SYNCHRONOUS, OK);
3402
3403 scoped_ptr<SpdyFrame> req(
3404 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3405 MockWrite writes[] = {
3406 CreateMockWrite(*req, 0),
3407 };
3408
3409 scoped_ptr<SpdyFrame> rst(
3410 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3411 MockRead reads[] = {
3412 CreateMockRead(*rst, 1),
3413 MockRead(ASYNC, 0, 2) // EOF
3414 };
3415 DeterministicSocketData data(reads, arraysize(reads),
3416 writes, arraysize(writes));
3417 data.set_connect_data(connect_data);
3418 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3419
3420 CreateDeterministicNetworkSession();
3421
3422 base::WeakPtr<SpdySession> session =
3423 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3424
3425 GURL url(kDefaultURL);
3426 base::WeakPtr<SpdyStream> spdy_stream =
3427 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3428 session, url, MEDIUM, BoundNetLog());
3429 ASSERT_TRUE(spdy_stream.get() != NULL);
3430 EXPECT_EQ(0u, spdy_stream->stream_id());
3431
3432 StreamCreatingDelegate delegate(spdy_stream, session);
3433 spdy_stream->SetDelegate(&delegate);
3434
3435 scoped_ptr<SpdyHeaderBlock> headers(
3436 spdy_util_.ConstructGetHeaderBlock(url.spec()));
3437 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3438 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3439
3440 EXPECT_EQ(0u, spdy_stream->stream_id());
3441
3442 data.RunFor(1);
3443
3444 EXPECT_EQ(1u, spdy_stream->stream_id());
3445
3446 // Cause the stream to be reset, which should cause another stream
3447 // to be created.
3448 data.RunFor(1);
3449
3450 EXPECT_EQ(NULL, spdy_stream.get());
3451 EXPECT_TRUE(delegate.StreamIsClosed());
3452 EXPECT_EQ(0u, session->num_active_streams());
3453 EXPECT_EQ(1u, session->num_created_streams());
3454 }
3455
3456 // The tests below are only for SPDY/3 and above.
3457
TEST_P(SpdySessionTest,UpdateStreamsSendWindowSize)3458 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3459 if (GetParam() < kProtoSPDY3)
3460 return;
3461
3462 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3463 // gets sent.
3464 SettingsMap new_settings;
3465 int32 window_size = 1;
3466 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3467 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3468
3469 // Set up the socket so we read a SETTINGS frame that sets
3470 // INITIAL_WINDOW_SIZE.
3471 MockConnect connect_data(SYNCHRONOUS, OK);
3472 scoped_ptr<SpdyFrame> settings_frame(
3473 spdy_util_.ConstructSpdySettings(new_settings));
3474 MockRead reads[] = {
3475 CreateMockRead(*settings_frame, 0),
3476 MockRead(ASYNC, 0, 1) // EOF
3477 };
3478
3479 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3480 MockWrite writes[] = {
3481 CreateMockWrite(*settings_ack, 2),
3482 };
3483
3484 session_deps_.host_resolver->set_synchronous_mode(true);
3485
3486 DeterministicSocketData data(reads, arraysize(reads),
3487 writes, arraysize(writes));
3488 data.set_connect_data(connect_data);
3489 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3490
3491 CreateDeterministicNetworkSession();
3492
3493 base::WeakPtr<SpdySession> session =
3494 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3495 base::WeakPtr<SpdyStream> spdy_stream1 =
3496 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3497 session, test_url_, MEDIUM, BoundNetLog());
3498 ASSERT_TRUE(spdy_stream1.get() != NULL);
3499 TestCompletionCallback callback1;
3500 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3501
3502 data.RunFor(1); // Process the SETTINGS frame, but not the EOF
3503 base::MessageLoop::current()->RunUntilIdle();
3504 EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3505 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3506
3507 // Release the first one, this will allow the second to be created.
3508 spdy_stream1->Cancel();
3509 EXPECT_EQ(NULL, spdy_stream1.get());
3510
3511 base::WeakPtr<SpdyStream> spdy_stream2 =
3512 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3513 session, test_url_, MEDIUM, BoundNetLog());
3514 ASSERT_TRUE(spdy_stream2.get() != NULL);
3515 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3516 spdy_stream2->Cancel();
3517 EXPECT_EQ(NULL, spdy_stream2.get());
3518 }
3519
3520 // The tests below are only for SPDY/3.1 and above.
3521
3522 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3523 // adjust the session receive window size for SPDY 3.1 and higher. In
3524 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3525 // sending a WINDOW_UPDATE frame for a large enough delta.
TEST_P(SpdySessionTest,AdjustRecvWindowSize)3526 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3527 if (GetParam() < kProtoSPDY31)
3528 return;
3529
3530 session_deps_.host_resolver->set_synchronous_mode(true);
3531
3532 const int32 delta_window_size = 100;
3533
3534 MockConnect connect_data(SYNCHRONOUS, OK);
3535 MockRead reads[] = {
3536 MockRead(ASYNC, 0, 1) // EOF
3537 };
3538 scoped_ptr<SpdyFrame> window_update(
3539 spdy_util_.ConstructSpdyWindowUpdate(
3540 kSessionFlowControlStreamId,
3541 kSpdySessionInitialWindowSize + delta_window_size));
3542 MockWrite writes[] = {
3543 CreateMockWrite(*window_update, 0),
3544 };
3545 DeterministicSocketData data(reads, arraysize(reads),
3546 writes, arraysize(writes));
3547 data.set_connect_data(connect_data);
3548 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3549
3550 CreateDeterministicNetworkSession();
3551 base::WeakPtr<SpdySession> session =
3552 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3553 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3554 session->flow_control_state());
3555
3556 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3557 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3558
3559 session->IncreaseRecvWindowSize(delta_window_size);
3560 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3561 session->session_recv_window_size_);
3562 EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3563
3564 // Should trigger sending a WINDOW_UPDATE frame.
3565 session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize);
3566 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size +
3567 kSpdySessionInitialWindowSize,
3568 session->session_recv_window_size_);
3569 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3570
3571 data.RunFor(1);
3572
3573 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3574 session->in_io_loop_ = true;
3575 session->DecreaseRecvWindowSize(
3576 kSpdySessionInitialWindowSize + delta_window_size +
3577 kSpdySessionInitialWindowSize);
3578 session->in_io_loop_ = false;
3579 EXPECT_EQ(0, session->session_recv_window_size_);
3580 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3581 }
3582
3583 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3584 // adjust the session send window size when the "enable_spdy_31" flag
3585 // is set.
TEST_P(SpdySessionTest,AdjustSendWindowSize)3586 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3587 if (GetParam() < kProtoSPDY31)
3588 return;
3589
3590 session_deps_.host_resolver->set_synchronous_mode(true);
3591
3592 MockConnect connect_data(SYNCHRONOUS, OK);
3593 MockRead reads[] = {
3594 MockRead(SYNCHRONOUS, 0, 0) // EOF
3595 };
3596 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3597 data.set_connect_data(connect_data);
3598 session_deps_.socket_factory->AddSocketDataProvider(&data);
3599
3600 CreateNetworkSession();
3601 base::WeakPtr<SpdySession> session =
3602 CreateFakeSpdySession(spdy_session_pool_, key_);
3603 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3604 session->flow_control_state());
3605
3606 const int32 delta_window_size = 100;
3607
3608 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3609
3610 session->IncreaseSendWindowSize(delta_window_size);
3611 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3612 session->session_send_window_size_);
3613
3614 session->DecreaseSendWindowSize(delta_window_size);
3615 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3616 }
3617
3618 // Incoming data for an inactive stream should not cause the session
3619 // receive window size to decrease, but it should cause the unacked
3620 // bytes to increase.
TEST_P(SpdySessionTest,SessionFlowControlInactiveStream)3621 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3622 if (GetParam() < kProtoSPDY31)
3623 return;
3624
3625 session_deps_.host_resolver->set_synchronous_mode(true);
3626
3627 MockConnect connect_data(SYNCHRONOUS, OK);
3628 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3629 MockRead reads[] = {
3630 CreateMockRead(*resp, 0),
3631 MockRead(ASYNC, 0, 1) // EOF
3632 };
3633 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3634 data.set_connect_data(connect_data);
3635 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3636
3637 CreateDeterministicNetworkSession();
3638 base::WeakPtr<SpdySession> session =
3639 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3640 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3641 session->flow_control_state());
3642
3643 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3644 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3645
3646 data.RunFor(1);
3647
3648 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3649 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3650
3651 data.RunFor(1);
3652 }
3653
3654 // A delegate that drops any received data.
3655 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3656 public:
DropReceivedDataDelegate(const base::WeakPtr<SpdyStream> & stream,base::StringPiece data)3657 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3658 base::StringPiece data)
3659 : StreamDelegateSendImmediate(stream, data) {}
3660
~DropReceivedDataDelegate()3661 virtual ~DropReceivedDataDelegate() {}
3662
3663 // Drop any received data.
OnDataReceived(scoped_ptr<SpdyBuffer> buffer)3664 virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) OVERRIDE {}
3665 };
3666
3667 // Send data back and forth but use a delegate that drops its received
3668 // data. The receive window should still increase to its original
3669 // value, i.e. we shouldn't "leak" receive window bytes.
TEST_P(SpdySessionTest,SessionFlowControlNoReceiveLeaks)3670 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3671 if (GetParam() < kProtoSPDY31)
3672 return;
3673
3674 const char kStreamUrl[] = "http://www.google.com/";
3675
3676 const int32 msg_data_size = 100;
3677 const std::string msg_data(msg_data_size, 'a');
3678
3679 MockConnect connect_data(SYNCHRONOUS, OK);
3680
3681 scoped_ptr<SpdyFrame> req(
3682 spdy_util_.ConstructSpdyPost(
3683 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3684 scoped_ptr<SpdyFrame> msg(
3685 spdy_util_.ConstructSpdyBodyFrame(
3686 1, msg_data.data(), msg_data_size, false));
3687 MockWrite writes[] = {
3688 CreateMockWrite(*req, 0),
3689 CreateMockWrite(*msg, 2),
3690 };
3691
3692 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3693 scoped_ptr<SpdyFrame> echo(
3694 spdy_util_.ConstructSpdyBodyFrame(
3695 1, msg_data.data(), msg_data_size, false));
3696 scoped_ptr<SpdyFrame> window_update(
3697 spdy_util_.ConstructSpdyWindowUpdate(
3698 kSessionFlowControlStreamId, msg_data_size));
3699 MockRead reads[] = {
3700 CreateMockRead(*resp, 1),
3701 CreateMockRead(*echo, 3),
3702 MockRead(ASYNC, 0, 4) // EOF
3703 };
3704
3705 // Create SpdySession and SpdyStream and send the request.
3706 DeterministicSocketData data(reads, arraysize(reads),
3707 writes, arraysize(writes));
3708 data.set_connect_data(connect_data);
3709 session_deps_.host_resolver->set_synchronous_mode(true);
3710 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3711
3712 CreateDeterministicNetworkSession();
3713
3714 base::WeakPtr<SpdySession> session =
3715 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3716
3717 GURL url(kStreamUrl);
3718 base::WeakPtr<SpdyStream> stream =
3719 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3720 session, url, MEDIUM, BoundNetLog());
3721 ASSERT_TRUE(stream.get() != NULL);
3722 EXPECT_EQ(0u, stream->stream_id());
3723
3724 DropReceivedDataDelegate delegate(stream, msg_data);
3725 stream->SetDelegate(&delegate);
3726
3727 scoped_ptr<SpdyHeaderBlock> headers(
3728 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3729 EXPECT_EQ(ERR_IO_PENDING,
3730 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3731 EXPECT_TRUE(stream->HasUrlFromHeaders());
3732
3733 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3734 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3735
3736 data.RunFor(4);
3737
3738 EXPECT_TRUE(data.at_write_eof());
3739 EXPECT_TRUE(data.at_read_eof());
3740
3741 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3742 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3743
3744 stream->Close();
3745 EXPECT_EQ(NULL, stream.get());
3746
3747 EXPECT_EQ(OK, delegate.WaitForClose());
3748
3749 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3750 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3751 }
3752
3753 // Send data back and forth but close the stream before its data frame
3754 // can be written to the socket. The send window should then increase
3755 // to its original value, i.e. we shouldn't "leak" send window bytes.
TEST_P(SpdySessionTest,SessionFlowControlNoSendLeaks)3756 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3757 if (GetParam() < kProtoSPDY31)
3758 return;
3759
3760 const char kStreamUrl[] = "http://www.google.com/";
3761
3762 const int32 msg_data_size = 100;
3763 const std::string msg_data(msg_data_size, 'a');
3764
3765 MockConnect connect_data(SYNCHRONOUS, OK);
3766
3767 scoped_ptr<SpdyFrame> req(
3768 spdy_util_.ConstructSpdyPost(
3769 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3770 MockWrite writes[] = {
3771 CreateMockWrite(*req, 0),
3772 };
3773
3774 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3775 MockRead reads[] = {
3776 CreateMockRead(*resp, 1),
3777 MockRead(ASYNC, 0, 2) // EOF
3778 };
3779
3780 // Create SpdySession and SpdyStream and send the request.
3781 DeterministicSocketData data(reads, arraysize(reads),
3782 writes, arraysize(writes));
3783 data.set_connect_data(connect_data);
3784 session_deps_.host_resolver->set_synchronous_mode(true);
3785 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3786
3787 CreateDeterministicNetworkSession();
3788
3789 base::WeakPtr<SpdySession> session =
3790 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3791
3792 GURL url(kStreamUrl);
3793 base::WeakPtr<SpdyStream> stream =
3794 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3795 session, url, MEDIUM, BoundNetLog());
3796 ASSERT_TRUE(stream.get() != NULL);
3797 EXPECT_EQ(0u, stream->stream_id());
3798
3799 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3800 stream->SetDelegate(&delegate);
3801
3802 scoped_ptr<SpdyHeaderBlock> headers(
3803 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3804 EXPECT_EQ(ERR_IO_PENDING,
3805 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3806 EXPECT_TRUE(stream->HasUrlFromHeaders());
3807
3808 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3809
3810 data.RunFor(1);
3811
3812 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3813
3814 data.RunFor(1);
3815
3816 EXPECT_TRUE(data.at_write_eof());
3817 EXPECT_TRUE(data.at_read_eof());
3818
3819 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3820 session->session_send_window_size_);
3821
3822 // Closing the stream should increase the session's send window.
3823 stream->Close();
3824 EXPECT_EQ(NULL, stream.get());
3825
3826 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3827
3828 EXPECT_EQ(OK, delegate.WaitForClose());
3829 }
3830
3831 // Send data back and forth; the send and receive windows should
3832 // change appropriately.
TEST_P(SpdySessionTest,SessionFlowControlEndToEnd)3833 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
3834 if (GetParam() < kProtoSPDY31)
3835 return;
3836
3837 const char kStreamUrl[] = "http://www.google.com/";
3838
3839 const int32 msg_data_size = 100;
3840 const std::string msg_data(msg_data_size, 'a');
3841
3842 MockConnect connect_data(SYNCHRONOUS, OK);
3843
3844 scoped_ptr<SpdyFrame> req(
3845 spdy_util_.ConstructSpdyPost(
3846 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3847 scoped_ptr<SpdyFrame> msg(
3848 spdy_util_.ConstructSpdyBodyFrame(
3849 1, msg_data.data(), msg_data_size, false));
3850 MockWrite writes[] = {
3851 CreateMockWrite(*req, 0),
3852 CreateMockWrite(*msg, 2),
3853 };
3854
3855 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3856 scoped_ptr<SpdyFrame> echo(
3857 spdy_util_.ConstructSpdyBodyFrame(
3858 1, msg_data.data(), msg_data_size, false));
3859 scoped_ptr<SpdyFrame> window_update(
3860 spdy_util_.ConstructSpdyWindowUpdate(
3861 kSessionFlowControlStreamId, msg_data_size));
3862 MockRead reads[] = {
3863 CreateMockRead(*resp, 1),
3864 CreateMockRead(*echo, 3),
3865 CreateMockRead(*window_update, 4),
3866 MockRead(ASYNC, 0, 5) // EOF
3867 };
3868
3869 // Create SpdySession and SpdyStream and send the request.
3870 DeterministicSocketData data(reads, arraysize(reads),
3871 writes, arraysize(writes));
3872 data.set_connect_data(connect_data);
3873 session_deps_.host_resolver->set_synchronous_mode(true);
3874 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3875
3876 CreateDeterministicNetworkSession();
3877
3878 base::WeakPtr<SpdySession> session =
3879 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3880
3881 GURL url(kStreamUrl);
3882 base::WeakPtr<SpdyStream> stream =
3883 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3884 session, url, MEDIUM, BoundNetLog());
3885 ASSERT_TRUE(stream.get() != NULL);
3886 EXPECT_EQ(0u, stream->stream_id());
3887
3888 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3889 stream->SetDelegate(&delegate);
3890
3891 scoped_ptr<SpdyHeaderBlock> headers(
3892 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3893 EXPECT_EQ(ERR_IO_PENDING,
3894 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3895 EXPECT_TRUE(stream->HasUrlFromHeaders());
3896
3897 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3898 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3899 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3900
3901 data.RunFor(1);
3902
3903 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3904 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3905 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3906
3907 data.RunFor(1);
3908
3909 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3910 session->session_send_window_size_);
3911 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3912 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3913
3914 data.RunFor(1);
3915
3916 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3917 session->session_send_window_size_);
3918 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3919 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3920
3921 data.RunFor(1);
3922
3923 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3924 session->session_send_window_size_);
3925 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3926 session->session_recv_window_size_);
3927 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3928
3929 data.RunFor(1);
3930
3931 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3932 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3933 session->session_recv_window_size_);
3934 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3935
3936 EXPECT_TRUE(data.at_write_eof());
3937 EXPECT_TRUE(data.at_read_eof());
3938
3939 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
3940
3941 // Draining the delegate's read queue should increase the session's
3942 // receive window.
3943 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3944 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3945 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3946
3947 stream->Close();
3948 EXPECT_EQ(NULL, stream.get());
3949
3950 EXPECT_EQ(OK, delegate.WaitForClose());
3951
3952 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3953 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3954 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3955 }
3956
3957 // Given a stall function and an unstall function, runs a test to make
3958 // sure that a stream resumes after unstall.
RunResumeAfterUnstallTest(const base::Callback<void (SpdySession *,SpdyStream *)> & stall_function,const base::Callback<void (SpdySession *,SpdyStream *,int32)> & unstall_function)3959 void SpdySessionTest::RunResumeAfterUnstallTest(
3960 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
3961 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
3962 unstall_function) {
3963 const char kStreamUrl[] = "http://www.google.com/";
3964 GURL url(kStreamUrl);
3965
3966 session_deps_.host_resolver->set_synchronous_mode(true);
3967
3968 scoped_ptr<SpdyFrame> req(
3969 spdy_util_.ConstructSpdyPost(
3970 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3971 scoped_ptr<SpdyFrame> body(
3972 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3973 MockWrite writes[] = {
3974 CreateMockWrite(*req, 0),
3975 CreateMockWrite(*body, 1),
3976 };
3977
3978 scoped_ptr<SpdyFrame> resp(
3979 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3980 scoped_ptr<SpdyFrame> echo(
3981 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
3982 MockRead reads[] = {
3983 CreateMockRead(*resp, 2),
3984 MockRead(ASYNC, 0, 0, 3), // EOF
3985 };
3986
3987 DeterministicSocketData data(reads, arraysize(reads),
3988 writes, arraysize(writes));
3989 MockConnect connect_data(SYNCHRONOUS, OK);
3990 data.set_connect_data(connect_data);
3991
3992 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3993
3994 CreateDeterministicNetworkSession();
3995 base::WeakPtr<SpdySession> session =
3996 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3997 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3998 session->flow_control_state());
3999
4000 base::WeakPtr<SpdyStream> stream =
4001 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4002 session, url, LOWEST, BoundNetLog());
4003 ASSERT_TRUE(stream.get() != NULL);
4004
4005 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
4006 stream->SetDelegate(&delegate);
4007
4008 EXPECT_FALSE(stream->HasUrlFromHeaders());
4009 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4010
4011 scoped_ptr<SpdyHeaderBlock> headers(
4012 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4013 EXPECT_EQ(ERR_IO_PENDING,
4014 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4015 EXPECT_TRUE(stream->HasUrlFromHeaders());
4016 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
4017
4018 stall_function.Run(session.get(), stream.get());
4019
4020 data.RunFor(1);
4021
4022 EXPECT_TRUE(stream->send_stalled_by_flow_control());
4023
4024 unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
4025
4026 EXPECT_FALSE(stream->send_stalled_by_flow_control());
4027
4028 data.RunFor(3);
4029
4030 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
4031
4032 EXPECT_TRUE(delegate.send_headers_completed());
4033 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
4034 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
4035 EXPECT_TRUE(data.at_write_eof());
4036 }
4037
4038 // Run the resume-after-unstall test with all possible stall and
4039 // unstall sequences.
4040
TEST_P(SpdySessionTest,ResumeAfterUnstallSession)4041 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
4042 if (GetParam() < kProtoSPDY31)
4043 return;
4044
4045 RunResumeAfterUnstallTest(
4046 base::Bind(&SpdySessionTest::StallSessionOnly,
4047 base::Unretained(this)),
4048 base::Bind(&SpdySessionTest::UnstallSessionOnly,
4049 base::Unretained(this)));
4050 }
4051
4052 // Equivalent to
4053 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
TEST_P(SpdySessionTest,ResumeAfterUnstallStream)4054 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
4055 if (GetParam() < kProtoSPDY31)
4056 return;
4057
4058 RunResumeAfterUnstallTest(
4059 base::Bind(&SpdySessionTest::StallStreamOnly,
4060 base::Unretained(this)),
4061 base::Bind(&SpdySessionTest::UnstallStreamOnly,
4062 base::Unretained(this)));
4063 }
4064
TEST_P(SpdySessionTest,StallSessionStreamResumeAfterUnstallSessionStream)4065 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4066 if (GetParam() < kProtoSPDY31)
4067 return;
4068
4069 RunResumeAfterUnstallTest(
4070 base::Bind(&SpdySessionTest::StallSessionStream,
4071 base::Unretained(this)),
4072 base::Bind(&SpdySessionTest::UnstallSessionStream,
4073 base::Unretained(this)));
4074 }
4075
TEST_P(SpdySessionTest,StallStreamSessionResumeAfterUnstallSessionStream)4076 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4077 if (GetParam() < kProtoSPDY31)
4078 return;
4079
4080 RunResumeAfterUnstallTest(
4081 base::Bind(&SpdySessionTest::StallStreamSession,
4082 base::Unretained(this)),
4083 base::Bind(&SpdySessionTest::UnstallSessionStream,
4084 base::Unretained(this)));
4085 }
4086
TEST_P(SpdySessionTest,StallStreamSessionResumeAfterUnstallStreamSession)4087 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4088 if (GetParam() < kProtoSPDY31)
4089 return;
4090
4091 RunResumeAfterUnstallTest(
4092 base::Bind(&SpdySessionTest::StallStreamSession,
4093 base::Unretained(this)),
4094 base::Bind(&SpdySessionTest::UnstallStreamSession,
4095 base::Unretained(this)));
4096 }
4097
TEST_P(SpdySessionTest,StallSessionStreamResumeAfterUnstallStreamSession)4098 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4099 if (GetParam() < kProtoSPDY31)
4100 return;
4101
4102 RunResumeAfterUnstallTest(
4103 base::Bind(&SpdySessionTest::StallSessionStream,
4104 base::Unretained(this)),
4105 base::Bind(&SpdySessionTest::UnstallStreamSession,
4106 base::Unretained(this)));
4107 }
4108
4109 // Cause a stall by reducing the flow control send window to 0. The
4110 // streams should resume in priority order when that window is then
4111 // increased.
TEST_P(SpdySessionTest,ResumeByPriorityAfterSendWindowSizeIncrease)4112 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4113 if (GetParam() < kProtoSPDY31)
4114 return;
4115
4116 const char kStreamUrl[] = "http://www.google.com/";
4117 GURL url(kStreamUrl);
4118
4119 session_deps_.host_resolver->set_synchronous_mode(true);
4120
4121 scoped_ptr<SpdyFrame> req1(
4122 spdy_util_.ConstructSpdyPost(
4123 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4124 scoped_ptr<SpdyFrame> req2(
4125 spdy_util_.ConstructSpdyPost(
4126 kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
4127 scoped_ptr<SpdyFrame> body1(
4128 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4129 scoped_ptr<SpdyFrame> body2(
4130 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4131 MockWrite writes[] = {
4132 CreateMockWrite(*req1, 0),
4133 CreateMockWrite(*req2, 1),
4134 CreateMockWrite(*body2, 2),
4135 CreateMockWrite(*body1, 3),
4136 };
4137
4138 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4139 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4140 MockRead reads[] = {
4141 CreateMockRead(*resp1, 4),
4142 CreateMockRead(*resp2, 5),
4143 MockRead(ASYNC, 0, 0, 6), // EOF
4144 };
4145
4146 DeterministicSocketData data(reads, arraysize(reads),
4147 writes, arraysize(writes));
4148 MockConnect connect_data(SYNCHRONOUS, OK);
4149 data.set_connect_data(connect_data);
4150
4151 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4152
4153 CreateDeterministicNetworkSession();
4154 base::WeakPtr<SpdySession> session =
4155 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4156 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4157 session->flow_control_state());
4158
4159 base::WeakPtr<SpdyStream> stream1 =
4160 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4161 session, url, LOWEST, BoundNetLog());
4162 ASSERT_TRUE(stream1.get() != NULL);
4163
4164 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4165 stream1->SetDelegate(&delegate1);
4166
4167 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4168
4169 base::WeakPtr<SpdyStream> stream2 =
4170 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4171 session, url, MEDIUM, BoundNetLog());
4172 ASSERT_TRUE(stream2.get() != NULL);
4173
4174 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4175 stream2->SetDelegate(&delegate2);
4176
4177 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4178
4179 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4180 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4181
4182 StallSessionSend(session.get());
4183
4184 scoped_ptr<SpdyHeaderBlock> headers1(
4185 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4186 EXPECT_EQ(ERR_IO_PENDING,
4187 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4188 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4189 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4190
4191 data.RunFor(1);
4192 EXPECT_EQ(1u, stream1->stream_id());
4193 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4194
4195 scoped_ptr<SpdyHeaderBlock> headers2(
4196 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4197 EXPECT_EQ(ERR_IO_PENDING,
4198 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4199 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4200 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4201
4202 data.RunFor(1);
4203 EXPECT_EQ(3u, stream2->stream_id());
4204 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4205
4206 // This should unstall only stream2.
4207 UnstallSessionSend(session.get(), kBodyDataSize);
4208
4209 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4210 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4211
4212 data.RunFor(1);
4213
4214 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4215 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4216
4217 // This should then unstall stream1.
4218 UnstallSessionSend(session.get(), kBodyDataSize);
4219
4220 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4221 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4222
4223 data.RunFor(4);
4224
4225 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4226 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4227
4228 EXPECT_TRUE(delegate1.send_headers_completed());
4229 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4230 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4231
4232 EXPECT_TRUE(delegate2.send_headers_completed());
4233 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4234 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4235
4236 EXPECT_TRUE(data.at_write_eof());
4237 }
4238
4239 // Delegate that closes a given stream after sending its body.
4240 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4241 public:
StreamClosingDelegate(const base::WeakPtr<SpdyStream> & stream,base::StringPiece data)4242 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4243 base::StringPiece data)
4244 : StreamDelegateWithBody(stream, data) {}
4245
~StreamClosingDelegate()4246 virtual ~StreamClosingDelegate() {}
4247
set_stream_to_close(const base::WeakPtr<SpdyStream> & stream_to_close)4248 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4249 stream_to_close_ = stream_to_close;
4250 }
4251
OnDataSent()4252 virtual void OnDataSent() OVERRIDE {
4253 test::StreamDelegateWithBody::OnDataSent();
4254 if (stream_to_close_.get()) {
4255 stream_to_close_->Close();
4256 EXPECT_EQ(NULL, stream_to_close_.get());
4257 }
4258 }
4259
4260 private:
4261 base::WeakPtr<SpdyStream> stream_to_close_;
4262 };
4263
4264 // Cause a stall by reducing the flow control send window to
4265 // 0. Unstalling the session should properly handle deleted streams.
TEST_P(SpdySessionTest,SendWindowSizeIncreaseWithDeletedStreams)4266 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4267 if (GetParam() < kProtoSPDY31)
4268 return;
4269
4270 const char kStreamUrl[] = "http://www.google.com/";
4271 GURL url(kStreamUrl);
4272
4273 session_deps_.host_resolver->set_synchronous_mode(true);
4274
4275 scoped_ptr<SpdyFrame> req1(
4276 spdy_util_.ConstructSpdyPost(
4277 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4278 scoped_ptr<SpdyFrame> req2(
4279 spdy_util_.ConstructSpdyPost(
4280 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4281 scoped_ptr<SpdyFrame> req3(
4282 spdy_util_.ConstructSpdyPost(
4283 kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
4284 scoped_ptr<SpdyFrame> body2(
4285 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4286 MockWrite writes[] = {
4287 CreateMockWrite(*req1, 0),
4288 CreateMockWrite(*req2, 1),
4289 CreateMockWrite(*req3, 2),
4290 CreateMockWrite(*body2, 3),
4291 };
4292
4293 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4294 MockRead reads[] = {
4295 CreateMockRead(*resp2, 4),
4296 MockRead(ASYNC, 0, 0, 5), // EOF
4297 };
4298
4299 DeterministicSocketData data(reads, arraysize(reads),
4300 writes, arraysize(writes));
4301 MockConnect connect_data(SYNCHRONOUS, OK);
4302 data.set_connect_data(connect_data);
4303
4304 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4305
4306 CreateDeterministicNetworkSession();
4307 base::WeakPtr<SpdySession> session =
4308 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4309 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4310 session->flow_control_state());
4311
4312 base::WeakPtr<SpdyStream> stream1 =
4313 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4314 session, url, LOWEST, BoundNetLog());
4315 ASSERT_TRUE(stream1.get() != NULL);
4316
4317 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4318 stream1->SetDelegate(&delegate1);
4319
4320 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4321
4322 base::WeakPtr<SpdyStream> stream2 =
4323 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4324 session, url, LOWEST, BoundNetLog());
4325 ASSERT_TRUE(stream2.get() != NULL);
4326
4327 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4328 stream2->SetDelegate(&delegate2);
4329
4330 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4331
4332 base::WeakPtr<SpdyStream> stream3 =
4333 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4334 session, url, LOWEST, BoundNetLog());
4335 ASSERT_TRUE(stream3.get() != NULL);
4336
4337 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4338 stream3->SetDelegate(&delegate3);
4339
4340 EXPECT_FALSE(stream3->HasUrlFromHeaders());
4341
4342 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4343 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4344 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4345
4346 StallSessionSend(session.get());
4347
4348 scoped_ptr<SpdyHeaderBlock> headers1(
4349 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4350 EXPECT_EQ(ERR_IO_PENDING,
4351 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4352 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4353 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4354
4355 data.RunFor(1);
4356 EXPECT_EQ(1u, stream1->stream_id());
4357 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4358
4359 scoped_ptr<SpdyHeaderBlock> headers2(
4360 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4361 EXPECT_EQ(ERR_IO_PENDING,
4362 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4363 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4364 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4365
4366 data.RunFor(1);
4367 EXPECT_EQ(3u, stream2->stream_id());
4368 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4369
4370 scoped_ptr<SpdyHeaderBlock> headers3(
4371 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4372 EXPECT_EQ(ERR_IO_PENDING,
4373 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4374 EXPECT_TRUE(stream3->HasUrlFromHeaders());
4375 EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4376
4377 data.RunFor(1);
4378 EXPECT_EQ(5u, stream3->stream_id());
4379 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4380
4381 SpdyStreamId stream_id1 = stream1->stream_id();
4382 SpdyStreamId stream_id2 = stream2->stream_id();
4383 SpdyStreamId stream_id3 = stream3->stream_id();
4384
4385 // Close stream1 preemptively.
4386 session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4387 EXPECT_EQ(NULL, stream1.get());
4388
4389 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4390 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4391 EXPECT_TRUE(session->IsStreamActive(stream_id3));
4392
4393 // Unstall stream2, which should then close stream3.
4394 delegate2.set_stream_to_close(stream3);
4395 UnstallSessionSend(session.get(), kBodyDataSize);
4396
4397 data.RunFor(1);
4398 EXPECT_EQ(NULL, stream3.get());
4399
4400 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4401 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4402 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4403 EXPECT_FALSE(session->IsStreamActive(stream_id3));
4404
4405 data.RunFor(2);
4406 EXPECT_EQ(NULL, stream2.get());
4407
4408 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4409 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4410 EXPECT_EQ(OK, delegate3.WaitForClose());
4411
4412 EXPECT_TRUE(delegate1.send_headers_completed());
4413 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4414
4415 EXPECT_TRUE(delegate2.send_headers_completed());
4416 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4417 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4418
4419 EXPECT_TRUE(delegate3.send_headers_completed());
4420 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4421
4422 EXPECT_TRUE(data.at_write_eof());
4423 }
4424
4425 // Cause a stall by reducing the flow control send window to
4426 // 0. Unstalling the session should properly handle the session itself
4427 // being closed.
TEST_P(SpdySessionTest,SendWindowSizeIncreaseWithDeletedSession)4428 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4429 if (GetParam() < kProtoSPDY31)
4430 return;
4431
4432 const char kStreamUrl[] = "http://www.google.com/";
4433 GURL url(kStreamUrl);
4434
4435 session_deps_.host_resolver->set_synchronous_mode(true);
4436
4437 scoped_ptr<SpdyFrame> req1(
4438 spdy_util_.ConstructSpdyPost(
4439 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4440 scoped_ptr<SpdyFrame> req2(
4441 spdy_util_.ConstructSpdyPost(
4442 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4443 scoped_ptr<SpdyFrame> body1(
4444 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4445 MockWrite writes[] = {
4446 CreateMockWrite(*req1, 0),
4447 CreateMockWrite(*req2, 1),
4448 };
4449
4450 MockRead reads[] = {
4451 MockRead(ASYNC, 0, 0, 2), // EOF
4452 };
4453
4454 DeterministicSocketData data(reads, arraysize(reads),
4455 writes, arraysize(writes));
4456 MockConnect connect_data(SYNCHRONOUS, OK);
4457 data.set_connect_data(connect_data);
4458
4459 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4460
4461 CreateDeterministicNetworkSession();
4462 base::WeakPtr<SpdySession> session =
4463 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4464 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4465 session->flow_control_state());
4466
4467 base::WeakPtr<SpdyStream> stream1 =
4468 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4469 session, url, LOWEST, BoundNetLog());
4470 ASSERT_TRUE(stream1.get() != NULL);
4471
4472 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4473 stream1->SetDelegate(&delegate1);
4474
4475 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4476
4477 base::WeakPtr<SpdyStream> stream2 =
4478 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4479 session, url, LOWEST, BoundNetLog());
4480 ASSERT_TRUE(stream2.get() != NULL);
4481
4482 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4483 stream2->SetDelegate(&delegate2);
4484
4485 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4486
4487 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4488 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4489
4490 StallSessionSend(session.get());
4491
4492 scoped_ptr<SpdyHeaderBlock> headers1(
4493 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4494 EXPECT_EQ(ERR_IO_PENDING,
4495 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4496 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4497 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4498
4499 data.RunFor(1);
4500 EXPECT_EQ(1u, stream1->stream_id());
4501 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4502
4503 scoped_ptr<SpdyHeaderBlock> headers2(
4504 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4505 EXPECT_EQ(ERR_IO_PENDING,
4506 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4507 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4508 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4509
4510 data.RunFor(1);
4511 EXPECT_EQ(3u, stream2->stream_id());
4512 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4513
4514 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4515
4516 // Unstall stream1.
4517 UnstallSessionSend(session.get(), kBodyDataSize);
4518
4519 // Close the session (since we can't do it from within the delegate
4520 // method, since it's in the stream's loop).
4521 session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4522 base::RunLoop().RunUntilIdle();
4523 EXPECT_TRUE(session == NULL);
4524
4525 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4526
4527 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4528 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4529
4530 EXPECT_TRUE(delegate1.send_headers_completed());
4531 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4532
4533 EXPECT_TRUE(delegate2.send_headers_completed());
4534 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4535
4536 EXPECT_TRUE(data.at_write_eof());
4537 }
4538
TEST_P(SpdySessionTest,GoAwayOnSessionFlowControlError)4539 TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4540 if (GetParam() < kProtoSPDY31)
4541 return;
4542
4543 MockConnect connect_data(SYNCHRONOUS, OK);
4544
4545 scoped_ptr<SpdyFrame> req(
4546 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4547 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4548 0,
4549 GOAWAY_FLOW_CONTROL_ERROR,
4550 "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4551 "the receive window size of 1"));
4552 MockWrite writes[] = {
4553 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
4554 };
4555
4556 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4557 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4558 MockRead reads[] = {
4559 CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
4560 };
4561
4562 DeterministicSocketData data(
4563 reads, arraysize(reads), writes, arraysize(writes));
4564 data.set_connect_data(connect_data);
4565 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4566
4567 CreateDeterministicNetworkSession();
4568
4569 base::WeakPtr<SpdySession> session =
4570 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4571
4572 GURL url(kDefaultURL);
4573 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4574 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
4575 ASSERT_TRUE(spdy_stream.get() != NULL);
4576 test::StreamDelegateDoNothing delegate(spdy_stream);
4577 spdy_stream->SetDelegate(&delegate);
4578
4579 scoped_ptr<SpdyHeaderBlock> headers(
4580 spdy_util_.ConstructGetHeaderBlock(url.spec()));
4581 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4582
4583 data.RunFor(1); // Write request.
4584
4585 // Put session on the edge of overflowing it's recv window.
4586 session->session_recv_window_size_ = 1;
4587
4588 // Read response headers & body. Body overflows the session window, and a
4589 // goaway is written.
4590 data.RunFor(3);
4591 base::MessageLoop::current()->RunUntilIdle();
4592
4593 EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4594 EXPECT_TRUE(session == NULL);
4595 }
4596
TEST_P(SpdySessionTest,SplitHeaders)4597 TEST_P(SpdySessionTest, SplitHeaders) {
4598 GURL kStreamUrl("http://www.google.com/foo.dat");
4599 SpdyHeaderBlock headers;
4600 spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4601 headers["alpha"] = "beta";
4602
4603 SpdyHeaderBlock request_headers;
4604 SpdyHeaderBlock response_headers;
4605
4606 SplitPushedHeadersToRequestAndResponse(
4607 headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4608
4609 SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4610 std::string alpha_val =
4611 (it == response_headers.end()) ? std::string() : it->second;
4612 EXPECT_EQ("beta", alpha_val);
4613
4614 GURL request_url =
4615 GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4616 EXPECT_EQ(kStreamUrl, request_url);
4617 }
4618
4619 // Regression. Sorta. Push streams and client streams were sharing a single
4620 // limit for a long time.
TEST_P(SpdySessionTest,PushedStreamShouldNotCountToClientConcurrencyLimit)4621 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4622 SettingsMap new_settings;
4623 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4624 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4625 scoped_ptr<SpdyFrame> settings_frame(
4626 spdy_util_.ConstructSpdySettings(new_settings));
4627 scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4628 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4629 MockRead reads[] = {
4630 CreateMockRead(*settings_frame), CreateMockRead(*pushed, 3),
4631 MockRead(ASYNC, 0, 4),
4632 };
4633
4634 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4635 scoped_ptr<SpdyFrame> req(
4636 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4637 MockWrite writes[] = {
4638 CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4639 };
4640
4641 DeterministicSocketData data(
4642 reads, arraysize(reads), writes, arraysize(writes));
4643 MockConnect connect_data(SYNCHRONOUS, OK);
4644 data.set_connect_data(connect_data);
4645 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4646
4647 CreateDeterministicNetworkSession();
4648
4649 base::WeakPtr<SpdySession> session =
4650 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4651
4652 // Read the settings frame.
4653 data.RunFor(1);
4654
4655 GURL url1(kDefaultURL);
4656 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4657 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4658 ASSERT_TRUE(spdy_stream1.get() != NULL);
4659 EXPECT_EQ(0u, spdy_stream1->stream_id());
4660 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4661 spdy_stream1->SetDelegate(&delegate1);
4662
4663 EXPECT_EQ(0u, session->num_active_streams());
4664 EXPECT_EQ(1u, session->num_created_streams());
4665 EXPECT_EQ(0u, session->num_pushed_streams());
4666 EXPECT_EQ(0u, session->num_active_pushed_streams());
4667
4668 scoped_ptr<SpdyHeaderBlock> headers(
4669 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4670 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4671 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4672
4673 // Run until 1st stream is activated.
4674 EXPECT_EQ(0u, delegate1.stream_id());
4675 data.RunFor(2);
4676 EXPECT_EQ(1u, delegate1.stream_id());
4677 EXPECT_EQ(1u, session->num_active_streams());
4678 EXPECT_EQ(0u, session->num_created_streams());
4679 EXPECT_EQ(0u, session->num_pushed_streams());
4680 EXPECT_EQ(0u, session->num_active_pushed_streams());
4681
4682 // Run until pushed stream is created.
4683 data.RunFor(1);
4684 EXPECT_EQ(2u, session->num_active_streams());
4685 EXPECT_EQ(0u, session->num_created_streams());
4686 EXPECT_EQ(1u, session->num_pushed_streams());
4687 EXPECT_EQ(1u, session->num_active_pushed_streams());
4688
4689 // Second stream should not be stalled, although we have 2 active streams, but
4690 // one of them is push stream and should not be taken into account when we
4691 // create streams on the client.
4692 base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4693 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4694 EXPECT_TRUE(spdy_stream2.get() != NULL);
4695 EXPECT_EQ(2u, session->num_active_streams());
4696 EXPECT_EQ(1u, session->num_created_streams());
4697 EXPECT_EQ(1u, session->num_pushed_streams());
4698 EXPECT_EQ(1u, session->num_active_pushed_streams());
4699
4700 // Read EOF.
4701 data.RunFor(1);
4702 }
4703
TEST_P(SpdySessionTest,RejectPushedStreamExceedingConcurrencyLimit)4704 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4705 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4706 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4707 scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4708 NULL, 0, 4, 1, "http://www.google.com/b.dat"));
4709 MockRead reads[] = {
4710 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4711 MockRead(ASYNC, 0, 4),
4712 };
4713
4714 scoped_ptr<SpdyFrame> req(
4715 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4716 scoped_ptr<SpdyFrame> rst(
4717 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4718 MockWrite writes[] = {
4719 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4720 };
4721
4722 DeterministicSocketData data(
4723 reads, arraysize(reads), writes, arraysize(writes));
4724 MockConnect connect_data(SYNCHRONOUS, OK);
4725 data.set_connect_data(connect_data);
4726 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4727
4728 CreateDeterministicNetworkSession();
4729
4730 base::WeakPtr<SpdySession> session =
4731 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4732 session->set_max_concurrent_pushed_streams(1);
4733
4734 GURL url1(kDefaultURL);
4735 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4736 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4737 ASSERT_TRUE(spdy_stream1.get() != NULL);
4738 EXPECT_EQ(0u, spdy_stream1->stream_id());
4739 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4740 spdy_stream1->SetDelegate(&delegate1);
4741
4742 EXPECT_EQ(0u, session->num_active_streams());
4743 EXPECT_EQ(1u, session->num_created_streams());
4744 EXPECT_EQ(0u, session->num_pushed_streams());
4745 EXPECT_EQ(0u, session->num_active_pushed_streams());
4746
4747 scoped_ptr<SpdyHeaderBlock> headers(
4748 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4749 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4750 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4751
4752 // Run until 1st stream is activated.
4753 EXPECT_EQ(0u, delegate1.stream_id());
4754 data.RunFor(1);
4755 EXPECT_EQ(1u, delegate1.stream_id());
4756 EXPECT_EQ(1u, session->num_active_streams());
4757 EXPECT_EQ(0u, session->num_created_streams());
4758 EXPECT_EQ(0u, session->num_pushed_streams());
4759 EXPECT_EQ(0u, session->num_active_pushed_streams());
4760
4761 // Run until pushed stream is created.
4762 data.RunFor(1);
4763 EXPECT_EQ(2u, session->num_active_streams());
4764 EXPECT_EQ(0u, session->num_created_streams());
4765 EXPECT_EQ(1u, session->num_pushed_streams());
4766 EXPECT_EQ(1u, session->num_active_pushed_streams());
4767
4768 // Reset incoming pushed stream.
4769 data.RunFor(2);
4770 EXPECT_EQ(2u, session->num_active_streams());
4771 EXPECT_EQ(0u, session->num_created_streams());
4772 EXPECT_EQ(1u, session->num_pushed_streams());
4773 EXPECT_EQ(1u, session->num_active_pushed_streams());
4774
4775 // Read EOF.
4776 data.RunFor(1);
4777 }
4778
TEST_P(SpdySessionTest,IgnoreReservedRemoteStreamsCount)4779 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4780 // Streams in reserved remote state exist only in SPDY4.
4781 if (spdy_util_.spdy_version() < SPDY4)
4782 return;
4783
4784 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4785 NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4786 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4787 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
4788 push_headers.get());
4789 scoped_ptr<SpdyFrame> push_b(
4790 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4791 scoped_ptr<SpdyFrame> headers_b(
4792 spdy_util_.ConstructSpdyPushHeaders(4, NULL, 0));
4793 MockRead reads[] = {
4794 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4795 CreateMockRead(*headers_b, 3), MockRead(ASYNC, 0, 5),
4796 };
4797
4798 scoped_ptr<SpdyFrame> req(
4799 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4800 scoped_ptr<SpdyFrame> rst(
4801 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4802 MockWrite writes[] = {
4803 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
4804 };
4805
4806 DeterministicSocketData data(
4807 reads, arraysize(reads), writes, arraysize(writes));
4808 MockConnect connect_data(SYNCHRONOUS, OK);
4809 data.set_connect_data(connect_data);
4810 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4811
4812 CreateDeterministicNetworkSession();
4813
4814 base::WeakPtr<SpdySession> session =
4815 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4816 session->set_max_concurrent_pushed_streams(1);
4817
4818 GURL url1(kDefaultURL);
4819 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4820 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4821 ASSERT_TRUE(spdy_stream1.get() != NULL);
4822 EXPECT_EQ(0u, spdy_stream1->stream_id());
4823 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4824 spdy_stream1->SetDelegate(&delegate1);
4825
4826 EXPECT_EQ(0u, session->num_active_streams());
4827 EXPECT_EQ(1u, session->num_created_streams());
4828 EXPECT_EQ(0u, session->num_pushed_streams());
4829 EXPECT_EQ(0u, session->num_active_pushed_streams());
4830
4831 scoped_ptr<SpdyHeaderBlock> headers(
4832 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4833 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4834 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4835
4836 // Run until 1st stream is activated.
4837 EXPECT_EQ(0u, delegate1.stream_id());
4838 data.RunFor(1);
4839 EXPECT_EQ(1u, delegate1.stream_id());
4840 EXPECT_EQ(1u, session->num_active_streams());
4841 EXPECT_EQ(0u, session->num_created_streams());
4842 EXPECT_EQ(0u, session->num_pushed_streams());
4843 EXPECT_EQ(0u, session->num_active_pushed_streams());
4844
4845 // Run until pushed stream is created.
4846 data.RunFor(1);
4847 EXPECT_EQ(2u, session->num_active_streams());
4848 EXPECT_EQ(0u, session->num_created_streams());
4849 EXPECT_EQ(1u, session->num_pushed_streams());
4850 EXPECT_EQ(1u, session->num_active_pushed_streams());
4851
4852 // Accept promised stream. It should not count towards pushed stream limit.
4853 data.RunFor(1);
4854 EXPECT_EQ(3u, session->num_active_streams());
4855 EXPECT_EQ(0u, session->num_created_streams());
4856 EXPECT_EQ(2u, session->num_pushed_streams());
4857 EXPECT_EQ(1u, session->num_active_pushed_streams());
4858
4859 // Reset last pushed stream upon headers reception as it is going to be 2nd,
4860 // while we accept only one.
4861 data.RunFor(2);
4862 EXPECT_EQ(2u, session->num_active_streams());
4863 EXPECT_EQ(0u, session->num_created_streams());
4864 EXPECT_EQ(1u, session->num_pushed_streams());
4865 EXPECT_EQ(1u, session->num_active_pushed_streams());
4866
4867 // Read EOF.
4868 data.RunFor(1);
4869 }
4870
TEST_P(SpdySessionTest,CancelReservedStreamOnHeadersReceived)4871 TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
4872 // Streams in reserved remote state exist only in SPDY4.
4873 if (spdy_util_.spdy_version() < SPDY4)
4874 return;
4875
4876 const char kPushedUrl[] = "http://www.google.com/a.dat";
4877 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4878 spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
4879 scoped_ptr<SpdyFrame> push_promise(
4880 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
4881 scoped_ptr<SpdyFrame> headers_frame(
4882 spdy_util_.ConstructSpdyPushHeaders(2, NULL, 0));
4883 MockRead reads[] = {
4884 CreateMockRead(*push_promise, 1), CreateMockRead(*headers_frame, 2),
4885 MockRead(ASYNC, 0, 4),
4886 };
4887
4888 scoped_ptr<SpdyFrame> req(
4889 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4890 scoped_ptr<SpdyFrame> rst(
4891 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
4892 MockWrite writes[] = {
4893 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4894 };
4895
4896 DeterministicSocketData data(
4897 reads, arraysize(reads), writes, arraysize(writes));
4898 MockConnect connect_data(SYNCHRONOUS, OK);
4899 data.set_connect_data(connect_data);
4900 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4901
4902 CreateDeterministicNetworkSession();
4903
4904 base::WeakPtr<SpdySession> session =
4905 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4906
4907 GURL url1(kDefaultURL);
4908 base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4909 SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4910 ASSERT_TRUE(spdy_stream1.get() != NULL);
4911 EXPECT_EQ(0u, spdy_stream1->stream_id());
4912 test::StreamDelegateDoNothing delegate1(spdy_stream1);
4913 spdy_stream1->SetDelegate(&delegate1);
4914
4915 EXPECT_EQ(0u, session->num_active_streams());
4916 EXPECT_EQ(1u, session->num_created_streams());
4917 EXPECT_EQ(0u, session->num_pushed_streams());
4918 EXPECT_EQ(0u, session->num_active_pushed_streams());
4919
4920 scoped_ptr<SpdyHeaderBlock> headers(
4921 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4922 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4923 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4924
4925 // Run until 1st stream is activated.
4926 EXPECT_EQ(0u, delegate1.stream_id());
4927 data.RunFor(1);
4928 EXPECT_EQ(1u, delegate1.stream_id());
4929 EXPECT_EQ(1u, session->num_active_streams());
4930 EXPECT_EQ(0u, session->num_created_streams());
4931 EXPECT_EQ(0u, session->num_pushed_streams());
4932 EXPECT_EQ(0u, session->num_active_pushed_streams());
4933
4934 // Run until pushed stream is created.
4935 data.RunFor(1);
4936 EXPECT_EQ(2u, session->num_active_streams());
4937 EXPECT_EQ(0u, session->num_created_streams());
4938 EXPECT_EQ(1u, session->num_pushed_streams());
4939 EXPECT_EQ(0u, session->num_active_pushed_streams());
4940
4941 base::WeakPtr<SpdyStream> pushed_stream;
4942 int rv =
4943 session->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
4944 ASSERT_EQ(OK, rv);
4945 ASSERT_TRUE(pushed_stream.get() != NULL);
4946 test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
4947 pushed_stream->SetDelegate(&delegate2);
4948
4949 // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4950 // that all our counters are in consistent state.
4951 data.RunFor(1);
4952 EXPECT_EQ(1u, session->num_active_streams());
4953 EXPECT_EQ(0u, session->num_created_streams());
4954 EXPECT_EQ(0u, session->num_pushed_streams());
4955 EXPECT_EQ(0u, session->num_active_pushed_streams());
4956
4957 // Read EOF.
4958 data.RunFor(2);
4959 }
4960
TEST_P(SpdySessionTest,RejectInvalidUnknownFrames)4961 TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
4962 session_deps_.host_resolver->set_synchronous_mode(true);
4963
4964 MockRead reads[] = {
4965 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
4966 };
4967
4968 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
4969
4970 MockConnect connect_data(SYNCHRONOUS, OK);
4971 data.set_connect_data(connect_data);
4972 session_deps_.socket_factory->AddSocketDataProvider(&data);
4973
4974 CreateNetworkSession();
4975 base::WeakPtr<SpdySession> session =
4976 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4977
4978 session->stream_hi_water_mark_ = 5;
4979 // Low client (odd) ids are fine.
4980 EXPECT_TRUE(session->OnUnknownFrame(3, 0));
4981 // Client id exceeding watermark.
4982 EXPECT_FALSE(session->OnUnknownFrame(9, 0));
4983
4984 session->last_accepted_push_stream_id_ = 6;
4985 // Low server (even) ids are fine.
4986 EXPECT_TRUE(session->OnUnknownFrame(2, 0));
4987 // Server id exceeding last accepted id.
4988 EXPECT_FALSE(session->OnUnknownFrame(8, 0));
4989 }
4990
TEST(MapFramerErrorToProtocolError,MapsValues)4991 TEST(MapFramerErrorToProtocolError, MapsValues) {
4992 CHECK_EQ(
4993 SPDY_ERROR_INVALID_CONTROL_FRAME,
4994 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4995 CHECK_EQ(
4996 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4997 MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4998 CHECK_EQ(
4999 SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
5000 MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
5001 CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
5002 MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
5003 }
5004
TEST(MapFramerErrorToNetError,MapsValue)5005 TEST(MapFramerErrorToNetError, MapsValue) {
5006 CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
5007 MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
5008 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5009 MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
5010 CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5011 MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
5012 CHECK_EQ(
5013 ERR_SPDY_FRAME_SIZE_ERROR,
5014 MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
5015 }
5016
TEST(MapRstStreamStatusToProtocolError,MapsValues)5017 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
5018 CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
5019 MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
5020 CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
5021 MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
5022 CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
5023 MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
5024 }
5025
TEST(MapNetErrorToGoAwayStatus,MapsValue)5026 TEST(MapNetErrorToGoAwayStatus, MapsValue) {
5027 CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
5028 MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
5029 CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
5030 MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
5031 CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
5032 MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
5033 CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
5034 MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
5035 CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
5036 MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
5037 CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
5038 }
5039
TEST(CanPoolTest,CanPool)5040 TEST(CanPoolTest, CanPool) {
5041 // Load a cert that is valid for:
5042 // www.example.org
5043 // mail.example.org
5044 // www.example.com
5045
5046 TransportSecurityState tss;
5047 SSLInfo ssl_info;
5048 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5049 "spdy_pooling.pem");
5050
5051 EXPECT_TRUE(SpdySession::CanPool(
5052 &tss, ssl_info, "www.example.org", "www.example.org"));
5053 EXPECT_TRUE(SpdySession::CanPool(
5054 &tss, ssl_info, "www.example.org", "mail.example.org"));
5055 EXPECT_TRUE(SpdySession::CanPool(
5056 &tss, ssl_info, "www.example.org", "mail.example.com"));
5057 EXPECT_FALSE(SpdySession::CanPool(
5058 &tss, ssl_info, "www.example.org", "mail.google.com"));
5059 }
5060
TEST(CanPoolTest,CanNotPoolWithCertErrors)5061 TEST(CanPoolTest, CanNotPoolWithCertErrors) {
5062 // Load a cert that is valid for:
5063 // www.example.org
5064 // mail.example.org
5065 // www.example.com
5066
5067 TransportSecurityState tss;
5068 SSLInfo ssl_info;
5069 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5070 "spdy_pooling.pem");
5071 ssl_info.cert_status = CERT_STATUS_REVOKED;
5072
5073 EXPECT_FALSE(SpdySession::CanPool(
5074 &tss, ssl_info, "www.example.org", "mail.example.org"));
5075 }
5076
TEST(CanPoolTest,CanNotPoolWithClientCerts)5077 TEST(CanPoolTest, CanNotPoolWithClientCerts) {
5078 // Load a cert that is valid for:
5079 // www.example.org
5080 // mail.example.org
5081 // www.example.com
5082
5083 TransportSecurityState tss;
5084 SSLInfo ssl_info;
5085 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5086 "spdy_pooling.pem");
5087 ssl_info.client_cert_sent = true;
5088
5089 EXPECT_FALSE(SpdySession::CanPool(
5090 &tss, ssl_info, "www.example.org", "mail.example.org"));
5091 }
5092
TEST(CanPoolTest,CanNotPoolAcrossETLDsWithChannelID)5093 TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
5094 // Load a cert that is valid for:
5095 // www.example.org
5096 // mail.example.org
5097 // www.example.com
5098
5099 TransportSecurityState tss;
5100 SSLInfo ssl_info;
5101 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5102 "spdy_pooling.pem");
5103 ssl_info.channel_id_sent = true;
5104
5105 EXPECT_TRUE(SpdySession::CanPool(
5106 &tss, ssl_info, "www.example.org", "mail.example.org"));
5107 EXPECT_FALSE(SpdySession::CanPool(
5108 &tss, ssl_info, "www.example.org", "www.example.com"));
5109 }
5110
TEST(CanPoolTest,CanNotPoolWithBadPins)5111 TEST(CanPoolTest, CanNotPoolWithBadPins) {
5112 uint8 primary_pin = 1;
5113 uint8 backup_pin = 2;
5114 uint8 bad_pin = 3;
5115 TransportSecurityState tss;
5116 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5117
5118 SSLInfo ssl_info;
5119 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5120 "spdy_pooling.pem");
5121 ssl_info.is_issued_by_known_root = true;
5122 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
5123
5124 EXPECT_FALSE(SpdySession::CanPool(
5125 &tss, ssl_info, "www.example.org", "mail.example.org"));
5126 }
5127
TEST(CanPoolTest,CanPoolWithAcceptablePins)5128 TEST(CanPoolTest, CanPoolWithAcceptablePins) {
5129 uint8 primary_pin = 1;
5130 uint8 backup_pin = 2;
5131 TransportSecurityState tss;
5132 test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5133
5134 SSLInfo ssl_info;
5135 ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5136 "spdy_pooling.pem");
5137 ssl_info.is_issued_by_known_root = true;
5138 ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
5139
5140 EXPECT_TRUE(SpdySession::CanPool(
5141 &tss, ssl_info, "www.example.org", "mail.example.org"));
5142 }
5143
5144 } // namespace net
5145