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/bind.h"
8 #include "base/callback.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "net/base/io_buffer.h"
12 #include "net/base/ip_endpoint.h"
13 #include "net/base/net_log_unittest.h"
14 #include "net/base/request_priority.h"
15 #include "net/base/test_data_directory.h"
16 #include "net/base/test_data_stream.h"
17 #include "net/socket/client_socket_pool_manager.h"
18 #include "net/socket/next_proto.h"
19 #include "net/socket/socket_test_util.h"
20 #include "net/spdy/spdy_http_utils.h"
21 #include "net/spdy/spdy_session_pool.h"
22 #include "net/spdy/spdy_session_test_util.h"
23 #include "net/spdy/spdy_stream.h"
24 #include "net/spdy/spdy_stream_test_util.h"
25 #include "net/spdy/spdy_test_util_common.h"
26 #include "net/spdy/spdy_test_utils.h"
27 #include "net/test/cert_test_util.h"
28 #include "testing/platform_test.h"
29
30 namespace net {
31
32 namespace {
33
34 static const char kTestUrl[] = "http://www.example.org/";
35 static const char kTestHost[] = "www.example.org";
36 static const int kTestPort = 80;
37
38 const char kBodyData[] = "Body data";
39 const size_t kBodyDataSize = arraysize(kBodyData);
40 const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize);
41
42 static base::TimeDelta g_time_delta;
TheNearFuture()43 base::TimeTicks TheNearFuture() {
44 return base::TimeTicks::Now() + g_time_delta;
45 }
46
47 } // namespace
48
49 class SpdySessionTest : public PlatformTest,
50 public ::testing::WithParamInterface<NextProto> {
51 public:
52 // Functions used with RunResumeAfterUnstallTest().
53
StallSessionOnly(SpdySession * session,SpdyStream * stream)54 void StallSessionOnly(SpdySession* session, SpdyStream* stream) {
55 StallSessionSend(session);
56 }
57
StallStreamOnly(SpdySession * session,SpdyStream * stream)58 void StallStreamOnly(SpdySession* session, SpdyStream* stream) {
59 StallStreamSend(stream);
60 }
61
StallSessionStream(SpdySession * session,SpdyStream * stream)62 void StallSessionStream(SpdySession* session, SpdyStream* stream) {
63 StallSessionSend(session);
64 StallStreamSend(stream);
65 }
66
StallStreamSession(SpdySession * session,SpdyStream * stream)67 void StallStreamSession(SpdySession* session, SpdyStream* stream) {
68 StallStreamSend(stream);
69 StallSessionSend(session);
70 }
71
UnstallSessionOnly(SpdySession * session,SpdyStream * stream,int32 delta_window_size)72 void UnstallSessionOnly(SpdySession* session,
73 SpdyStream* stream,
74 int32 delta_window_size) {
75 UnstallSessionSend(session, delta_window_size);
76 }
77
UnstallStreamOnly(SpdySession * session,SpdyStream * stream,int32 delta_window_size)78 void UnstallStreamOnly(SpdySession* session,
79 SpdyStream* stream,
80 int32 delta_window_size) {
81 UnstallStreamSend(stream, delta_window_size);
82 }
83
UnstallSessionStream(SpdySession * session,SpdyStream * stream,int32 delta_window_size)84 void UnstallSessionStream(SpdySession* session,
85 SpdyStream* stream,
86 int32 delta_window_size) {
87 UnstallSessionSend(session, delta_window_size);
88 UnstallStreamSend(stream, delta_window_size);
89 }
90
UnstallStreamSession(SpdySession * session,SpdyStream * stream,int32 delta_window_size)91 void UnstallStreamSession(SpdySession* session,
92 SpdyStream* stream,
93 int32 delta_window_size) {
94 UnstallStreamSend(stream, delta_window_size);
95 UnstallSessionSend(session, delta_window_size);
96 }
97
98 protected:
SpdySessionTest()99 SpdySessionTest()
100 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
101 HttpNetworkSession::NORMAL_SOCKET_POOL)),
102 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
103 HttpNetworkSession::NORMAL_SOCKET_POOL)),
104 spdy_util_(GetParam()),
105 session_deps_(GetParam()),
106 spdy_session_pool_(NULL),
107 test_url_(kTestUrl),
108 test_host_port_pair_(kTestHost, kTestPort),
109 key_(test_host_port_pair_, ProxyServer::Direct(),
110 kPrivacyModeDisabled) {
111 }
112
~SpdySessionTest()113 virtual ~SpdySessionTest() {
114 // Important to restore the per-pool limit first, since the pool limit must
115 // always be greater than group limit, and the tests reduce both limits.
116 ClientSocketPoolManager::set_max_sockets_per_pool(
117 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
118 ClientSocketPoolManager::set_max_sockets_per_group(
119 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
120 }
121
SetUp()122 virtual void SetUp() OVERRIDE {
123 g_time_delta = base::TimeDelta();
124 }
125
CreateDeterministicNetworkSession()126 void CreateDeterministicNetworkSession() {
127 http_session_ =
128 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
129 spdy_session_pool_ = http_session_->spdy_session_pool();
130 }
131
CreateNetworkSession()132 void CreateNetworkSession() {
133 http_session_ =
134 SpdySessionDependencies::SpdyCreateSession(&session_deps_);
135 spdy_session_pool_ = http_session_->spdy_session_pool();
136 }
137
StallSessionSend(SpdySession * session)138 void StallSessionSend(SpdySession* session) {
139 // Reduce the send window size to 0 to stall.
140 while (session->session_send_window_size_ > 0) {
141 session->DecreaseSendWindowSize(
142 std::min(kMaxSpdyFrameChunkSize, session->session_send_window_size_));
143 }
144 }
145
UnstallSessionSend(SpdySession * session,int32 delta_window_size)146 void UnstallSessionSend(SpdySession* session, int32 delta_window_size) {
147 session->IncreaseSendWindowSize(delta_window_size);
148 }
149
StallStreamSend(SpdyStream * stream)150 void StallStreamSend(SpdyStream* stream) {
151 // Reduce the send window size to 0 to stall.
152 while (stream->send_window_size() > 0) {
153 stream->DecreaseSendWindowSize(
154 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
155 }
156 }
157
UnstallStreamSend(SpdyStream * stream,int32 delta_window_size)158 void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) {
159 stream->IncreaseSendWindowSize(delta_window_size);
160 }
161
162 void RunResumeAfterUnstallTest(
163 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
164 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
165 unstall_function);
166
167 // Original socket limits. Some tests set these. Safest to always restore
168 // them once each test has been run.
169 int old_max_group_sockets_;
170 int old_max_pool_sockets_;
171
172 SpdyTestUtil spdy_util_;
173 SpdySessionDependencies session_deps_;
174 scoped_refptr<HttpNetworkSession> http_session_;
175 SpdySessionPool* spdy_session_pool_;
176 GURL test_url_;
177 HostPortPair test_host_port_pair_;
178 SpdySessionKey key_;
179 };
180
181 INSTANTIATE_TEST_CASE_P(
182 NextProto,
183 SpdySessionTest,
184 testing::Values(kProtoDeprecatedSPDY2,
185 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
186 kProtoHTTP2Draft04));
187
188 // Try to create a SPDY session that will fail during
189 // initialization. Nothing should blow up.
TEST_P(SpdySessionTest,InitialReadError)190 TEST_P(SpdySessionTest, InitialReadError) {
191 CreateDeterministicNetworkSession();
192
193 TryCreateFakeSpdySessionExpectingFailure(
194 spdy_session_pool_, key_, ERR_FAILED);
195 }
196
197 namespace {
198
199 // A helper class that vends a callback that, when fired, destroys a
200 // given SpdyStreamRequest.
201 class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
202 public:
StreamRequestDestroyingCallback()203 StreamRequestDestroyingCallback() {}
204
~StreamRequestDestroyingCallback()205 virtual ~StreamRequestDestroyingCallback() {}
206
SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request)207 void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) {
208 request_ = request.Pass();
209 }
210
MakeCallback()211 CompletionCallback MakeCallback() {
212 return base::Bind(&StreamRequestDestroyingCallback::OnComplete,
213 base::Unretained(this));
214 }
215
216 private:
OnComplete(int result)217 void OnComplete(int result) {
218 request_.reset();
219 SetResult(result);
220 }
221
222 scoped_ptr<SpdyStreamRequest> request_;
223 };
224
225 } // namespace
226
227 // Request kInitialMaxConcurrentStreams streams. Request two more
228 // streams, but have the callback for one destroy the second stream
229 // request. Close the session. Nothing should blow up. This is a
230 // regression test for http://crbug.com/250841 .
TEST_P(SpdySessionTest,PendingStreamCancellingAnother)231 TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
232 session_deps_.host_resolver->set_synchronous_mode(true);
233
234 MockRead reads[] = {MockRead(ASYNC, 0, 0), };
235
236 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
237 MockConnect connect_data(SYNCHRONOUS, OK);
238 data.set_connect_data(connect_data);
239 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
240
241 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
242 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
243
244 CreateDeterministicNetworkSession();
245
246 base::WeakPtr<SpdySession> session =
247 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
248
249 // Create the maximum number of concurrent streams.
250 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
251 base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
252 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog());
253 ASSERT_TRUE(spdy_stream != NULL);
254 }
255
256 SpdyStreamRequest request1;
257 scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest);
258
259 StreamRequestDestroyingCallback callback1;
260 ASSERT_EQ(ERR_IO_PENDING,
261 request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM,
262 session,
263 test_url_,
264 MEDIUM,
265 BoundNetLog(),
266 callback1.MakeCallback()));
267
268 // |callback2| is never called.
269 TestCompletionCallback callback2;
270 ASSERT_EQ(ERR_IO_PENDING,
271 request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM,
272 session,
273 test_url_,
274 MEDIUM,
275 BoundNetLog(),
276 callback2.callback()));
277
278 callback1.SetRequestToDestroy(request2.Pass());
279
280 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
281
282 EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
283
284 data.RunFor(1);
285 }
286
287 // A session receiving a GOAWAY frame with no active streams should
288 // immediately close.
TEST_P(SpdySessionTest,GoAwayWithNoActiveStreams)289 TEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
290 session_deps_.host_resolver->set_synchronous_mode(true);
291
292 MockConnect connect_data(SYNCHRONOUS, OK);
293 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
294 MockRead reads[] = {
295 CreateMockRead(*goaway, 0),
296 };
297 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
298 data.set_connect_data(connect_data);
299 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
300
301 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
302 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
303
304 CreateDeterministicNetworkSession();
305
306 base::WeakPtr<SpdySession> session =
307 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
308
309 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
310
311 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
312
313 // Read and process the GOAWAY frame.
314 data.RunFor(1);
315
316 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
317
318 EXPECT_TRUE(session == NULL);
319 }
320
321 // A session receiving a GOAWAY frame immediately with no active
322 // streams should then close.
TEST_P(SpdySessionTest,GoAwayImmediatelyWithNoActiveStreams)323 TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
324 session_deps_.host_resolver->set_synchronous_mode(true);
325
326 MockConnect connect_data(SYNCHRONOUS, OK);
327 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
328 MockRead reads[] = {
329 CreateMockRead(*goaway, 0, SYNCHRONOUS),
330 };
331 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
332 data.set_connect_data(connect_data);
333 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
334
335 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
336 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
337
338 CreateDeterministicNetworkSession();
339
340 data.StopAfter(1);
341
342 TryCreateInsecureSpdySessionExpectingFailure(
343 http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
344
345 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
346 }
347
348 // A session receiving a GOAWAY frame with active streams should close
349 // when the last active stream is closed.
TEST_P(SpdySessionTest,GoAwayWithActiveStreams)350 TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
351 session_deps_.host_resolver->set_synchronous_mode(true);
352
353 MockConnect connect_data(SYNCHRONOUS, OK);
354 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
355 MockRead reads[] = {
356 CreateMockRead(*goaway, 2),
357 MockRead(ASYNC, 0, 3) // EOF
358 };
359 scoped_ptr<SpdyFrame> req1(
360 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
361 scoped_ptr<SpdyFrame> req2(
362 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
363 MockWrite writes[] = {
364 CreateMockWrite(*req1, 0),
365 CreateMockWrite(*req2, 1),
366 };
367 DeterministicSocketData data(reads, arraysize(reads),
368 writes, arraysize(writes));
369 data.set_connect_data(connect_data);
370 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
371
372 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
373 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
374
375 CreateDeterministicNetworkSession();
376
377 base::WeakPtr<SpdySession> session =
378 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
379
380 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
381
382 GURL url("http://www.google.com");
383 base::WeakPtr<SpdyStream> spdy_stream1 =
384 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
385 session, url, MEDIUM, BoundNetLog());
386 test::StreamDelegateDoNothing delegate1(spdy_stream1);
387 spdy_stream1->SetDelegate(&delegate1);
388
389 base::WeakPtr<SpdyStream> spdy_stream2 =
390 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
391 session, url, MEDIUM, BoundNetLog());
392 test::StreamDelegateDoNothing delegate2(spdy_stream2);
393 spdy_stream2->SetDelegate(&delegate2);
394
395 scoped_ptr<SpdyHeaderBlock> headers(
396 spdy_util_.ConstructGetHeaderBlock(url.spec()));
397 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
398
399 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
400 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
401 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
402 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
403
404 data.RunFor(2);
405
406 EXPECT_EQ(1u, spdy_stream1->stream_id());
407 EXPECT_EQ(3u, spdy_stream2->stream_id());
408
409 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
410
411 // Read and process the GOAWAY frame.
412 data.RunFor(1);
413
414 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
415
416 EXPECT_FALSE(session->IsStreamActive(3));
417 EXPECT_EQ(NULL, spdy_stream2.get());
418 EXPECT_TRUE(session->IsStreamActive(1));
419
420 EXPECT_FALSE(session->IsClosed());
421
422 // Should close the session.
423 spdy_stream1->Close();
424 EXPECT_EQ(NULL, spdy_stream1.get());
425
426 EXPECT_TRUE(session == NULL);
427 }
428
429 // Have a session receive two GOAWAY frames, with the last one causing
430 // the last active stream to be closed. The session should then be
431 // closed after the second GOAWAY frame.
TEST_P(SpdySessionTest,GoAwayTwice)432 TEST_P(SpdySessionTest, GoAwayTwice) {
433 session_deps_.host_resolver->set_synchronous_mode(true);
434
435 MockConnect connect_data(SYNCHRONOUS, OK);
436 scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
437 scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
438 MockRead reads[] = {
439 CreateMockRead(*goaway1, 2),
440 CreateMockRead(*goaway2, 3),
441 MockRead(ASYNC, 0, 4) // EOF
442 };
443 scoped_ptr<SpdyFrame> req1(
444 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
445 scoped_ptr<SpdyFrame> req2(
446 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
447 MockWrite writes[] = {
448 CreateMockWrite(*req1, 0),
449 CreateMockWrite(*req2, 1),
450 };
451 DeterministicSocketData data(reads, arraysize(reads),
452 writes, arraysize(writes));
453 data.set_connect_data(connect_data);
454 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
455
456 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
457 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
458
459 CreateDeterministicNetworkSession();
460
461 base::WeakPtr<SpdySession> session =
462 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
463
464 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
465
466 GURL url("http://www.google.com");
467 base::WeakPtr<SpdyStream> spdy_stream1 =
468 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
469 session, url, MEDIUM, BoundNetLog());
470 test::StreamDelegateDoNothing delegate1(spdy_stream1);
471 spdy_stream1->SetDelegate(&delegate1);
472
473 base::WeakPtr<SpdyStream> spdy_stream2 =
474 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
475 session, url, MEDIUM, BoundNetLog());
476 test::StreamDelegateDoNothing delegate2(spdy_stream2);
477 spdy_stream2->SetDelegate(&delegate2);
478
479 scoped_ptr<SpdyHeaderBlock> headers(
480 spdy_util_.ConstructGetHeaderBlock(url.spec()));
481 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
482
483 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
484 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
485 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
486 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
487
488 data.RunFor(2);
489
490 EXPECT_EQ(1u, spdy_stream1->stream_id());
491 EXPECT_EQ(3u, spdy_stream2->stream_id());
492
493 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
494
495 // Read and process the first GOAWAY frame.
496 data.RunFor(1);
497
498 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
499
500 EXPECT_FALSE(session->IsStreamActive(3));
501 EXPECT_EQ(NULL, spdy_stream2.get());
502 EXPECT_TRUE(session->IsStreamActive(1));
503
504 EXPECT_FALSE(session->IsClosed());
505
506 // Read and process the second GOAWAY frame, which should close the
507 // session.
508 data.RunFor(1);
509
510 EXPECT_TRUE(session == NULL);
511 }
512
513 // Have a session with active streams receive a GOAWAY frame and then
514 // close it. It should handle the close properly (i.e., not try to
515 // make itself unavailable in its pool twice).
TEST_P(SpdySessionTest,GoAwayWithActiveStreamsThenClose)516 TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
517 session_deps_.host_resolver->set_synchronous_mode(true);
518
519 MockConnect connect_data(SYNCHRONOUS, OK);
520 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
521 MockRead reads[] = {
522 CreateMockRead(*goaway, 2),
523 MockRead(ASYNC, 0, 3) // EOF
524 };
525 scoped_ptr<SpdyFrame> req1(
526 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
527 scoped_ptr<SpdyFrame> req2(
528 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
529 MockWrite writes[] = {
530 CreateMockWrite(*req1, 0),
531 CreateMockWrite(*req2, 1),
532 };
533 DeterministicSocketData data(reads, arraysize(reads),
534 writes, arraysize(writes));
535 data.set_connect_data(connect_data);
536 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
537
538 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
539 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
540
541 CreateDeterministicNetworkSession();
542
543 base::WeakPtr<SpdySession> session =
544 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
545
546 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
547
548 GURL url("http://www.google.com");
549 base::WeakPtr<SpdyStream> spdy_stream1 =
550 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
551 session, url, MEDIUM, BoundNetLog());
552 test::StreamDelegateDoNothing delegate1(spdy_stream1);
553 spdy_stream1->SetDelegate(&delegate1);
554
555 base::WeakPtr<SpdyStream> spdy_stream2 =
556 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
557 session, url, MEDIUM, BoundNetLog());
558 test::StreamDelegateDoNothing delegate2(spdy_stream2);
559 spdy_stream2->SetDelegate(&delegate2);
560
561 scoped_ptr<SpdyHeaderBlock> headers(
562 spdy_util_.ConstructGetHeaderBlock(url.spec()));
563 scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
564
565 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
566 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
567 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
568 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
569
570 data.RunFor(2);
571
572 EXPECT_EQ(1u, spdy_stream1->stream_id());
573 EXPECT_EQ(3u, spdy_stream2->stream_id());
574
575 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
576
577 // Read and process the GOAWAY frame.
578 data.RunFor(1);
579
580 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
581
582 EXPECT_FALSE(session->IsStreamActive(3));
583 EXPECT_EQ(NULL, spdy_stream2.get());
584 EXPECT_TRUE(session->IsStreamActive(1));
585
586 EXPECT_FALSE(session->IsClosed());
587
588 session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
589
590 EXPECT_EQ(NULL, spdy_stream1.get());
591 EXPECT_TRUE(session == NULL);
592 }
593
594 // Try to create a stream after receiving a GOAWAY frame. It should
595 // fail.
TEST_P(SpdySessionTest,CreateStreamAfterGoAway)596 TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
597 const char kStreamUrl[] = "http://www.google.com";
598 session_deps_.host_resolver->set_synchronous_mode(true);
599
600 MockConnect connect_data(SYNCHRONOUS, OK);
601 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
602 MockRead reads[] = {
603 CreateMockRead(*goaway, 1),
604 MockRead(ASYNC, 0, 2) // EOF
605 };
606 scoped_ptr<SpdyFrame> req(
607 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
608 MockWrite writes[] = {
609 CreateMockWrite(*req, 0),
610 };
611 DeterministicSocketData data(reads, arraysize(reads),
612 writes, arraysize(writes));
613 data.set_connect_data(connect_data);
614 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
615
616 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
617 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
618
619 CreateDeterministicNetworkSession();
620
621 base::WeakPtr<SpdySession> session =
622 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
623
624 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
625
626 GURL url(kStreamUrl);
627 base::WeakPtr<SpdyStream> spdy_stream =
628 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
629 session, url, MEDIUM, BoundNetLog());
630 test::StreamDelegateDoNothing delegate(spdy_stream);
631 spdy_stream->SetDelegate(&delegate);
632
633 scoped_ptr<SpdyHeaderBlock> headers(
634 spdy_util_.ConstructGetHeaderBlock(url.spec()));
635 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
636 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
637
638 data.RunFor(1);
639
640 EXPECT_EQ(1u, spdy_stream->stream_id());
641
642 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
643
644 // Read and process the GOAWAY frame.
645 data.RunFor(1);
646
647 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
648 EXPECT_TRUE(session->IsStreamActive(1));
649
650 SpdyStreamRequest stream_request;
651 int rv = stream_request.StartRequest(
652 SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog(),
653 CompletionCallback());
654 EXPECT_EQ(ERR_FAILED, rv);
655
656 // Read and process EOF.
657 data.RunFor(1);
658
659 EXPECT_TRUE(session == NULL);
660 }
661
662 // Receiving a SYN_STREAM frame after a GOAWAY frame should result in
663 // the stream being refused.
TEST_P(SpdySessionTest,SynStreamAfterGoAway)664 TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
665 const char kStreamUrl[] = "http://www.google.com";
666 session_deps_.host_resolver->set_synchronous_mode(true);
667
668 MockConnect connect_data(SYNCHRONOUS, OK);
669 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
670 scoped_ptr<SpdyFrame>
671 push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
672 MockRead reads[] = {
673 CreateMockRead(*goaway, 1),
674 CreateMockRead(*push, 2),
675 MockRead(ASYNC, 0, 4) // EOF
676 };
677 scoped_ptr<SpdyFrame> req(
678 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
679 scoped_ptr<SpdyFrame> rst(
680 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
681 MockWrite writes[] = {
682 CreateMockWrite(*req, 0),
683 CreateMockWrite(*rst, 3)
684 };
685 DeterministicSocketData data(reads, arraysize(reads),
686 writes, arraysize(writes));
687 data.set_connect_data(connect_data);
688 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
689
690 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
691 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
692
693 CreateDeterministicNetworkSession();
694
695 base::WeakPtr<SpdySession> session =
696 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
697
698 EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
699
700 GURL url(kStreamUrl);
701 base::WeakPtr<SpdyStream> spdy_stream =
702 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
703 session, url, MEDIUM, BoundNetLog());
704 test::StreamDelegateDoNothing delegate(spdy_stream);
705 spdy_stream->SetDelegate(&delegate);
706
707 scoped_ptr<SpdyHeaderBlock> headers(
708 spdy_util_.ConstructGetHeaderBlock(url.spec()));
709 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
710 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
711
712 data.RunFor(1);
713
714 EXPECT_EQ(1u, spdy_stream->stream_id());
715
716 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
717
718 // Read and process the GOAWAY frame.
719 data.RunFor(1);
720
721 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
722 EXPECT_TRUE(session->IsStreamActive(1));
723
724 // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
725 // and EOF.
726 data.RunFor(3);
727
728 EXPECT_TRUE(session == NULL);
729 }
730
TEST_P(SpdySessionTest,ClientPing)731 TEST_P(SpdySessionTest, ClientPing) {
732 session_deps_.enable_ping = true;
733 session_deps_.host_resolver->set_synchronous_mode(true);
734
735 MockConnect connect_data(SYNCHRONOUS, OK);
736 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1));
737 MockRead reads[] = {
738 CreateMockRead(*read_ping, 1),
739 MockRead(ASYNC, 0, 0, 2) // EOF
740 };
741 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1));
742 MockWrite writes[] = {
743 CreateMockWrite(*write_ping, 0),
744 };
745 DeterministicSocketData data(
746 reads, arraysize(reads), writes, arraysize(writes));
747 data.set_connect_data(connect_data);
748 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
749
750 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
751 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
752
753 CreateDeterministicNetworkSession();
754
755 base::WeakPtr<SpdySession> session =
756 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
757
758 base::WeakPtr<SpdyStream> spdy_stream1 =
759 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
760 session, test_url_, MEDIUM, BoundNetLog());
761 ASSERT_TRUE(spdy_stream1.get() != NULL);
762 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
763 spdy_stream1->SetDelegate(&delegate);
764
765 base::TimeTicks before_ping_time = base::TimeTicks::Now();
766
767 session->set_connection_at_risk_of_loss_time(
768 base::TimeDelta::FromSeconds(-1));
769 session->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
770
771 session->SendPrefacePingIfNoneInFlight();
772
773 data.RunFor(2);
774
775 session->CheckPingStatus(before_ping_time);
776
777 EXPECT_EQ(0, session->pings_in_flight());
778 EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1));
779 EXPECT_FALSE(session->check_ping_status_pending());
780 EXPECT_GE(session->last_activity_time(), before_ping_time);
781
782 data.RunFor(1);
783
784 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
785
786 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
787 EXPECT_TRUE(session == NULL);
788 }
789
TEST_P(SpdySessionTest,ServerPing)790 TEST_P(SpdySessionTest, ServerPing) {
791 session_deps_.host_resolver->set_synchronous_mode(true);
792
793 MockConnect connect_data(SYNCHRONOUS, OK);
794 scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2));
795 MockRead reads[] = {
796 CreateMockRead(*read_ping),
797 MockRead(SYNCHRONOUS, 0, 0) // EOF
798 };
799 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2));
800 MockWrite writes[] = {
801 CreateMockWrite(*write_ping),
802 };
803 StaticSocketDataProvider data(
804 reads, arraysize(reads), writes, arraysize(writes));
805 data.set_connect_data(connect_data);
806 session_deps_.socket_factory->AddSocketDataProvider(&data);
807
808 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
809 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
810
811 CreateNetworkSession();
812
813 base::WeakPtr<SpdySession> session =
814 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
815
816 base::WeakPtr<SpdyStream> spdy_stream1 =
817 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
818 session, test_url_, MEDIUM, BoundNetLog());
819 ASSERT_TRUE(spdy_stream1.get() != NULL);
820 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
821 spdy_stream1->SetDelegate(&delegate);
822
823 // Flush the read completion task.
824 base::MessageLoop::current()->RunUntilIdle();
825
826 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
827
828 EXPECT_TRUE(session == NULL);
829 EXPECT_EQ(NULL, spdy_stream1.get());
830 }
831
832 // Cause a ping to be sent out while producing a write. The write loop
833 // should handle this properly, i.e. another DoWriteLoop task should
834 // not be posted. This is a regression test for
835 // http://crbug.com/261043 .
TEST_P(SpdySessionTest,PingAndWriteLoop)836 TEST_P(SpdySessionTest, PingAndWriteLoop) {
837 session_deps_.enable_ping = true;
838 session_deps_.time_func = TheNearFuture;
839
840 MockConnect connect_data(SYNCHRONOUS, OK);
841 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1));
842 scoped_ptr<SpdyFrame> req(
843 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
844 MockWrite writes[] = {
845 CreateMockWrite(*req, 0),
846 CreateMockWrite(*write_ping, 1),
847 };
848
849 MockRead reads[] = {
850 MockRead(ASYNC, 0, 2) // EOF
851 };
852
853 session_deps_.host_resolver->set_synchronous_mode(true);
854
855 DeterministicSocketData data(reads, arraysize(reads),
856 writes, arraysize(writes));
857 data.set_connect_data(connect_data);
858 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
859
860 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
861 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
862
863 CreateDeterministicNetworkSession();
864
865 base::WeakPtr<SpdySession> session =
866 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
867
868 GURL url("http://www.google.com");
869 base::WeakPtr<SpdyStream> spdy_stream =
870 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
871 session, url, LOWEST, BoundNetLog());
872 test::StreamDelegateDoNothing delegate(spdy_stream);
873 spdy_stream->SetDelegate(&delegate);
874
875 scoped_ptr<SpdyHeaderBlock> headers(
876 spdy_util_.ConstructGetHeaderBlock(url.spec()));
877 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
878
879 // Shift time so that a ping will be sent out.
880 g_time_delta = base::TimeDelta::FromSeconds(11);
881
882 data.RunFor(2);
883
884 session->CloseSessionOnError(ERR_ABORTED, "Aborting");
885 }
886
TEST_P(SpdySessionTest,DeleteExpiredPushStreams)887 TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
888 session_deps_.host_resolver->set_synchronous_mode(true);
889
890 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
891 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
892 session_deps_.time_func = TheNearFuture;
893
894 CreateNetworkSession();
895
896 base::WeakPtr<SpdySession> session =
897 CreateFakeSpdySession(spdy_session_pool_, key_);
898
899 session->buffered_spdy_framer_.reset(
900 new BufferedSpdyFramer(spdy_util_.spdy_version(), false));
901
902 // Create the associated stream and add to active streams.
903 scoped_ptr<SpdyHeaderBlock> request_headers(
904 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
905
906 scoped_ptr<SpdyStream> stream(new SpdyStream(SPDY_REQUEST_RESPONSE_STREAM,
907 session,
908 GURL(),
909 DEFAULT_PRIORITY,
910 kSpdyStreamInitialWindowSize,
911 kSpdyStreamInitialWindowSize,
912 session->net_log_));
913 stream->SendRequestHeaders(request_headers.Pass(), NO_MORE_DATA_TO_SEND);
914 SpdyStream* stream_ptr = stream.get();
915 session->InsertCreatedStream(stream.Pass());
916 stream = session->ActivateCreatedStream(stream_ptr);
917 session->InsertActivatedStream(stream.Pass());
918
919 SpdyHeaderBlock headers;
920 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/a.dat", &headers);
921
922 // OnSynStream() expects |in_io_loop_| to be true.
923 session->in_io_loop_ = true;
924 session->OnSynStream(2, 1, 0, 0, true, false, headers);
925 session->in_io_loop_ = false;
926
927 // Verify that there is one unclaimed push stream.
928 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
929 SpdySession::PushedStreamMap::iterator iter =
930 session->unclaimed_pushed_streams_.find(
931 GURL("http://www.google.com/a.dat"));
932 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
933
934 // Shift time to expire the push stream.
935 g_time_delta = base::TimeDelta::FromSeconds(301);
936
937 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat", &headers);
938 session->in_io_loop_ = true;
939 session->OnSynStream(4, 1, 0, 0, true, false, headers);
940 session->in_io_loop_ = false;
941
942 // Verify that the second pushed stream evicted the first pushed stream.
943 EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
944 iter = session->unclaimed_pushed_streams_.find(
945 GURL("http://www.google.com/b.dat"));
946 EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
947 }
948
TEST_P(SpdySessionTest,FailedPing)949 TEST_P(SpdySessionTest, FailedPing) {
950 session_deps_.host_resolver->set_synchronous_mode(true);
951
952 MockConnect connect_data(SYNCHRONOUS, OK);
953 MockRead reads[] = {
954 MockRead(ASYNC, 0, 0, 0) // EOF
955 };
956 scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1));
957 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
958 data.set_connect_data(connect_data);
959 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
960
961 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
962 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
963
964 CreateDeterministicNetworkSession();
965
966 base::WeakPtr<SpdySession> session =
967 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
968
969 base::WeakPtr<SpdyStream> spdy_stream1 =
970 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
971 session, test_url_, MEDIUM, BoundNetLog());
972 ASSERT_TRUE(spdy_stream1.get() != NULL);
973 test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
974 spdy_stream1->SetDelegate(&delegate);
975
976 session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
977 session->set_hung_interval(base::TimeDelta::FromSeconds(0));
978
979 // Send a PING frame.
980 session->WritePingFrame(1);
981 EXPECT_LT(0, session->pings_in_flight());
982 EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1));
983 EXPECT_TRUE(session->check_ping_status_pending());
984
985 // Assert session is not closed.
986 EXPECT_FALSE(session->IsClosed());
987 EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams());
988 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
989
990 // We set last time we have received any data in 1 sec less than now.
991 // CheckPingStatus will trigger timeout because hung interval is zero.
992 base::TimeTicks now = base::TimeTicks::Now();
993 session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
994 session->CheckPingStatus(now);
995
996 EXPECT_TRUE(session == NULL);
997 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
998
999 data.RunFor(1);
1000 EXPECT_EQ(NULL, spdy_stream1.get());
1001 }
1002
1003 // Request kInitialMaxConcurrentStreams + 1 streams. Receive a
1004 // settings frame increasing the max concurrent streams by 1. Make
1005 // sure nothing blows up. This is a regression test for
1006 // http://crbug.com/57331 .
TEST_P(SpdySessionTest,OnSettings)1007 TEST_P(SpdySessionTest, OnSettings) {
1008 session_deps_.host_resolver->set_synchronous_mode(true);
1009
1010 const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1011
1012 SettingsMap new_settings;
1013 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1014 new_settings[kSpdySettingsIds] =
1015 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1016 scoped_ptr<SpdyFrame> settings_frame(
1017 spdy_util_.ConstructSpdySettings(new_settings));
1018 MockRead reads[] = {
1019 CreateMockRead(*settings_frame, 0),
1020 MockRead(ASYNC, 0, 1),
1021 };
1022
1023 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
1024 MockConnect connect_data(SYNCHRONOUS, OK);
1025 data.set_connect_data(connect_data);
1026 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1027
1028 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1029 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1030
1031 CreateDeterministicNetworkSession();
1032
1033 base::WeakPtr<SpdySession> session =
1034 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1035
1036 // Create the maximum number of concurrent streams.
1037 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1038 base::WeakPtr<SpdyStream> spdy_stream =
1039 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1040 session, test_url_, MEDIUM, BoundNetLog());
1041 ASSERT_TRUE(spdy_stream != NULL);
1042 }
1043
1044 StreamReleaserCallback stream_releaser;
1045 SpdyStreamRequest request;
1046 ASSERT_EQ(ERR_IO_PENDING,
1047 request.StartRequest(
1048 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1049 BoundNetLog(),
1050 stream_releaser.MakeCallback(&request)));
1051
1052 data.RunFor(1);
1053
1054 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1055
1056 data.RunFor(1);
1057 EXPECT_TRUE(session == NULL);
1058 }
1059
1060 // Start with a persisted value for max concurrent streams. Receive a
1061 // settings frame increasing the max concurrent streams by 1 and which
1062 // also clears the persisted data. Verify that persisted data is
1063 // correct.
TEST_P(SpdySessionTest,ClearSettings)1064 TEST_P(SpdySessionTest, ClearSettings) {
1065 session_deps_.host_resolver->set_synchronous_mode(true);
1066
1067 SettingsMap new_settings;
1068 const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1069 new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1070 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1071 scoped_ptr<SpdyFrame> settings_frame(
1072 spdy_util_.ConstructSpdySettings(new_settings));
1073 uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1074 test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1075 MockRead reads[] = {
1076 CreateMockRead(*settings_frame, 0),
1077 MockRead(ASYNC, 0, 1),
1078 };
1079
1080 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
1081 MockConnect connect_data(SYNCHRONOUS, OK);
1082 data.set_connect_data(connect_data);
1083 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1084
1085 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1086 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1087
1088 CreateDeterministicNetworkSession();
1089
1090 // Initialize the SpdySetting with the default.
1091 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1092 test_host_port_pair_,
1093 SETTINGS_MAX_CONCURRENT_STREAMS,
1094 SETTINGS_FLAG_PLEASE_PERSIST,
1095 kInitialMaxConcurrentStreams);
1096
1097 EXPECT_FALSE(
1098 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1099 test_host_port_pair_).empty());
1100
1101 base::WeakPtr<SpdySession> session =
1102 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1103
1104 // Create the maximum number of concurrent streams.
1105 for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1106 base::WeakPtr<SpdyStream> spdy_stream =
1107 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1108 session, test_url_, MEDIUM, BoundNetLog());
1109 ASSERT_TRUE(spdy_stream != NULL);
1110 }
1111
1112 StreamReleaserCallback stream_releaser;
1113
1114 SpdyStreamRequest request;
1115 ASSERT_EQ(ERR_IO_PENDING,
1116 request.StartRequest(
1117 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1118 BoundNetLog(),
1119 stream_releaser.MakeCallback(&request)));
1120
1121 data.RunFor(1);
1122
1123 EXPECT_EQ(OK, stream_releaser.WaitForResult());
1124
1125 // Make sure that persisted data is cleared.
1126 EXPECT_TRUE(
1127 spdy_session_pool_->http_server_properties()->GetSpdySettings(
1128 test_host_port_pair_).empty());
1129
1130 // Make sure session's max_concurrent_streams is correct.
1131 EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1132 session->max_concurrent_streams());
1133
1134 data.RunFor(1);
1135 EXPECT_TRUE(session == NULL);
1136 }
1137
1138 // Start with max concurrent streams set to 1. Request two streams.
1139 // When the first completes, have the callback close its stream, which
1140 // should trigger the second stream creation. Then cancel that one
1141 // immediately. Don't crash. This is a regression test for
1142 // http://crbug.com/63532 .
TEST_P(SpdySessionTest,CancelPendingCreateStream)1143 TEST_P(SpdySessionTest, CancelPendingCreateStream) {
1144 session_deps_.host_resolver->set_synchronous_mode(true);
1145
1146 MockRead reads[] = {
1147 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1148 };
1149
1150 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1151 MockConnect connect_data(SYNCHRONOUS, OK);
1152
1153 data.set_connect_data(connect_data);
1154 session_deps_.socket_factory->AddSocketDataProvider(&data);
1155
1156 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1157 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1158
1159 CreateNetworkSession();
1160
1161 // Initialize the SpdySetting with 1 max concurrent streams.
1162 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1163 test_host_port_pair_,
1164 SETTINGS_MAX_CONCURRENT_STREAMS,
1165 SETTINGS_FLAG_PLEASE_PERSIST,
1166 1);
1167
1168 base::WeakPtr<SpdySession> session =
1169 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1170
1171 // Leave room for only one more stream to be created.
1172 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1173 base::WeakPtr<SpdyStream> spdy_stream =
1174 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1175 session, test_url_, MEDIUM, BoundNetLog());
1176 ASSERT_TRUE(spdy_stream != NULL);
1177 }
1178
1179 // Create 2 more streams. First will succeed. Second will be pending.
1180 base::WeakPtr<SpdyStream> spdy_stream1 =
1181 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1182 session, test_url_, MEDIUM, BoundNetLog());
1183 ASSERT_TRUE(spdy_stream1.get() != NULL);
1184
1185 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1186 // a valgrind error if the callback is invoked when it's not supposed to be.
1187 scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
1188
1189 SpdyStreamRequest request;
1190 ASSERT_EQ(ERR_IO_PENDING,
1191 request.StartRequest(
1192 SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1193 BoundNetLog(),
1194 callback->callback()));
1195
1196 // Release the first one, this will allow the second to be created.
1197 spdy_stream1->Cancel();
1198 EXPECT_EQ(NULL, spdy_stream1.get());
1199
1200 request.CancelRequest();
1201 callback.reset();
1202
1203 // Should not crash when running the pending callback.
1204 base::MessageLoop::current()->RunUntilIdle();
1205 }
1206
TEST_P(SpdySessionTest,SendInitialDataOnNewSession)1207 TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
1208 session_deps_.host_resolver->set_synchronous_mode(true);
1209
1210 MockRead reads[] = {
1211 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
1212 };
1213
1214 SettingsMap settings;
1215 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
1216 const SpdySettingsIds kSpdySettingsIds2 = SETTINGS_INITIAL_WINDOW_SIZE;
1217 const uint32 kInitialRecvWindowSize = 10 * 1024 * 1024;
1218 settings[kSpdySettingsIds1] =
1219 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
1220 if (spdy_util_.spdy_version() >= SPDY3) {
1221 settings[kSpdySettingsIds2] =
1222 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialRecvWindowSize);
1223 }
1224 MockConnect connect_data(SYNCHRONOUS, OK);
1225 scoped_ptr<SpdyFrame> settings_frame(
1226 spdy_util_.ConstructSpdySettings(settings));
1227 scoped_ptr<SpdyFrame> initial_window_update(
1228 spdy_util_.ConstructSpdyWindowUpdate(
1229 kSessionFlowControlStreamId,
1230 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
1231 std::vector<MockWrite> writes;
1232 if (GetParam() == kProtoHTTP2Draft04) {
1233 writes.push_back(
1234 MockWrite(ASYNC,
1235 kHttp2ConnectionHeaderPrefix,
1236 kHttp2ConnectionHeaderPrefixSize));
1237 }
1238 writes.push_back(CreateMockWrite(*settings_frame));
1239 if (GetParam() >= kProtoSPDY31) {
1240 writes.push_back(CreateMockWrite(*initial_window_update));
1241 };
1242
1243 SettingsMap server_settings;
1244 const uint32 initial_max_concurrent_streams = 1;
1245 server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1246 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1247 initial_max_concurrent_streams);
1248 scoped_ptr<SpdyFrame> server_settings_frame(
1249 spdy_util_.ConstructSpdySettings(server_settings));
1250 writes.push_back(CreateMockWrite(*server_settings_frame));
1251
1252 session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize;
1253
1254 StaticSocketDataProvider data(reads, arraysize(reads),
1255 vector_as_array(&writes), writes.size());
1256 data.set_connect_data(connect_data);
1257 session_deps_.socket_factory->AddSocketDataProvider(&data);
1258
1259 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1260 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1261
1262 CreateNetworkSession();
1263
1264 spdy_session_pool_->http_server_properties()->SetSpdySetting(
1265 test_host_port_pair_,
1266 SETTINGS_MAX_CONCURRENT_STREAMS,
1267 SETTINGS_FLAG_PLEASE_PERSIST,
1268 initial_max_concurrent_streams);
1269
1270 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1271 pool_peer.SetEnableSendingInitialData(true);
1272
1273 base::WeakPtr<SpdySession> session =
1274 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1275
1276 base::MessageLoop::current()->RunUntilIdle();
1277 EXPECT_TRUE(data.at_write_eof());
1278 }
1279
TEST_P(SpdySessionTest,ClearSettingsStorageOnIPAddressChanged)1280 TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
1281 CreateNetworkSession();
1282
1283 base::WeakPtr<HttpServerProperties> test_http_server_properties =
1284 spdy_session_pool_->http_server_properties();
1285 SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
1286 test_http_server_properties->SetSpdySetting(
1287 test_host_port_pair_,
1288 SETTINGS_MAX_CONCURRENT_STREAMS,
1289 SETTINGS_FLAG_PLEASE_PERSIST,
1290 2);
1291 EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
1292 test_host_port_pair_).size());
1293 spdy_session_pool_->OnIPAddressChanged();
1294 EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
1295 test_host_port_pair_).size());
1296 }
1297
TEST_P(SpdySessionTest,Initialize)1298 TEST_P(SpdySessionTest, Initialize) {
1299 CapturingBoundNetLog log;
1300 session_deps_.net_log = log.bound().net_log();
1301 session_deps_.host_resolver->set_synchronous_mode(true);
1302
1303 MockConnect connect_data(SYNCHRONOUS, OK);
1304 MockRead reads[] = {
1305 MockRead(ASYNC, 0, 0) // EOF
1306 };
1307
1308 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1309 data.set_connect_data(connect_data);
1310 session_deps_.socket_factory->AddSocketDataProvider(&data);
1311
1312 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1313 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1314
1315 CreateNetworkSession();
1316
1317 base::WeakPtr<SpdySession> session =
1318 CreateInsecureSpdySession(http_session_, key_, log.bound());
1319 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1320
1321 // Flush the read completion task.
1322 base::MessageLoop::current()->RunUntilIdle();
1323
1324 net::CapturingNetLog::CapturedEntryList entries;
1325 log.GetEntries(&entries);
1326 EXPECT_LT(0u, entries.size());
1327
1328 // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly.
1329 int pos = net::ExpectLogContainsSomewhere(
1330 entries, 0,
1331 net::NetLog::TYPE_SPDY_SESSION_INITIALIZED,
1332 net::NetLog::PHASE_NONE);
1333 EXPECT_LT(0, pos);
1334
1335 CapturingNetLog::CapturedEntry entry = entries[pos];
1336 NetLog::Source socket_source;
1337 EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1338 &socket_source));
1339 EXPECT_TRUE(socket_source.IsValid());
1340 EXPECT_NE(log.bound().source().id, socket_source.id);
1341 }
1342
TEST_P(SpdySessionTest,CloseSessionOnError)1343 TEST_P(SpdySessionTest, CloseSessionOnError) {
1344 session_deps_.host_resolver->set_synchronous_mode(true);
1345
1346 MockConnect connect_data(SYNCHRONOUS, OK);
1347 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
1348 MockRead reads[] = {
1349 CreateMockRead(*goaway),
1350 MockRead(SYNCHRONOUS, 0, 0) // EOF
1351 };
1352
1353 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1354 data.set_connect_data(connect_data);
1355 session_deps_.socket_factory->AddSocketDataProvider(&data);
1356
1357 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1358 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1359
1360 CreateNetworkSession();
1361
1362 CapturingBoundNetLog log;
1363 base::WeakPtr<SpdySession> session =
1364 CreateInsecureSpdySession(http_session_, key_, log.bound());
1365 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1366
1367 // Flush the read completion task.
1368 base::MessageLoop::current()->RunUntilIdle();
1369
1370 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1371 EXPECT_TRUE(session == NULL);
1372
1373 // Check that the NetLog was filled reasonably.
1374 net::CapturingNetLog::CapturedEntryList entries;
1375 log.GetEntries(&entries);
1376 EXPECT_LT(0u, entries.size());
1377
1378 // Check that we logged SPDY_SESSION_CLOSE correctly.
1379 int pos = net::ExpectLogContainsSomewhere(
1380 entries, 0,
1381 net::NetLog::TYPE_SPDY_SESSION_CLOSE,
1382 net::NetLog::PHASE_NONE);
1383
1384 if (pos < static_cast<int>(entries.size())) {
1385 CapturingNetLog::CapturedEntry entry = entries[pos];
1386 int error_code = 0;
1387 ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1388 EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1389 } else {
1390 ADD_FAILURE();
1391 }
1392 }
1393
1394 // Queue up a low-priority SYN_STREAM followed by a high-priority
1395 // one. The high priority one should still send first and receive
1396 // first.
TEST_P(SpdySessionTest,OutOfOrderSynStreams)1397 TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1398 // Construct the request.
1399 MockConnect connect_data(SYNCHRONOUS, OK);
1400 scoped_ptr<SpdyFrame> req_highest(
1401 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true));
1402 scoped_ptr<SpdyFrame> req_lowest(
1403 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1404 MockWrite writes[] = {
1405 CreateMockWrite(*req_highest, 0),
1406 CreateMockWrite(*req_lowest, 1),
1407 };
1408
1409 scoped_ptr<SpdyFrame> resp_highest(
1410 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1411 scoped_ptr<SpdyFrame> body_highest(
1412 spdy_util_.ConstructSpdyBodyFrame(1, true));
1413 scoped_ptr<SpdyFrame> resp_lowest(
1414 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1415 scoped_ptr<SpdyFrame> body_lowest(
1416 spdy_util_.ConstructSpdyBodyFrame(3, true));
1417 MockRead reads[] = {
1418 CreateMockRead(*resp_highest, 2),
1419 CreateMockRead(*body_highest, 3),
1420 CreateMockRead(*resp_lowest, 4),
1421 CreateMockRead(*body_lowest, 5),
1422 MockRead(ASYNC, 0, 6) // EOF
1423 };
1424
1425 session_deps_.host_resolver->set_synchronous_mode(true);
1426
1427 DeterministicSocketData data(reads, arraysize(reads),
1428 writes, arraysize(writes));
1429 data.set_connect_data(connect_data);
1430 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1431
1432 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1433 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1434
1435 CreateDeterministicNetworkSession();
1436
1437 base::WeakPtr<SpdySession> session =
1438 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1439
1440 GURL url("http://www.google.com");
1441
1442 base::WeakPtr<SpdyStream> spdy_stream_lowest =
1443 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1444 session, url, LOWEST, BoundNetLog());
1445 ASSERT_TRUE(spdy_stream_lowest);
1446 EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1447 test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1448 spdy_stream_lowest->SetDelegate(&delegate_lowest);
1449
1450 base::WeakPtr<SpdyStream> spdy_stream_highest =
1451 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1452 session, url, HIGHEST, BoundNetLog());
1453 ASSERT_TRUE(spdy_stream_highest);
1454 EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1455 test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1456 spdy_stream_highest->SetDelegate(&delegate_highest);
1457
1458 // Queue the lower priority one first.
1459
1460 scoped_ptr<SpdyHeaderBlock> headers_lowest(
1461 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1462 spdy_stream_lowest->SendRequestHeaders(
1463 headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1464 EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1465
1466 scoped_ptr<SpdyHeaderBlock> headers_highest(
1467 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1468 spdy_stream_highest->SendRequestHeaders(
1469 headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1470 EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1471
1472 data.RunFor(7);
1473
1474 EXPECT_FALSE(spdy_stream_lowest);
1475 EXPECT_FALSE(spdy_stream_highest);
1476 EXPECT_EQ(3u, delegate_lowest.stream_id());
1477 EXPECT_EQ(1u, delegate_highest.stream_id());
1478 }
1479
TEST_P(SpdySessionTest,CancelStream)1480 TEST_P(SpdySessionTest, CancelStream) {
1481 MockConnect connect_data(SYNCHRONOUS, OK);
1482 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1483 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1484 scoped_ptr<SpdyFrame> req2(
1485 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1486 MockWrite writes[] = {
1487 CreateMockWrite(*req2, 0),
1488 };
1489
1490 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1491 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1492 MockRead reads[] = {
1493 CreateMockRead(*resp2, 1),
1494 CreateMockRead(*body2, 2),
1495 MockRead(ASYNC, 0, 3) // EOF
1496 };
1497
1498 session_deps_.host_resolver->set_synchronous_mode(true);
1499
1500 DeterministicSocketData data(reads, arraysize(reads),
1501 writes, arraysize(writes));
1502 data.set_connect_data(connect_data);
1503 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1504
1505 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1506 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1507
1508 CreateDeterministicNetworkSession();
1509
1510 base::WeakPtr<SpdySession> session =
1511 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1512
1513 GURL url1("http://www.google.com");
1514 base::WeakPtr<SpdyStream> spdy_stream1 =
1515 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1516 session, url1, HIGHEST, BoundNetLog());
1517 ASSERT_TRUE(spdy_stream1.get() != NULL);
1518 EXPECT_EQ(0u, spdy_stream1->stream_id());
1519 test::StreamDelegateDoNothing delegate1(spdy_stream1);
1520 spdy_stream1->SetDelegate(&delegate1);
1521
1522 GURL url2("http://www.google.com");
1523 base::WeakPtr<SpdyStream> spdy_stream2 =
1524 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1525 session, url2, LOWEST, BoundNetLog());
1526 ASSERT_TRUE(spdy_stream2.get() != NULL);
1527 EXPECT_EQ(0u, spdy_stream2->stream_id());
1528 test::StreamDelegateDoNothing delegate2(spdy_stream2);
1529 spdy_stream2->SetDelegate(&delegate2);
1530
1531 scoped_ptr<SpdyHeaderBlock> headers(
1532 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1533 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1534 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1535
1536 scoped_ptr<SpdyHeaderBlock> headers2(
1537 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1538 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1539 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1540
1541 EXPECT_EQ(0u, spdy_stream1->stream_id());
1542
1543 spdy_stream1->Cancel();
1544 EXPECT_EQ(NULL, spdy_stream1.get());
1545
1546 EXPECT_EQ(0u, delegate1.stream_id());
1547
1548 data.RunFor(1);
1549
1550 EXPECT_EQ(0u, delegate1.stream_id());
1551 EXPECT_EQ(1u, delegate2.stream_id());
1552
1553 spdy_stream2->Cancel();
1554 EXPECT_EQ(NULL, spdy_stream2.get());
1555 }
1556
1557 // Create two streams that are set to re-close themselves on close,
1558 // and then close the session. Nothing should blow up. Also a
1559 // regression test for http://crbug.com/139518 .
TEST_P(SpdySessionTest,CloseSessionWithTwoCreatedSelfClosingStreams)1560 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1561 session_deps_.host_resolver->set_synchronous_mode(true);
1562
1563 MockConnect connect_data(SYNCHRONOUS, OK);
1564
1565 // No actual data will be sent.
1566 MockWrite writes[] = {
1567 MockWrite(ASYNC, 0, 1) // EOF
1568 };
1569
1570 MockRead reads[] = {
1571 MockRead(ASYNC, 0, 0) // EOF
1572 };
1573 DeterministicSocketData data(reads, arraysize(reads),
1574 writes, arraysize(writes));
1575 data.set_connect_data(connect_data);
1576 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1577
1578 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1579 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1580
1581 CreateDeterministicNetworkSession();
1582
1583 base::WeakPtr<SpdySession> session =
1584 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1585
1586 GURL url1("http://www.google.com");
1587 base::WeakPtr<SpdyStream> spdy_stream1 =
1588 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1589 session, url1, HIGHEST, BoundNetLog());
1590 ASSERT_TRUE(spdy_stream1.get() != NULL);
1591 EXPECT_EQ(0u, spdy_stream1->stream_id());
1592
1593 GURL url2("http://www.google.com");
1594 base::WeakPtr<SpdyStream> spdy_stream2 =
1595 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1596 session, url2, LOWEST, BoundNetLog());
1597 ASSERT_TRUE(spdy_stream2.get() != NULL);
1598 EXPECT_EQ(0u, spdy_stream2->stream_id());
1599
1600 test::ClosingDelegate delegate1(spdy_stream1);
1601 spdy_stream1->SetDelegate(&delegate1);
1602
1603 test::ClosingDelegate delegate2(spdy_stream2);
1604 spdy_stream2->SetDelegate(&delegate2);
1605
1606 scoped_ptr<SpdyHeaderBlock> headers(
1607 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1608 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1609 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1610
1611 scoped_ptr<SpdyHeaderBlock> headers2(
1612 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1613 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1614 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1615
1616 // Ensure that the streams have not yet been activated and assigned an id.
1617 EXPECT_EQ(0u, spdy_stream1->stream_id());
1618 EXPECT_EQ(0u, spdy_stream2->stream_id());
1619
1620 // Ensure we don't crash while closing the session.
1621 session->CloseSessionOnError(ERR_ABORTED, std::string());
1622
1623 EXPECT_EQ(NULL, spdy_stream1.get());
1624 EXPECT_EQ(NULL, spdy_stream2.get());
1625
1626 EXPECT_TRUE(delegate1.StreamIsClosed());
1627 EXPECT_TRUE(delegate2.StreamIsClosed());
1628
1629 EXPECT_TRUE(session == NULL);
1630 }
1631
1632 // Create two streams that are set to close each other on close, and
1633 // then close the session. Nothing should blow up.
TEST_P(SpdySessionTest,CloseSessionWithTwoCreatedMutuallyClosingStreams)1634 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
1635 session_deps_.host_resolver->set_synchronous_mode(true);
1636
1637 MockConnect connect_data(SYNCHRONOUS, OK);
1638
1639 // No actual data will be sent.
1640 MockWrite writes[] = {
1641 MockWrite(ASYNC, 0, 1) // EOF
1642 };
1643
1644 MockRead reads[] = {
1645 MockRead(ASYNC, 0, 0) // EOF
1646 };
1647 DeterministicSocketData data(reads, arraysize(reads),
1648 writes, arraysize(writes));
1649 data.set_connect_data(connect_data);
1650 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1651
1652 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1653 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1654
1655 CreateDeterministicNetworkSession();
1656
1657 base::WeakPtr<SpdySession> session =
1658 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1659
1660 GURL url1("http://www.google.com");
1661 base::WeakPtr<SpdyStream> spdy_stream1 =
1662 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1663 session, url1, HIGHEST, BoundNetLog());
1664 ASSERT_TRUE(spdy_stream1.get() != NULL);
1665 EXPECT_EQ(0u, spdy_stream1->stream_id());
1666
1667 GURL url2("http://www.google.com");
1668 base::WeakPtr<SpdyStream> spdy_stream2 =
1669 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1670 session, url2, LOWEST, BoundNetLog());
1671 ASSERT_TRUE(spdy_stream2.get() != NULL);
1672 EXPECT_EQ(0u, spdy_stream2->stream_id());
1673
1674 // Make |spdy_stream1| close |spdy_stream2|.
1675 test::ClosingDelegate delegate1(spdy_stream2);
1676 spdy_stream1->SetDelegate(&delegate1);
1677
1678 // Make |spdy_stream2| close |spdy_stream1|.
1679 test::ClosingDelegate delegate2(spdy_stream1);
1680 spdy_stream2->SetDelegate(&delegate2);
1681
1682 scoped_ptr<SpdyHeaderBlock> headers(
1683 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1684 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1685 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1686
1687 scoped_ptr<SpdyHeaderBlock> headers2(
1688 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1689 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1690 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1691
1692 // Ensure that the streams have not yet been activated and assigned an id.
1693 EXPECT_EQ(0u, spdy_stream1->stream_id());
1694 EXPECT_EQ(0u, spdy_stream2->stream_id());
1695
1696 // Ensure we don't crash while closing the session.
1697 session->CloseSessionOnError(ERR_ABORTED, std::string());
1698
1699 EXPECT_EQ(NULL, spdy_stream1.get());
1700 EXPECT_EQ(NULL, spdy_stream2.get());
1701
1702 EXPECT_TRUE(delegate1.StreamIsClosed());
1703 EXPECT_TRUE(delegate2.StreamIsClosed());
1704
1705 EXPECT_TRUE(session == NULL);
1706 }
1707
1708 // Create two streams that are set to re-close themselves on close,
1709 // activate them, and then close the session. Nothing should blow up.
TEST_P(SpdySessionTest,CloseSessionWithTwoActivatedSelfClosingStreams)1710 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
1711 session_deps_.host_resolver->set_synchronous_mode(true);
1712
1713 MockConnect connect_data(SYNCHRONOUS, OK);
1714
1715 scoped_ptr<SpdyFrame> req1(
1716 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1717 scoped_ptr<SpdyFrame> req2(
1718 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
1719 MockWrite writes[] = {
1720 CreateMockWrite(*req1, 0),
1721 CreateMockWrite(*req2, 1),
1722 };
1723
1724 MockRead reads[] = {
1725 MockRead(ASYNC, 0, 2) // EOF
1726 };
1727
1728 DeterministicSocketData data(reads, arraysize(reads),
1729 writes, arraysize(writes));
1730 data.set_connect_data(connect_data);
1731 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1732
1733 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1734 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1735
1736 CreateDeterministicNetworkSession();
1737
1738 base::WeakPtr<SpdySession> session =
1739 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1740
1741 GURL url1("http://www.google.com");
1742 base::WeakPtr<SpdyStream> spdy_stream1 =
1743 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1744 session, url1, MEDIUM, BoundNetLog());
1745 ASSERT_TRUE(spdy_stream1.get() != NULL);
1746 EXPECT_EQ(0u, spdy_stream1->stream_id());
1747
1748 GURL url2("http://www.google.com");
1749 base::WeakPtr<SpdyStream> spdy_stream2 =
1750 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1751 session, url2, MEDIUM, BoundNetLog());
1752 ASSERT_TRUE(spdy_stream2.get() != NULL);
1753 EXPECT_EQ(0u, spdy_stream2->stream_id());
1754
1755 test::ClosingDelegate delegate1(spdy_stream1);
1756 spdy_stream1->SetDelegate(&delegate1);
1757
1758 test::ClosingDelegate delegate2(spdy_stream2);
1759 spdy_stream2->SetDelegate(&delegate2);
1760
1761 scoped_ptr<SpdyHeaderBlock> headers(
1762 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1763 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1764 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1765
1766 scoped_ptr<SpdyHeaderBlock> headers2(
1767 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1768 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1769 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1770
1771 // Ensure that the streams have not yet been activated and assigned an id.
1772 EXPECT_EQ(0u, spdy_stream1->stream_id());
1773 EXPECT_EQ(0u, spdy_stream2->stream_id());
1774
1775 data.RunFor(2);
1776
1777 EXPECT_EQ(1u, spdy_stream1->stream_id());
1778 EXPECT_EQ(3u, spdy_stream2->stream_id());
1779
1780 // Ensure we don't crash while closing the session.
1781 session->CloseSessionOnError(ERR_ABORTED, std::string());
1782
1783 EXPECT_EQ(NULL, spdy_stream1.get());
1784 EXPECT_EQ(NULL, spdy_stream2.get());
1785
1786 EXPECT_TRUE(delegate1.StreamIsClosed());
1787 EXPECT_TRUE(delegate2.StreamIsClosed());
1788
1789 EXPECT_TRUE(session == NULL);
1790 }
1791
1792 // Create two streams that are set to close each other on close,
1793 // activate them, and then close the session. Nothing should blow up.
TEST_P(SpdySessionTest,CloseSessionWithTwoActivatedMutuallyClosingStreams)1794 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
1795 session_deps_.host_resolver->set_synchronous_mode(true);
1796
1797 MockConnect connect_data(SYNCHRONOUS, OK);
1798
1799 scoped_ptr<SpdyFrame> req1(
1800 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1801 scoped_ptr<SpdyFrame> req2(
1802 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
1803 MockWrite writes[] = {
1804 CreateMockWrite(*req1, 0),
1805 CreateMockWrite(*req2, 1),
1806 };
1807
1808 MockRead reads[] = {
1809 MockRead(ASYNC, 0, 2) // EOF
1810 };
1811
1812 DeterministicSocketData data(reads, arraysize(reads),
1813 writes, arraysize(writes));
1814 data.set_connect_data(connect_data);
1815 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1816
1817 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1818 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1819
1820 CreateDeterministicNetworkSession();
1821
1822 base::WeakPtr<SpdySession> session =
1823 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1824
1825 GURL url1("http://www.google.com");
1826 base::WeakPtr<SpdyStream> spdy_stream1 =
1827 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1828 session, url1, MEDIUM, BoundNetLog());
1829 ASSERT_TRUE(spdy_stream1.get() != NULL);
1830 EXPECT_EQ(0u, spdy_stream1->stream_id());
1831
1832 GURL url2("http://www.google.com");
1833 base::WeakPtr<SpdyStream> spdy_stream2 =
1834 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1835 session, url2, MEDIUM, BoundNetLog());
1836 ASSERT_TRUE(spdy_stream2.get() != NULL);
1837 EXPECT_EQ(0u, spdy_stream2->stream_id());
1838
1839 // Make |spdy_stream1| close |spdy_stream2|.
1840 test::ClosingDelegate delegate1(spdy_stream2);
1841 spdy_stream1->SetDelegate(&delegate1);
1842
1843 // Make |spdy_stream2| close |spdy_stream1|.
1844 test::ClosingDelegate delegate2(spdy_stream1);
1845 spdy_stream2->SetDelegate(&delegate2);
1846
1847 scoped_ptr<SpdyHeaderBlock> headers(
1848 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1849 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1850 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1851
1852 scoped_ptr<SpdyHeaderBlock> headers2(
1853 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1854 spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1855 EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1856
1857 // Ensure that the streams have not yet been activated and assigned an id.
1858 EXPECT_EQ(0u, spdy_stream1->stream_id());
1859 EXPECT_EQ(0u, spdy_stream2->stream_id());
1860
1861 data.RunFor(2);
1862
1863 EXPECT_EQ(1u, spdy_stream1->stream_id());
1864 EXPECT_EQ(3u, spdy_stream2->stream_id());
1865
1866 // Ensure we don't crash while closing the session.
1867 session->CloseSessionOnError(ERR_ABORTED, std::string());
1868
1869 EXPECT_EQ(NULL, spdy_stream1.get());
1870 EXPECT_EQ(NULL, spdy_stream2.get());
1871
1872 EXPECT_TRUE(delegate1.StreamIsClosed());
1873 EXPECT_TRUE(delegate2.StreamIsClosed());
1874
1875 EXPECT_TRUE(session == NULL);
1876 }
1877
1878 // Delegate that closes a given session when the stream is closed.
1879 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
1880 public:
SessionClosingDelegate(const base::WeakPtr<SpdyStream> & stream,const base::WeakPtr<SpdySession> & session_to_close)1881 SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
1882 const base::WeakPtr<SpdySession>& session_to_close)
1883 : StreamDelegateDoNothing(stream),
1884 session_to_close_(session_to_close) {}
1885
~SessionClosingDelegate()1886 virtual ~SessionClosingDelegate() {}
1887
OnClose(int status)1888 virtual void OnClose(int status) OVERRIDE {
1889 session_to_close_->CloseSessionOnError(ERR_ABORTED, "Aborted");
1890 }
1891
1892 private:
1893 base::WeakPtr<SpdySession> session_to_close_;
1894 };
1895
1896 // Close an activated stream that closes its session. Nothing should
1897 // blow up. This is a regression test for http://crbug.com/263691 .
TEST_P(SpdySessionTest,CloseActivatedStreamThatClosesSession)1898 TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
1899 session_deps_.host_resolver->set_synchronous_mode(true);
1900
1901 MockConnect connect_data(SYNCHRONOUS, OK);
1902
1903 scoped_ptr<SpdyFrame> req(
1904 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1905 MockWrite writes[] = {
1906 CreateMockWrite(*req, 0),
1907 };
1908
1909 MockRead reads[] = {
1910 MockRead(ASYNC, 0, 1) // EOF
1911 };
1912 DeterministicSocketData data(reads, arraysize(reads),
1913 writes, arraysize(writes));
1914 data.set_connect_data(connect_data);
1915 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1916
1917 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1918 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1919
1920 CreateDeterministicNetworkSession();
1921
1922 base::WeakPtr<SpdySession> session =
1923 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1924
1925 GURL url("http://www.google.com");
1926 base::WeakPtr<SpdyStream> spdy_stream =
1927 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1928 session, url, MEDIUM, BoundNetLog());
1929 ASSERT_TRUE(spdy_stream.get() != NULL);
1930 EXPECT_EQ(0u, spdy_stream->stream_id());
1931
1932 SessionClosingDelegate delegate(spdy_stream, session);
1933 spdy_stream->SetDelegate(&delegate);
1934
1935 scoped_ptr<SpdyHeaderBlock> headers(
1936 spdy_util_.ConstructGetHeaderBlock(url.spec()));
1937 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1938 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1939
1940 EXPECT_EQ(0u, spdy_stream->stream_id());
1941
1942 data.RunFor(1);
1943
1944 EXPECT_EQ(1u, spdy_stream->stream_id());
1945
1946 // Ensure we don't crash while closing the stream (which closes the
1947 // session).
1948 spdy_stream->Cancel();
1949
1950 EXPECT_EQ(NULL, spdy_stream.get());
1951 EXPECT_TRUE(delegate.StreamIsClosed());
1952 EXPECT_TRUE(session == NULL);
1953 }
1954
TEST_P(SpdySessionTest,VerifyDomainAuthentication)1955 TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
1956 session_deps_.host_resolver->set_synchronous_mode(true);
1957
1958 MockConnect connect_data(SYNCHRONOUS, OK);
1959
1960 // No actual data will be sent.
1961 MockWrite writes[] = {
1962 MockWrite(ASYNC, 0, 1) // EOF
1963 };
1964
1965 MockRead reads[] = {
1966 MockRead(ASYNC, 0, 0) // EOF
1967 };
1968 DeterministicSocketData data(reads, arraysize(reads),
1969 writes, arraysize(writes));
1970 data.set_connect_data(connect_data);
1971 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1972
1973 // Load a cert that is valid for:
1974 // www.example.org
1975 // mail.example.org
1976 // www.example.com
1977 base::FilePath certs_dir = GetTestCertsDirectory();
1978 scoped_refptr<X509Certificate> test_cert(
1979 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
1980 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert);
1981
1982 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1983 ssl.cert = test_cert;
1984 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1985
1986 CreateDeterministicNetworkSession();
1987
1988 base::WeakPtr<SpdySession> session =
1989 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
1990
1991 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
1992 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
1993 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
1994 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
1995 }
1996
TEST_P(SpdySessionTest,ConnectionPooledWithTlsChannelId)1997 TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
1998 session_deps_.host_resolver->set_synchronous_mode(true);
1999
2000 MockConnect connect_data(SYNCHRONOUS, OK);
2001
2002 // No actual data will be sent.
2003 MockWrite writes[] = {
2004 MockWrite(ASYNC, 0, 1) // EOF
2005 };
2006
2007 MockRead reads[] = {
2008 MockRead(ASYNC, 0, 0) // EOF
2009 };
2010 DeterministicSocketData data(reads, arraysize(reads),
2011 writes, arraysize(writes));
2012 data.set_connect_data(connect_data);
2013 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2014
2015 // Load a cert that is valid for:
2016 // www.example.org
2017 // mail.example.org
2018 // www.example.com
2019 base::FilePath certs_dir = GetTestCertsDirectory();
2020 scoped_refptr<X509Certificate> test_cert(
2021 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2022 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert);
2023
2024 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2025 ssl.channel_id_sent = true;
2026 ssl.cert = test_cert;
2027 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2028
2029 CreateDeterministicNetworkSession();
2030
2031 base::WeakPtr<SpdySession> session =
2032 CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2033
2034 EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2035 EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2036 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2037 EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2038 }
2039
TEST_P(SpdySessionTest,CloseTwoStalledCreateStream)2040 TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2041 // TODO(rtenneti): Define a helper class/methods and move the common code in
2042 // this file.
2043 MockConnect connect_data(SYNCHRONOUS, OK);
2044
2045 SettingsMap new_settings;
2046 const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2047 const uint32 max_concurrent_streams = 1;
2048 new_settings[kSpdySettingsIds1] =
2049 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2050
2051 scoped_ptr<SpdyFrame> req1(
2052 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2053 scoped_ptr<SpdyFrame> req2(
2054 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
2055 scoped_ptr<SpdyFrame> req3(
2056 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
2057 MockWrite writes[] = {
2058 CreateMockWrite(*req1, 1),
2059 CreateMockWrite(*req2, 4),
2060 CreateMockWrite(*req3, 7),
2061 };
2062
2063 // Set up the socket so we read a SETTINGS frame that sets max concurrent
2064 // streams to 1.
2065 scoped_ptr<SpdyFrame> settings_frame(
2066 spdy_util_.ConstructSpdySettings(new_settings));
2067
2068 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2069 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2070
2071 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2072 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2073
2074 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
2075 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2076
2077 MockRead reads[] = {
2078 CreateMockRead(*settings_frame),
2079 CreateMockRead(*resp1, 2),
2080 CreateMockRead(*body1, 3),
2081 CreateMockRead(*resp2, 5),
2082 CreateMockRead(*body2, 6),
2083 CreateMockRead(*resp3, 8),
2084 CreateMockRead(*body3, 9),
2085 MockRead(ASYNC, 0, 10) // EOF
2086 };
2087
2088 DeterministicSocketData data(reads, arraysize(reads),
2089 writes, arraysize(writes));
2090 data.set_connect_data(connect_data);
2091 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2092
2093 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2094 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2095
2096 CreateDeterministicNetworkSession();
2097
2098 base::WeakPtr<SpdySession> session =
2099 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2100
2101 // Read the settings frame.
2102 data.RunFor(1);
2103
2104 GURL url1("http://www.google.com");
2105 base::WeakPtr<SpdyStream> spdy_stream1 =
2106 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2107 session, url1, LOWEST, BoundNetLog());
2108 ASSERT_TRUE(spdy_stream1.get() != NULL);
2109 EXPECT_EQ(0u, spdy_stream1->stream_id());
2110 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2111 spdy_stream1->SetDelegate(&delegate1);
2112
2113 TestCompletionCallback callback2;
2114 GURL url2("http://www.google.com");
2115 SpdyStreamRequest request2;
2116 ASSERT_EQ(ERR_IO_PENDING,
2117 request2.StartRequest(
2118 SPDY_REQUEST_RESPONSE_STREAM,
2119 session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2120
2121 TestCompletionCallback callback3;
2122 GURL url3("http://www.google.com");
2123 SpdyStreamRequest request3;
2124 ASSERT_EQ(ERR_IO_PENDING,
2125 request3.StartRequest(
2126 SPDY_REQUEST_RESPONSE_STREAM,
2127 session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2128
2129 EXPECT_EQ(0u, session->num_active_streams());
2130 EXPECT_EQ(1u, session->num_created_streams());
2131 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2132
2133 scoped_ptr<SpdyHeaderBlock> headers(
2134 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2135 spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2136 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2137
2138 // Run until 1st stream is activated and then closed.
2139 EXPECT_EQ(0u, delegate1.stream_id());
2140 data.RunFor(3);
2141 EXPECT_EQ(NULL, spdy_stream1.get());
2142 EXPECT_EQ(1u, delegate1.stream_id());
2143
2144 EXPECT_EQ(0u, session->num_active_streams());
2145 EXPECT_EQ(0u, session->num_created_streams());
2146 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2147
2148 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2149 // create the 2nd stream.
2150 base::MessageLoop::current()->RunUntilIdle();
2151
2152 EXPECT_EQ(0u, session->num_active_streams());
2153 EXPECT_EQ(1u, session->num_created_streams());
2154 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2155
2156 base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2157 test::StreamDelegateDoNothing delegate2(stream2);
2158 stream2->SetDelegate(&delegate2);
2159 scoped_ptr<SpdyHeaderBlock> headers2(
2160 spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2161 stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2162 EXPECT_TRUE(stream2->HasUrlFromHeaders());
2163
2164 // Run until 2nd stream is activated and then closed.
2165 EXPECT_EQ(0u, delegate2.stream_id());
2166 data.RunFor(3);
2167 EXPECT_EQ(NULL, stream2.get());
2168 EXPECT_EQ(3u, delegate2.stream_id());
2169
2170 EXPECT_EQ(0u, session->num_active_streams());
2171 EXPECT_EQ(0u, session->num_created_streams());
2172 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2173
2174 // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2175 // create the 3rd stream.
2176 base::MessageLoop::current()->RunUntilIdle();
2177
2178 EXPECT_EQ(0u, session->num_active_streams());
2179 EXPECT_EQ(1u, session->num_created_streams());
2180 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2181
2182 base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2183 test::StreamDelegateDoNothing delegate3(stream3);
2184 stream3->SetDelegate(&delegate3);
2185 scoped_ptr<SpdyHeaderBlock> headers3(
2186 spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2187 stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2188 EXPECT_TRUE(stream3->HasUrlFromHeaders());
2189
2190 // Run until 2nd stream is activated and then closed.
2191 EXPECT_EQ(0u, delegate3.stream_id());
2192 data.RunFor(3);
2193 EXPECT_EQ(NULL, stream3.get());
2194 EXPECT_EQ(5u, delegate3.stream_id());
2195
2196 EXPECT_EQ(0u, session->num_active_streams());
2197 EXPECT_EQ(0u, session->num_created_streams());
2198 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2199
2200 data.RunFor(1);
2201 }
2202
TEST_P(SpdySessionTest,CancelTwoStalledCreateStream)2203 TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2204 session_deps_.host_resolver->set_synchronous_mode(true);
2205
2206 MockRead reads[] = {
2207 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2208 };
2209
2210 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2211 MockConnect connect_data(SYNCHRONOUS, OK);
2212
2213 data.set_connect_data(connect_data);
2214 session_deps_.socket_factory->AddSocketDataProvider(&data);
2215
2216 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2217 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2218
2219 CreateNetworkSession();
2220
2221 base::WeakPtr<SpdySession> session =
2222 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2223
2224 // Leave room for only one more stream to be created.
2225 for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2226 base::WeakPtr<SpdyStream> spdy_stream =
2227 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2228 session, test_url_, MEDIUM, BoundNetLog());
2229 ASSERT_TRUE(spdy_stream != NULL);
2230 }
2231
2232 GURL url1("http://www.google.com");
2233 base::WeakPtr<SpdyStream> spdy_stream1 =
2234 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2235 session, url1, LOWEST, BoundNetLog());
2236 ASSERT_TRUE(spdy_stream1.get() != NULL);
2237 EXPECT_EQ(0u, spdy_stream1->stream_id());
2238
2239 TestCompletionCallback callback2;
2240 GURL url2("http://www.google.com");
2241 SpdyStreamRequest request2;
2242 ASSERT_EQ(ERR_IO_PENDING,
2243 request2.StartRequest(
2244 SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2245 callback2.callback()));
2246
2247 TestCompletionCallback callback3;
2248 GURL url3("http://www.google.com");
2249 SpdyStreamRequest request3;
2250 ASSERT_EQ(ERR_IO_PENDING,
2251 request3.StartRequest(
2252 SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2253 callback3.callback()));
2254
2255 EXPECT_EQ(0u, session->num_active_streams());
2256 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2257 EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2258
2259 // Cancel the first stream; this will allow the second stream to be created.
2260 EXPECT_TRUE(spdy_stream1.get() != NULL);
2261 spdy_stream1->Cancel();
2262 EXPECT_EQ(NULL, spdy_stream1.get());
2263
2264 EXPECT_EQ(OK, callback2.WaitForResult());
2265 EXPECT_EQ(0u, session->num_active_streams());
2266 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2267 EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2268
2269 // Cancel the second stream; this will allow the third stream to be created.
2270 base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2271 spdy_stream2->Cancel();
2272 EXPECT_EQ(NULL, spdy_stream2.get());
2273
2274 EXPECT_EQ(OK, callback3.WaitForResult());
2275 EXPECT_EQ(0u, session->num_active_streams());
2276 EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2277 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2278
2279 // Cancel the third stream.
2280 base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2281 spdy_stream3->Cancel();
2282 EXPECT_EQ(NULL, spdy_stream3.get());
2283 EXPECT_EQ(0u, session->num_active_streams());
2284 EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
2285 EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2286 }
2287
2288 // Test that SpdySession::DoReadLoop reads data from the socket
2289 // without yielding. This test makes 32k - 1 bytes of data available
2290 // on the socket for reading. It then verifies that it has read all
2291 // the available data without yielding.
TEST_P(SpdySessionTest,ReadDataWithoutYielding)2292 TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2293 MockConnect connect_data(SYNCHRONOUS, OK);
2294 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2295
2296 scoped_ptr<SpdyFrame> req1(
2297 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2298 MockWrite writes[] = {
2299 CreateMockWrite(*req1, 0),
2300 };
2301
2302 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2303 // (-spdy_data_frame_size).
2304 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2305 const int kPayloadSize =
2306 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2307 TestDataStream test_stream;
2308 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2309 char* payload_data = payload->data();
2310 test_stream.GetBytes(payload_data, kPayloadSize);
2311
2312 scoped_ptr<SpdyFrame> partial_data_frame(
2313 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2314 scoped_ptr<SpdyFrame> finish_data_frame(
2315 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2316
2317 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2318
2319 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2320 // bytes.
2321 MockRead reads[] = {
2322 CreateMockRead(*resp1, 1),
2323 CreateMockRead(*partial_data_frame, 2),
2324 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2325 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2326 CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2327 MockRead(ASYNC, 0, 6) // EOF
2328 };
2329
2330 // Create SpdySession and SpdyStream and send the request.
2331 DeterministicSocketData data(reads, arraysize(reads),
2332 writes, arraysize(writes));
2333 data.set_connect_data(connect_data);
2334 session_deps_.host_resolver->set_synchronous_mode(true);
2335 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2336
2337 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2338 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2339
2340 CreateDeterministicNetworkSession();
2341
2342 base::WeakPtr<SpdySession> session =
2343 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2344
2345 GURL url1("http://www.google.com");
2346 base::WeakPtr<SpdyStream> spdy_stream1 =
2347 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2348 session, url1, MEDIUM, BoundNetLog());
2349 ASSERT_TRUE(spdy_stream1.get() != NULL);
2350 EXPECT_EQ(0u, spdy_stream1->stream_id());
2351 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2352 spdy_stream1->SetDelegate(&delegate1);
2353
2354 scoped_ptr<SpdyHeaderBlock> headers1(
2355 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2356 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2357 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2358
2359 // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2360 // post a task.
2361 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2362
2363 // Run until 1st read.
2364 EXPECT_EQ(0u, delegate1.stream_id());
2365 data.RunFor(2);
2366 EXPECT_EQ(1u, delegate1.stream_id());
2367 EXPECT_EQ(0u, observer.executed_count());
2368
2369 // Read all the data and verify SpdySession::DoReadLoop has not
2370 // posted a task.
2371 data.RunFor(4);
2372 EXPECT_EQ(NULL, spdy_stream1.get());
2373
2374 // Verify task observer's executed_count is zero, which indicates DoRead read
2375 // all the available data.
2376 EXPECT_EQ(0u, observer.executed_count());
2377 EXPECT_TRUE(data.at_write_eof());
2378 EXPECT_TRUE(data.at_read_eof());
2379 }
2380
2381 // Test that SpdySession::DoReadLoop yields while reading the
2382 // data. This test makes 32k + 1 bytes of data available on the socket
2383 // for reading. It then verifies that DoRead has yielded even though
2384 // there is data available for it to read (i.e, socket()->Read didn't
2385 // return ERR_IO_PENDING during socket reads).
TEST_P(SpdySessionTest,TestYieldingDuringReadData)2386 TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2387 MockConnect connect_data(SYNCHRONOUS, OK);
2388 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2389
2390 scoped_ptr<SpdyFrame> req1(
2391 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2392 MockWrite writes[] = {
2393 CreateMockWrite(*req1, 0),
2394 };
2395
2396 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2397 // (-spdy_data_frame_size).
2398 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2399 const int kPayloadSize =
2400 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2401 TestDataStream test_stream;
2402 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2403 char* payload_data = payload->data();
2404 test_stream.GetBytes(payload_data, kPayloadSize);
2405
2406 scoped_ptr<SpdyFrame> partial_data_frame(
2407 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2408 scoped_ptr<SpdyFrame> finish_data_frame(
2409 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2410
2411 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2412
2413 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2414 MockRead reads[] = {
2415 CreateMockRead(*resp1, 1),
2416 CreateMockRead(*partial_data_frame, 2),
2417 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2418 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2419 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2420 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2421 MockRead(ASYNC, 0, 7) // EOF
2422 };
2423
2424 // Create SpdySession and SpdyStream and send the request.
2425 DeterministicSocketData data(reads, arraysize(reads),
2426 writes, arraysize(writes));
2427 data.set_connect_data(connect_data);
2428 session_deps_.host_resolver->set_synchronous_mode(true);
2429 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2430
2431 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2432 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2433
2434 CreateDeterministicNetworkSession();
2435
2436 base::WeakPtr<SpdySession> session =
2437 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2438
2439 GURL url1("http://www.google.com");
2440 base::WeakPtr<SpdyStream> spdy_stream1 =
2441 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2442 session, url1, MEDIUM, BoundNetLog());
2443 ASSERT_TRUE(spdy_stream1.get() != NULL);
2444 EXPECT_EQ(0u, spdy_stream1->stream_id());
2445 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2446 spdy_stream1->SetDelegate(&delegate1);
2447
2448 scoped_ptr<SpdyHeaderBlock> headers1(
2449 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2450 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2451 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2452
2453 // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2454 // task.
2455 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2456
2457 // Run until 1st read.
2458 EXPECT_EQ(0u, delegate1.stream_id());
2459 data.RunFor(2);
2460 EXPECT_EQ(1u, delegate1.stream_id());
2461 EXPECT_EQ(0u, observer.executed_count());
2462
2463 // Read all the data and verify SpdySession::DoReadLoop has posted a
2464 // task.
2465 data.RunFor(6);
2466 EXPECT_EQ(NULL, spdy_stream1.get());
2467
2468 // Verify task observer's executed_count is 1, which indicates DoRead has
2469 // posted only one task and thus yielded though there is data available for it
2470 // to read.
2471 EXPECT_EQ(1u, observer.executed_count());
2472 EXPECT_TRUE(data.at_write_eof());
2473 EXPECT_TRUE(data.at_read_eof());
2474 }
2475
2476 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2477 // + async, by doing the following MockReads.
2478 //
2479 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2480 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2481 //
2482 // The above reads 26K synchronously. Since that is less that 32K, we
2483 // will attempt to read again. However, that DoRead() will return
2484 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2485 // yield. When we come back, DoRead() will read the results from the
2486 // async read, and rest of the data synchronously.
TEST_P(SpdySessionTest,TestYieldingDuringAsyncReadData)2487 TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2488 MockConnect connect_data(SYNCHRONOUS, OK);
2489 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2490
2491 scoped_ptr<SpdyFrame> req1(
2492 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2493 MockWrite writes[] = {
2494 CreateMockWrite(*req1, 0),
2495 };
2496
2497 // Build buffer of size kMaxReadBytesWithoutYielding / 4
2498 // (-spdy_data_frame_size).
2499 ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2500 TestDataStream test_stream;
2501 const int kEightKPayloadSize =
2502 kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2503 scoped_refptr<net::IOBuffer> eightk_payload(
2504 new net::IOBuffer(kEightKPayloadSize));
2505 char* eightk_payload_data = eightk_payload->data();
2506 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2507
2508 // Build buffer of 2k size.
2509 TestDataStream test_stream2;
2510 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2511 scoped_refptr<net::IOBuffer> twok_payload(
2512 new net::IOBuffer(kTwoKPayloadSize));
2513 char* twok_payload_data = twok_payload->data();
2514 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2515
2516 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2517 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2518 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2519 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2520 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2521 1, "h", 1, DATA_FLAG_FIN));
2522
2523 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2524
2525 MockRead reads[] = {
2526 CreateMockRead(*resp1, 1),
2527 CreateMockRead(*eightk_data_frame, 2),
2528 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
2529 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2530 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
2531 CreateMockRead(*eightk_data_frame, 6, ASYNC),
2532 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
2533 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2534 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2535 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
2536 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
2537 MockRead(ASYNC, 0, 12) // EOF
2538 };
2539
2540 // Create SpdySession and SpdyStream and send the request.
2541 DeterministicSocketData data(reads, arraysize(reads),
2542 writes, arraysize(writes));
2543 data.set_connect_data(connect_data);
2544 session_deps_.host_resolver->set_synchronous_mode(true);
2545 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2546
2547 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2548 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2549
2550 CreateDeterministicNetworkSession();
2551
2552 base::WeakPtr<SpdySession> session =
2553 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2554
2555 GURL url1("http://www.google.com");
2556 base::WeakPtr<SpdyStream> spdy_stream1 =
2557 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2558 session, url1, MEDIUM, BoundNetLog());
2559 ASSERT_TRUE(spdy_stream1.get() != NULL);
2560 EXPECT_EQ(0u, spdy_stream1->stream_id());
2561 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2562 spdy_stream1->SetDelegate(&delegate1);
2563
2564 scoped_ptr<SpdyHeaderBlock> headers1(
2565 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2566 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2567 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2568
2569 // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2570 // posting of tasks.
2571 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2572
2573 // Run until 1st read.
2574 EXPECT_EQ(0u, delegate1.stream_id());
2575 data.RunFor(2);
2576 EXPECT_EQ(1u, delegate1.stream_id());
2577 EXPECT_EQ(0u, observer.executed_count());
2578
2579 // Read all the data and verify SpdySession::DoReadLoop has posted a
2580 // task.
2581 data.RunFor(12);
2582 EXPECT_EQ(NULL, spdy_stream1.get());
2583
2584 // Verify task observer's executed_count is 1, which indicates DoRead has
2585 // posted only one task and thus yielded though there is data available for
2586 // it to read.
2587 EXPECT_EQ(1u, observer.executed_count());
2588 EXPECT_TRUE(data.at_write_eof());
2589 EXPECT_TRUE(data.at_read_eof());
2590 }
2591
2592 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2593 // nothing blows up.
TEST_P(SpdySessionTest,GoAwayWhileInDoReadLoop)2594 TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
2595 MockConnect connect_data(SYNCHRONOUS, OK);
2596 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2597
2598 scoped_ptr<SpdyFrame> req1(
2599 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2600 MockWrite writes[] = {
2601 CreateMockWrite(*req1, 0),
2602 };
2603
2604 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2605 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2606 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
2607
2608 MockRead reads[] = {
2609 CreateMockRead(*resp1, 1),
2610 CreateMockRead(*body1, 2),
2611 CreateMockRead(*goaway, 3),
2612 };
2613
2614 // Create SpdySession and SpdyStream and send the request.
2615 DeterministicSocketData data(reads, arraysize(reads),
2616 writes, arraysize(writes));
2617 data.set_connect_data(connect_data);
2618 session_deps_.host_resolver->set_synchronous_mode(true);
2619 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2620
2621 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2622 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2623
2624 CreateDeterministicNetworkSession();
2625
2626 base::WeakPtr<SpdySession> session =
2627 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2628
2629 GURL url1("http://www.google.com");
2630 base::WeakPtr<SpdyStream> spdy_stream1 =
2631 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2632 session, url1, MEDIUM, BoundNetLog());
2633 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2634 spdy_stream1->SetDelegate(&delegate1);
2635 ASSERT_TRUE(spdy_stream1.get() != NULL);
2636 EXPECT_EQ(0u, spdy_stream1->stream_id());
2637
2638 scoped_ptr<SpdyHeaderBlock> headers1(
2639 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2640 spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2641 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2642
2643 // Run until 1st read.
2644 EXPECT_EQ(0u, spdy_stream1->stream_id());
2645 data.RunFor(1);
2646 EXPECT_EQ(1u, spdy_stream1->stream_id());
2647
2648 // Run until GoAway.
2649 data.RunFor(3);
2650 EXPECT_EQ(NULL, spdy_stream1.get());
2651 EXPECT_TRUE(data.at_write_eof());
2652 EXPECT_TRUE(data.at_read_eof());
2653 EXPECT_TRUE(session == NULL);
2654 }
2655
2656 // Within this framework, a SpdySession should be initialized with
2657 // flow control disabled for protocol version 2, with flow control
2658 // enabled only for streams for protocol version 3, and with flow
2659 // control enabled for streams and sessions for higher versions.
TEST_P(SpdySessionTest,ProtocolNegotiation)2660 TEST_P(SpdySessionTest, ProtocolNegotiation) {
2661 session_deps_.host_resolver->set_synchronous_mode(true);
2662
2663 MockConnect connect_data(SYNCHRONOUS, OK);
2664 MockRead reads[] = {
2665 MockRead(SYNCHRONOUS, 0, 0) // EOF
2666 };
2667 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2668 data.set_connect_data(connect_data);
2669 session_deps_.socket_factory->AddSocketDataProvider(&data);
2670
2671 CreateNetworkSession();
2672 base::WeakPtr<SpdySession> session =
2673 CreateFakeSpdySession(spdy_session_pool_, key_);
2674
2675 EXPECT_EQ(spdy_util_.spdy_version(),
2676 session->buffered_spdy_framer_->protocol_version());
2677 if (GetParam() == kProtoDeprecatedSPDY2) {
2678 EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state());
2679 EXPECT_EQ(0, session->session_send_window_size_);
2680 EXPECT_EQ(0, session->session_recv_window_size_);
2681 } else if (GetParam() == kProtoSPDY3) {
2682 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
2683 EXPECT_EQ(0, session->session_send_window_size_);
2684 EXPECT_EQ(0, session->session_recv_window_size_);
2685 } else {
2686 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
2687 session->flow_control_state());
2688 EXPECT_EQ(kSpdySessionInitialWindowSize,
2689 session->session_send_window_size_);
2690 EXPECT_EQ(kSpdySessionInitialWindowSize,
2691 session->session_recv_window_size_);
2692 }
2693 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2694 }
2695
2696 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2697 // pointers to the idle session are currently held.
TEST_P(SpdySessionTest,CloseOneIdleConnection)2698 TEST_P(SpdySessionTest, CloseOneIdleConnection) {
2699 ClientSocketPoolManager::set_max_sockets_per_group(
2700 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2701 ClientSocketPoolManager::set_max_sockets_per_pool(
2702 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2703
2704 MockConnect connect_data(SYNCHRONOUS, OK);
2705 MockRead reads[] = {
2706 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2707 };
2708 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2709 data.set_connect_data(connect_data);
2710 session_deps_.socket_factory->AddSocketDataProvider(&data);
2711 session_deps_.socket_factory->AddSocketDataProvider(&data);
2712
2713 CreateNetworkSession();
2714
2715 TransportClientSocketPool* pool =
2716 http_session_->GetTransportSocketPool(
2717 HttpNetworkSession::NORMAL_SOCKET_POOL);
2718
2719 // Create an idle SPDY session.
2720 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2721 kPrivacyModeDisabled);
2722 base::WeakPtr<SpdySession> session1 =
2723 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2724 EXPECT_FALSE(pool->IsStalled());
2725
2726 // Trying to create a new connection should cause the pool to be stalled, and
2727 // post a task asynchronously to try and close the session.
2728 TestCompletionCallback callback2;
2729 HostPortPair host_port2("2.com", 80);
2730 scoped_refptr<TransportSocketParams> params2(
2731 new TransportSocketParams(host_port2, false, false,
2732 OnHostResolutionCallback()));
2733 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
2734 EXPECT_EQ(ERR_IO_PENDING,
2735 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
2736 callback2.callback(), pool, BoundNetLog()));
2737 EXPECT_TRUE(pool->IsStalled());
2738
2739 // The socket pool should close the connection asynchronously and establish a
2740 // new connection.
2741 EXPECT_EQ(OK, callback2.WaitForResult());
2742 EXPECT_FALSE(pool->IsStalled());
2743 EXPECT_TRUE(session1 == NULL);
2744 }
2745
2746 // Tests the case of a non-SPDY request closing an idle SPDY session when no
2747 // pointers to the idle session are currently held, in the case the SPDY session
2748 // has an alias.
TEST_P(SpdySessionTest,CloseOneIdleConnectionWithAlias)2749 TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
2750 ClientSocketPoolManager::set_max_sockets_per_group(
2751 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2752 ClientSocketPoolManager::set_max_sockets_per_pool(
2753 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2754
2755 MockConnect connect_data(SYNCHRONOUS, OK);
2756 MockRead reads[] = {
2757 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2758 };
2759 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2760 data.set_connect_data(connect_data);
2761 session_deps_.socket_factory->AddSocketDataProvider(&data);
2762 session_deps_.socket_factory->AddSocketDataProvider(&data);
2763
2764 session_deps_.host_resolver->set_synchronous_mode(true);
2765 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2766 "1.com", "192.168.0.2", std::string());
2767 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2768 "2.com", "192.168.0.2", std::string());
2769 // Not strictly needed.
2770 session_deps_.host_resolver->rules()->AddIPLiteralRule(
2771 "3.com", "192.168.0.3", std::string());
2772
2773 CreateNetworkSession();
2774
2775 TransportClientSocketPool* pool =
2776 http_session_->GetTransportSocketPool(
2777 HttpNetworkSession::NORMAL_SOCKET_POOL);
2778
2779 // Create an idle SPDY session.
2780 SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2781 kPrivacyModeDisabled);
2782 base::WeakPtr<SpdySession> session1 =
2783 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2784 EXPECT_FALSE(pool->IsStalled());
2785
2786 // Set up an alias for the idle SPDY session, increasing its ref count to 2.
2787 SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
2788 kPrivacyModeDisabled);
2789 HostResolver::RequestInfo info(key2.host_port_pair());
2790 AddressList addresses;
2791 // Pre-populate the DNS cache, since a synchronous resolution is required in
2792 // order to create the alias.
2793 session_deps_.host_resolver->Resolve(info,
2794 DEFAULT_PRIORITY,
2795 &addresses,
2796 CompletionCallback(),
2797 NULL,
2798 BoundNetLog());
2799 // Get a session for |key2|, which should return the session created earlier.
2800 base::WeakPtr<SpdySession> session2 =
2801 spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
2802 ASSERT_EQ(session1.get(), session2.get());
2803 EXPECT_FALSE(pool->IsStalled());
2804
2805 // Trying to create a new connection should cause the pool to be stalled, and
2806 // post a task asynchronously to try and close the session.
2807 TestCompletionCallback callback3;
2808 HostPortPair host_port3("3.com", 80);
2809 scoped_refptr<TransportSocketParams> params3(
2810 new TransportSocketParams(host_port3, false, false,
2811 OnHostResolutionCallback()));
2812 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
2813 EXPECT_EQ(ERR_IO_PENDING,
2814 connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
2815 callback3.callback(), pool, BoundNetLog()));
2816 EXPECT_TRUE(pool->IsStalled());
2817
2818 // The socket pool should close the connection asynchronously and establish a
2819 // new connection.
2820 EXPECT_EQ(OK, callback3.WaitForResult());
2821 EXPECT_FALSE(pool->IsStalled());
2822 EXPECT_TRUE(session1 == NULL);
2823 EXPECT_TRUE(session2 == NULL);
2824 }
2825
2826 // Tests that when a SPDY session becomes idle, it closes itself if there is
2827 // a lower layer pool stalled on the per-pool socket limit.
TEST_P(SpdySessionTest,CloseSessionOnIdleWhenPoolStalled)2828 TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
2829 ClientSocketPoolManager::set_max_sockets_per_group(
2830 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2831 ClientSocketPoolManager::set_max_sockets_per_pool(
2832 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2833
2834 MockConnect connect_data(SYNCHRONOUS, OK);
2835 MockRead reads[] = {
2836 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2837 };
2838 scoped_ptr<SpdyFrame> req1(
2839 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2840 scoped_ptr<SpdyFrame> cancel1(
2841 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2842 MockWrite writes[] = {
2843 CreateMockWrite(*req1, 1),
2844 CreateMockWrite(*cancel1, 1),
2845 };
2846 StaticSocketDataProvider data(reads, arraysize(reads),
2847 writes, arraysize(writes));
2848 data.set_connect_data(connect_data);
2849 session_deps_.socket_factory->AddSocketDataProvider(&data);
2850
2851 MockRead http_reads[] = {
2852 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
2853 };
2854 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
2855 NULL, 0);
2856 http_data.set_connect_data(connect_data);
2857 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
2858
2859
2860 CreateNetworkSession();
2861
2862 TransportClientSocketPool* pool =
2863 http_session_->GetTransportSocketPool(
2864 HttpNetworkSession::NORMAL_SOCKET_POOL);
2865
2866 // Create a SPDY session.
2867 GURL url1("http://www.google.com");
2868 SpdySessionKey key1(HostPortPair(url1.host(), 80),
2869 ProxyServer::Direct(), kPrivacyModeDisabled);
2870 base::WeakPtr<SpdySession> session1 =
2871 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2872 EXPECT_FALSE(pool->IsStalled());
2873
2874 // Create a stream using the session, and send a request.
2875
2876 TestCompletionCallback callback1;
2877 base::WeakPtr<SpdyStream> spdy_stream1 =
2878 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2879 session1, url1, DEFAULT_PRIORITY,
2880 BoundNetLog());
2881 ASSERT_TRUE(spdy_stream1.get());
2882 test::StreamDelegateDoNothing delegate1(spdy_stream1);
2883 spdy_stream1->SetDelegate(&delegate1);
2884
2885 scoped_ptr<SpdyHeaderBlock> headers1(
2886 spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2887 EXPECT_EQ(ERR_IO_PENDING,
2888 spdy_stream1->SendRequestHeaders(
2889 headers1.Pass(), NO_MORE_DATA_TO_SEND));
2890 EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2891
2892 base::MessageLoop::current()->RunUntilIdle();
2893
2894 // Trying to create a new connection should cause the pool to be stalled, and
2895 // post a task asynchronously to try and close the session.
2896 TestCompletionCallback callback2;
2897 HostPortPair host_port2("2.com", 80);
2898 scoped_refptr<TransportSocketParams> params2(
2899 new TransportSocketParams(host_port2, false, false,
2900 OnHostResolutionCallback()));
2901 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
2902 EXPECT_EQ(ERR_IO_PENDING,
2903 connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
2904 callback2.callback(), pool, BoundNetLog()));
2905 EXPECT_TRUE(pool->IsStalled());
2906
2907 // Running the message loop should cause the socket pool to ask the SPDY
2908 // session to close an idle socket, but since the socket is in use, nothing
2909 // happens.
2910 base::RunLoop().RunUntilIdle();
2911 EXPECT_TRUE(pool->IsStalled());
2912 EXPECT_FALSE(callback2.have_result());
2913
2914 // Cancelling the request should result in the session's socket being
2915 // closed, since the pool is stalled.
2916 ASSERT_TRUE(spdy_stream1.get());
2917 spdy_stream1->Cancel();
2918 base::RunLoop().RunUntilIdle();
2919 ASSERT_FALSE(pool->IsStalled());
2920 EXPECT_EQ(OK, callback2.WaitForResult());
2921 }
2922
2923 // Verify that SpdySessionKey and therefore SpdySession is different when
2924 // privacy mode is enabled or disabled.
TEST_P(SpdySessionTest,SpdySessionKeyPrivacyMode)2925 TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
2926 CreateDeterministicNetworkSession();
2927
2928 HostPortPair host_port_pair("www.google.com", 443);
2929 SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
2930 kPrivacyModeEnabled);
2931 SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
2932 kPrivacyModeDisabled);
2933
2934 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
2935 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2936
2937 // Add SpdySession with PrivacyMode Enabled to the pool.
2938 base::WeakPtr<SpdySession> session_privacy_enabled =
2939 CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
2940
2941 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
2942 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2943
2944 // Add SpdySession with PrivacyMode Disabled to the pool.
2945 base::WeakPtr<SpdySession> session_privacy_disabled =
2946 CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
2947
2948 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
2949 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2950
2951 session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
2952 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
2953 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2954
2955 session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
2956 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
2957 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2958 }
2959
2960 // Delegate that creates another stream when its stream is closed.
2961 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
2962 public:
StreamCreatingDelegate(const base::WeakPtr<SpdyStream> & stream,const base::WeakPtr<SpdySession> & session)2963 StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
2964 const base::WeakPtr<SpdySession>& session)
2965 : StreamDelegateDoNothing(stream),
2966 session_(session) {}
2967
~StreamCreatingDelegate()2968 virtual ~StreamCreatingDelegate() {}
2969
OnClose(int status)2970 virtual void OnClose(int status) OVERRIDE {
2971 GURL url("http://www.google.com");
2972 ignore_result(
2973 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2974 session_, url, MEDIUM, BoundNetLog()));
2975 }
2976
2977 private:
2978 const base::WeakPtr<SpdySession> session_;
2979 };
2980
2981 // Create another stream in response to a stream being reset. Nothing
2982 // should blow up. This is a regression test for
2983 // http://crbug.com/263690 .
TEST_P(SpdySessionTest,CreateStreamOnStreamReset)2984 TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
2985 session_deps_.host_resolver->set_synchronous_mode(true);
2986
2987 MockConnect connect_data(SYNCHRONOUS, OK);
2988
2989 scoped_ptr<SpdyFrame> req(
2990 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2991 MockWrite writes[] = {
2992 CreateMockWrite(*req, 0),
2993 };
2994
2995 scoped_ptr<SpdyFrame> rst(
2996 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
2997 MockRead reads[] = {
2998 CreateMockRead(*rst, 1),
2999 MockRead(ASYNC, 0, 2) // EOF
3000 };
3001 DeterministicSocketData data(reads, arraysize(reads),
3002 writes, arraysize(writes));
3003 data.set_connect_data(connect_data);
3004 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3005
3006 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
3007 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3008
3009 CreateDeterministicNetworkSession();
3010
3011 base::WeakPtr<SpdySession> session =
3012 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3013
3014 GURL url("http://www.google.com");
3015 base::WeakPtr<SpdyStream> spdy_stream =
3016 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3017 session, url, MEDIUM, BoundNetLog());
3018 ASSERT_TRUE(spdy_stream.get() != NULL);
3019 EXPECT_EQ(0u, spdy_stream->stream_id());
3020
3021 StreamCreatingDelegate delegate(spdy_stream, session);
3022 spdy_stream->SetDelegate(&delegate);
3023
3024 scoped_ptr<SpdyHeaderBlock> headers(
3025 spdy_util_.ConstructGetHeaderBlock(url.spec()));
3026 spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3027 EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3028
3029 EXPECT_EQ(0u, spdy_stream->stream_id());
3030
3031 data.RunFor(1);
3032
3033 EXPECT_EQ(1u, spdy_stream->stream_id());
3034
3035 // Cause the stream to be reset, which should cause another stream
3036 // to be created.
3037 data.RunFor(1);
3038
3039 EXPECT_EQ(NULL, spdy_stream.get());
3040 EXPECT_TRUE(delegate.StreamIsClosed());
3041 EXPECT_EQ(0u, session->num_active_streams());
3042 EXPECT_EQ(1u, session->num_created_streams());
3043 }
3044
3045 // The tests below are only for SPDY/3 and above.
3046
TEST_P(SpdySessionTest,UpdateStreamsSendWindowSize)3047 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3048 if (GetParam() < kProtoSPDY3)
3049 return;
3050
3051 // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3052 // gets sent.
3053 SettingsMap new_settings;
3054 int32 window_size = 1;
3055 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3056 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3057
3058 // Set up the socket so we read a SETTINGS frame that sets
3059 // INITIAL_WINDOW_SIZE.
3060 MockConnect connect_data(SYNCHRONOUS, OK);
3061 scoped_ptr<SpdyFrame> settings_frame(
3062 spdy_util_.ConstructSpdySettings(new_settings));
3063 MockRead reads[] = {
3064 CreateMockRead(*settings_frame, 0),
3065 MockRead(ASYNC, 0, 1) // EOF
3066 };
3067
3068 session_deps_.host_resolver->set_synchronous_mode(true);
3069
3070 scoped_ptr<DeterministicSocketData> data(
3071 new DeterministicSocketData(reads, arraysize(reads), NULL, 0));
3072 data->set_connect_data(connect_data);
3073 session_deps_.deterministic_socket_factory->AddSocketDataProvider(data.get());
3074
3075 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
3076 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3077
3078 CreateDeterministicNetworkSession();
3079
3080 base::WeakPtr<SpdySession> session =
3081 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3082 base::WeakPtr<SpdyStream> spdy_stream1 =
3083 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3084 session, test_url_, MEDIUM, BoundNetLog());
3085 ASSERT_TRUE(spdy_stream1.get() != NULL);
3086 TestCompletionCallback callback1;
3087 EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3088
3089 data->RunFor(1); // Process the SETTINGS frame, but not the EOF
3090 base::MessageLoop::current()->RunUntilIdle();
3091 EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3092 EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3093
3094 // Release the first one, this will allow the second to be created.
3095 spdy_stream1->Cancel();
3096 EXPECT_EQ(NULL, spdy_stream1.get());
3097
3098 base::WeakPtr<SpdyStream> spdy_stream2 =
3099 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3100 session, test_url_, MEDIUM, BoundNetLog());
3101 ASSERT_TRUE(spdy_stream2.get() != NULL);
3102 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3103 spdy_stream2->Cancel();
3104 EXPECT_EQ(NULL, spdy_stream2.get());
3105 }
3106
3107 // The tests below are only for SPDY/3.1 and above.
3108
3109 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3110 // adjust the session receive window size for SPDY 3.1 and higher. In
3111 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3112 // sending a WINDOW_UPDATE frame for a large enough delta.
TEST_P(SpdySessionTest,AdjustRecvWindowSize)3113 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3114 if (GetParam() < kProtoSPDY31)
3115 return;
3116
3117 session_deps_.host_resolver->set_synchronous_mode(true);
3118
3119 const int32 delta_window_size = 100;
3120
3121 MockConnect connect_data(SYNCHRONOUS, OK);
3122 MockRead reads[] = {
3123 MockRead(ASYNC, 0, 1) // EOF
3124 };
3125 scoped_ptr<SpdyFrame> window_update(
3126 spdy_util_.ConstructSpdyWindowUpdate(
3127 kSessionFlowControlStreamId,
3128 kSpdySessionInitialWindowSize + delta_window_size));
3129 MockWrite writes[] = {
3130 CreateMockWrite(*window_update, 0),
3131 };
3132 DeterministicSocketData data(reads, arraysize(reads),
3133 writes, arraysize(writes));
3134 data.set_connect_data(connect_data);
3135 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3136
3137 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
3138 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3139
3140 CreateDeterministicNetworkSession();
3141 base::WeakPtr<SpdySession> session =
3142 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3143 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3144 session->flow_control_state());
3145
3146 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3147 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3148
3149 session->IncreaseRecvWindowSize(delta_window_size);
3150 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3151 session->session_recv_window_size_);
3152 EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3153
3154 // Should trigger sending a WINDOW_UPDATE frame.
3155 session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize);
3156 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size +
3157 kSpdySessionInitialWindowSize,
3158 session->session_recv_window_size_);
3159 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3160
3161 data.RunFor(1);
3162
3163 // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3164 session->in_io_loop_ = true;
3165 session->DecreaseRecvWindowSize(
3166 kSpdySessionInitialWindowSize + delta_window_size +
3167 kSpdySessionInitialWindowSize);
3168 session->in_io_loop_ = false;
3169 EXPECT_EQ(0, session->session_recv_window_size_);
3170 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3171 }
3172
3173 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3174 // adjust the session send window size when the "enable_spdy_31" flag
3175 // is set.
TEST_P(SpdySessionTest,AdjustSendWindowSize)3176 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3177 if (GetParam() < kProtoSPDY31)
3178 return;
3179
3180 session_deps_.host_resolver->set_synchronous_mode(true);
3181
3182 MockConnect connect_data(SYNCHRONOUS, OK);
3183 MockRead reads[] = {
3184 MockRead(SYNCHRONOUS, 0, 0) // EOF
3185 };
3186 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3187 data.set_connect_data(connect_data);
3188 session_deps_.socket_factory->AddSocketDataProvider(&data);
3189
3190 CreateNetworkSession();
3191 base::WeakPtr<SpdySession> session =
3192 CreateFakeSpdySession(spdy_session_pool_, key_);
3193 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3194 session->flow_control_state());
3195
3196 const int32 delta_window_size = 100;
3197
3198 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3199
3200 session->IncreaseSendWindowSize(delta_window_size);
3201 EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3202 session->session_send_window_size_);
3203
3204 session->DecreaseSendWindowSize(delta_window_size);
3205 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3206 }
3207
3208 // Incoming data for an inactive stream should not cause the session
3209 // receive window size to decrease, but it should cause the unacked
3210 // bytes to increase.
TEST_P(SpdySessionTest,SessionFlowControlInactiveStream)3211 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3212 if (GetParam() < kProtoSPDY31)
3213 return;
3214
3215 session_deps_.host_resolver->set_synchronous_mode(true);
3216
3217 MockConnect connect_data(SYNCHRONOUS, OK);
3218 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3219 MockRead reads[] = {
3220 CreateMockRead(*resp, 0),
3221 MockRead(ASYNC, 0, 1) // EOF
3222 };
3223 DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3224 data.set_connect_data(connect_data);
3225 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3226
3227 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
3228 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3229
3230 CreateDeterministicNetworkSession();
3231 base::WeakPtr<SpdySession> session =
3232 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3233 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3234 session->flow_control_state());
3235
3236 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3237 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3238
3239 data.RunFor(1);
3240
3241 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3242 EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3243
3244 data.RunFor(1);
3245 }
3246
3247 // A delegate that drops any received data.
3248 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3249 public:
DropReceivedDataDelegate(const base::WeakPtr<SpdyStream> & stream,base::StringPiece data)3250 DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3251 base::StringPiece data)
3252 : StreamDelegateSendImmediate(stream, data) {}
3253
~DropReceivedDataDelegate()3254 virtual ~DropReceivedDataDelegate() {}
3255
3256 // Drop any received data.
OnDataReceived(scoped_ptr<SpdyBuffer> buffer)3257 virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) OVERRIDE {}
3258 };
3259
3260 // Send data back and forth but use a delegate that drops its received
3261 // data. The receive window should still increase to its original
3262 // value, i.e. we shouldn't "leak" receive window bytes.
TEST_P(SpdySessionTest,SessionFlowControlNoReceiveLeaks)3263 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3264 if (GetParam() < kProtoSPDY31)
3265 return;
3266
3267 const char kStreamUrl[] = "http://www.google.com/";
3268
3269 const int32 msg_data_size = 100;
3270 const std::string msg_data(msg_data_size, 'a');
3271
3272 MockConnect connect_data(SYNCHRONOUS, OK);
3273
3274 scoped_ptr<SpdyFrame> req(
3275 spdy_util_.ConstructSpdyPost(
3276 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3277 scoped_ptr<SpdyFrame> msg(
3278 spdy_util_.ConstructSpdyBodyFrame(
3279 1, msg_data.data(), msg_data_size, false));
3280 MockWrite writes[] = {
3281 CreateMockWrite(*req, 0),
3282 CreateMockWrite(*msg, 2),
3283 };
3284
3285 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3286 scoped_ptr<SpdyFrame> echo(
3287 spdy_util_.ConstructSpdyBodyFrame(
3288 1, msg_data.data(), msg_data_size, false));
3289 scoped_ptr<SpdyFrame> window_update(
3290 spdy_util_.ConstructSpdyWindowUpdate(
3291 kSessionFlowControlStreamId, msg_data_size));
3292 MockRead reads[] = {
3293 CreateMockRead(*resp, 1),
3294 CreateMockRead(*echo, 3),
3295 MockRead(ASYNC, 0, 4) // EOF
3296 };
3297
3298 // Create SpdySession and SpdyStream and send the request.
3299 DeterministicSocketData data(reads, arraysize(reads),
3300 writes, arraysize(writes));
3301 data.set_connect_data(connect_data);
3302 session_deps_.host_resolver->set_synchronous_mode(true);
3303 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3304
3305 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
3306 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3307
3308 CreateDeterministicNetworkSession();
3309
3310 base::WeakPtr<SpdySession> session =
3311 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3312
3313 GURL url(kStreamUrl);
3314 base::WeakPtr<SpdyStream> stream =
3315 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3316 session, url, MEDIUM, BoundNetLog());
3317 ASSERT_TRUE(stream.get() != NULL);
3318 EXPECT_EQ(0u, stream->stream_id());
3319
3320 DropReceivedDataDelegate delegate(stream, msg_data);
3321 stream->SetDelegate(&delegate);
3322
3323 scoped_ptr<SpdyHeaderBlock> headers(
3324 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3325 EXPECT_EQ(ERR_IO_PENDING,
3326 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3327 EXPECT_TRUE(stream->HasUrlFromHeaders());
3328
3329 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3330 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3331
3332 data.RunFor(4);
3333
3334 EXPECT_TRUE(data.at_write_eof());
3335 EXPECT_TRUE(data.at_read_eof());
3336
3337 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3338 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3339
3340 stream->Close();
3341 EXPECT_EQ(NULL, stream.get());
3342
3343 EXPECT_EQ(OK, delegate.WaitForClose());
3344
3345 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3346 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3347 }
3348
3349 // Send data back and forth but close the stream before its data frame
3350 // can be written to the socket. The send window should then increase
3351 // to its original value, i.e. we shouldn't "leak" send window bytes.
TEST_P(SpdySessionTest,SessionFlowControlNoSendLeaks)3352 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3353 if (GetParam() < kProtoSPDY31)
3354 return;
3355
3356 const char kStreamUrl[] = "http://www.google.com/";
3357
3358 const int32 msg_data_size = 100;
3359 const std::string msg_data(msg_data_size, 'a');
3360
3361 MockConnect connect_data(SYNCHRONOUS, OK);
3362
3363 scoped_ptr<SpdyFrame> req(
3364 spdy_util_.ConstructSpdyPost(
3365 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3366 MockWrite writes[] = {
3367 CreateMockWrite(*req, 0),
3368 };
3369
3370 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3371 MockRead reads[] = {
3372 CreateMockRead(*resp, 1),
3373 MockRead(ASYNC, 0, 2) // EOF
3374 };
3375
3376 // Create SpdySession and SpdyStream and send the request.
3377 DeterministicSocketData data(reads, arraysize(reads),
3378 writes, arraysize(writes));
3379 data.set_connect_data(connect_data);
3380 session_deps_.host_resolver->set_synchronous_mode(true);
3381 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3382
3383 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
3384 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3385
3386 CreateDeterministicNetworkSession();
3387
3388 base::WeakPtr<SpdySession> session =
3389 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3390
3391 GURL url(kStreamUrl);
3392 base::WeakPtr<SpdyStream> stream =
3393 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3394 session, url, MEDIUM, BoundNetLog());
3395 ASSERT_TRUE(stream.get() != NULL);
3396 EXPECT_EQ(0u, stream->stream_id());
3397
3398 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3399 stream->SetDelegate(&delegate);
3400
3401 scoped_ptr<SpdyHeaderBlock> headers(
3402 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3403 EXPECT_EQ(ERR_IO_PENDING,
3404 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3405 EXPECT_TRUE(stream->HasUrlFromHeaders());
3406
3407 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3408
3409 data.RunFor(1);
3410
3411 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3412
3413 data.RunFor(1);
3414
3415 EXPECT_TRUE(data.at_write_eof());
3416 EXPECT_TRUE(data.at_read_eof());
3417
3418 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3419 session->session_send_window_size_);
3420
3421 // Closing the stream should increase the session's send window.
3422 stream->Close();
3423 EXPECT_EQ(NULL, stream.get());
3424
3425 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3426
3427 EXPECT_EQ(OK, delegate.WaitForClose());
3428 }
3429
3430 // Send data back and forth; the send and receive windows should
3431 // change appropriately.
TEST_P(SpdySessionTest,SessionFlowControlEndToEnd)3432 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
3433 if (GetParam() < kProtoSPDY31)
3434 return;
3435
3436 const char kStreamUrl[] = "http://www.google.com/";
3437
3438 const int32 msg_data_size = 100;
3439 const std::string msg_data(msg_data_size, 'a');
3440
3441 MockConnect connect_data(SYNCHRONOUS, OK);
3442
3443 scoped_ptr<SpdyFrame> req(
3444 spdy_util_.ConstructSpdyPost(
3445 kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3446 scoped_ptr<SpdyFrame> msg(
3447 spdy_util_.ConstructSpdyBodyFrame(
3448 1, msg_data.data(), msg_data_size, false));
3449 MockWrite writes[] = {
3450 CreateMockWrite(*req, 0),
3451 CreateMockWrite(*msg, 2),
3452 };
3453
3454 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3455 scoped_ptr<SpdyFrame> echo(
3456 spdy_util_.ConstructSpdyBodyFrame(
3457 1, msg_data.data(), msg_data_size, false));
3458 scoped_ptr<SpdyFrame> window_update(
3459 spdy_util_.ConstructSpdyWindowUpdate(
3460 kSessionFlowControlStreamId, msg_data_size));
3461 MockRead reads[] = {
3462 CreateMockRead(*resp, 1),
3463 CreateMockRead(*echo, 3),
3464 CreateMockRead(*window_update, 4),
3465 MockRead(ASYNC, 0, 5) // EOF
3466 };
3467
3468 // Create SpdySession and SpdyStream and send the request.
3469 DeterministicSocketData data(reads, arraysize(reads),
3470 writes, arraysize(writes));
3471 data.set_connect_data(connect_data);
3472 session_deps_.host_resolver->set_synchronous_mode(true);
3473 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3474
3475 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
3476 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3477
3478 CreateDeterministicNetworkSession();
3479
3480 base::WeakPtr<SpdySession> session =
3481 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3482
3483 GURL url(kStreamUrl);
3484 base::WeakPtr<SpdyStream> stream =
3485 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3486 session, url, MEDIUM, BoundNetLog());
3487 ASSERT_TRUE(stream.get() != NULL);
3488 EXPECT_EQ(0u, stream->stream_id());
3489
3490 test::StreamDelegateSendImmediate delegate(stream, msg_data);
3491 stream->SetDelegate(&delegate);
3492
3493 scoped_ptr<SpdyHeaderBlock> headers(
3494 spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3495 EXPECT_EQ(ERR_IO_PENDING,
3496 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3497 EXPECT_TRUE(stream->HasUrlFromHeaders());
3498
3499 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3500 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3501 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3502
3503 data.RunFor(1);
3504
3505 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3506 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3507 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3508
3509 data.RunFor(1);
3510
3511 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3512 session->session_send_window_size_);
3513 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3514 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3515
3516 data.RunFor(1);
3517
3518 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3519 session->session_send_window_size_);
3520 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3521 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3522
3523 data.RunFor(1);
3524
3525 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3526 session->session_send_window_size_);
3527 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3528 session->session_recv_window_size_);
3529 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3530
3531 data.RunFor(1);
3532
3533 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3534 EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3535 session->session_recv_window_size_);
3536 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3537
3538 EXPECT_TRUE(data.at_write_eof());
3539 EXPECT_TRUE(data.at_read_eof());
3540
3541 EXPECT_EQ(msg_data, delegate.TakeReceivedData());
3542
3543 // Draining the delegate's read queue should increase the session's
3544 // receive window.
3545 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3546 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3547 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3548
3549 stream->Close();
3550 EXPECT_EQ(NULL, stream.get());
3551
3552 EXPECT_EQ(OK, delegate.WaitForClose());
3553
3554 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3555 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3556 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3557 }
3558
3559 // Given a stall function and an unstall function, runs a test to make
3560 // 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)3561 void SpdySessionTest::RunResumeAfterUnstallTest(
3562 const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
3563 const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
3564 unstall_function) {
3565 const char kStreamUrl[] = "http://www.google.com/";
3566 GURL url(kStreamUrl);
3567
3568 session_deps_.host_resolver->set_synchronous_mode(true);
3569
3570 scoped_ptr<SpdyFrame> req(
3571 spdy_util_.ConstructSpdyPost(
3572 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3573 scoped_ptr<SpdyFrame> body(
3574 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3575 MockWrite writes[] = {
3576 CreateMockWrite(*req, 0),
3577 CreateMockWrite(*body, 1),
3578 };
3579
3580 scoped_ptr<SpdyFrame> resp(
3581 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3582 scoped_ptr<SpdyFrame> echo(
3583 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
3584 MockRead reads[] = {
3585 CreateMockRead(*resp, 2),
3586 MockRead(ASYNC, 0, 0, 3), // EOF
3587 };
3588
3589 DeterministicSocketData data(reads, arraysize(reads),
3590 writes, arraysize(writes));
3591 MockConnect connect_data(SYNCHRONOUS, OK);
3592 data.set_connect_data(connect_data);
3593
3594 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3595
3596 CreateDeterministicNetworkSession();
3597 base::WeakPtr<SpdySession> session =
3598 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3599 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3600 session->flow_control_state());
3601
3602 base::WeakPtr<SpdyStream> stream =
3603 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3604 session, url, LOWEST, BoundNetLog());
3605 ASSERT_TRUE(stream.get() != NULL);
3606
3607 test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
3608 stream->SetDelegate(&delegate);
3609
3610 EXPECT_FALSE(stream->HasUrlFromHeaders());
3611 EXPECT_FALSE(stream->send_stalled_by_flow_control());
3612
3613 scoped_ptr<SpdyHeaderBlock> headers(
3614 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3615 EXPECT_EQ(ERR_IO_PENDING,
3616 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3617 EXPECT_TRUE(stream->HasUrlFromHeaders());
3618 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
3619
3620 stall_function.Run(session.get(), stream.get());
3621
3622 data.RunFor(1);
3623
3624 EXPECT_TRUE(stream->send_stalled_by_flow_control());
3625
3626 unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
3627
3628 EXPECT_FALSE(stream->send_stalled_by_flow_control());
3629
3630 data.RunFor(3);
3631
3632 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
3633
3634 EXPECT_TRUE(delegate.send_headers_completed());
3635 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
3636 EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version"));
3637 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
3638 EXPECT_TRUE(data.at_write_eof());
3639 }
3640
3641 // Run the resume-after-unstall test with all possible stall and
3642 // unstall sequences.
3643
TEST_P(SpdySessionTest,ResumeAfterUnstallSession)3644 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
3645 if (GetParam() < kProtoSPDY31)
3646 return;
3647
3648 RunResumeAfterUnstallTest(
3649 base::Bind(&SpdySessionTest::StallSessionOnly,
3650 base::Unretained(this)),
3651 base::Bind(&SpdySessionTest::UnstallSessionOnly,
3652 base::Unretained(this)));
3653 }
3654
3655 // Equivalent to
3656 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
TEST_P(SpdySessionTest,ResumeAfterUnstallStream)3657 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
3658 if (GetParam() < kProtoSPDY31)
3659 return;
3660
3661 RunResumeAfterUnstallTest(
3662 base::Bind(&SpdySessionTest::StallStreamOnly,
3663 base::Unretained(this)),
3664 base::Bind(&SpdySessionTest::UnstallStreamOnly,
3665 base::Unretained(this)));
3666 }
3667
TEST_P(SpdySessionTest,StallSessionStreamResumeAfterUnstallSessionStream)3668 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
3669 if (GetParam() < kProtoSPDY31)
3670 return;
3671
3672 RunResumeAfterUnstallTest(
3673 base::Bind(&SpdySessionTest::StallSessionStream,
3674 base::Unretained(this)),
3675 base::Bind(&SpdySessionTest::UnstallSessionStream,
3676 base::Unretained(this)));
3677 }
3678
TEST_P(SpdySessionTest,StallStreamSessionResumeAfterUnstallSessionStream)3679 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
3680 if (GetParam() < kProtoSPDY31)
3681 return;
3682
3683 RunResumeAfterUnstallTest(
3684 base::Bind(&SpdySessionTest::StallStreamSession,
3685 base::Unretained(this)),
3686 base::Bind(&SpdySessionTest::UnstallSessionStream,
3687 base::Unretained(this)));
3688 }
3689
TEST_P(SpdySessionTest,StallStreamSessionResumeAfterUnstallStreamSession)3690 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
3691 if (GetParam() < kProtoSPDY31)
3692 return;
3693
3694 RunResumeAfterUnstallTest(
3695 base::Bind(&SpdySessionTest::StallStreamSession,
3696 base::Unretained(this)),
3697 base::Bind(&SpdySessionTest::UnstallStreamSession,
3698 base::Unretained(this)));
3699 }
3700
TEST_P(SpdySessionTest,StallSessionStreamResumeAfterUnstallStreamSession)3701 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
3702 if (GetParam() < kProtoSPDY31)
3703 return;
3704
3705 RunResumeAfterUnstallTest(
3706 base::Bind(&SpdySessionTest::StallSessionStream,
3707 base::Unretained(this)),
3708 base::Bind(&SpdySessionTest::UnstallStreamSession,
3709 base::Unretained(this)));
3710 }
3711
3712 // Cause a stall by reducing the flow control send window to 0. The
3713 // streams should resume in priority order when that window is then
3714 // increased.
TEST_P(SpdySessionTest,ResumeByPriorityAfterSendWindowSizeIncrease)3715 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
3716 if (GetParam() < kProtoSPDY31)
3717 return;
3718
3719 const char kStreamUrl[] = "http://www.google.com/";
3720 GURL url(kStreamUrl);
3721
3722 session_deps_.host_resolver->set_synchronous_mode(true);
3723
3724 scoped_ptr<SpdyFrame> req1(
3725 spdy_util_.ConstructSpdyPost(
3726 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3727 scoped_ptr<SpdyFrame> req2(
3728 spdy_util_.ConstructSpdyPost(
3729 kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
3730 scoped_ptr<SpdyFrame> body1(
3731 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3732 scoped_ptr<SpdyFrame> body2(
3733 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
3734 MockWrite writes[] = {
3735 CreateMockWrite(*req1, 0),
3736 CreateMockWrite(*req2, 1),
3737 CreateMockWrite(*body2, 2),
3738 CreateMockWrite(*body1, 3),
3739 };
3740
3741 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3742 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3743 MockRead reads[] = {
3744 CreateMockRead(*resp1, 4),
3745 CreateMockRead(*resp2, 5),
3746 MockRead(ASYNC, 0, 0, 6), // EOF
3747 };
3748
3749 DeterministicSocketData data(reads, arraysize(reads),
3750 writes, arraysize(writes));
3751 MockConnect connect_data(SYNCHRONOUS, OK);
3752 data.set_connect_data(connect_data);
3753
3754 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3755
3756 CreateDeterministicNetworkSession();
3757 base::WeakPtr<SpdySession> session =
3758 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3759 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3760 session->flow_control_state());
3761
3762 base::WeakPtr<SpdyStream> stream1 =
3763 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3764 session, url, LOWEST, BoundNetLog());
3765 ASSERT_TRUE(stream1.get() != NULL);
3766
3767 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
3768 stream1->SetDelegate(&delegate1);
3769
3770 EXPECT_FALSE(stream1->HasUrlFromHeaders());
3771
3772 base::WeakPtr<SpdyStream> stream2 =
3773 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3774 session, url, MEDIUM, BoundNetLog());
3775 ASSERT_TRUE(stream2.get() != NULL);
3776
3777 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
3778 stream2->SetDelegate(&delegate2);
3779
3780 EXPECT_FALSE(stream2->HasUrlFromHeaders());
3781
3782 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
3783 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3784
3785 StallSessionSend(session.get());
3786
3787 scoped_ptr<SpdyHeaderBlock> headers1(
3788 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3789 EXPECT_EQ(ERR_IO_PENDING,
3790 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
3791 EXPECT_TRUE(stream1->HasUrlFromHeaders());
3792 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
3793
3794 data.RunFor(1);
3795 EXPECT_EQ(1u, stream1->stream_id());
3796 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
3797
3798 scoped_ptr<SpdyHeaderBlock> headers2(
3799 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3800 EXPECT_EQ(ERR_IO_PENDING,
3801 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
3802 EXPECT_TRUE(stream2->HasUrlFromHeaders());
3803 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
3804
3805 data.RunFor(1);
3806 EXPECT_EQ(3u, stream2->stream_id());
3807 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
3808
3809 // This should unstall only stream2.
3810 UnstallSessionSend(session.get(), kBodyDataSize);
3811
3812 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
3813 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3814
3815 data.RunFor(1);
3816
3817 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
3818 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3819
3820 // This should then unstall stream1.
3821 UnstallSessionSend(session.get(), kBodyDataSize);
3822
3823 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
3824 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3825
3826 data.RunFor(4);
3827
3828 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
3829 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
3830
3831 EXPECT_TRUE(delegate1.send_headers_completed());
3832 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
3833 EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version"));
3834 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
3835
3836 EXPECT_TRUE(delegate2.send_headers_completed());
3837 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
3838 EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version"));
3839 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
3840
3841 EXPECT_TRUE(data.at_write_eof());
3842 }
3843
3844 // Delegate that closes a given stream after sending its body.
3845 class StreamClosingDelegate : public test::StreamDelegateWithBody {
3846 public:
StreamClosingDelegate(const base::WeakPtr<SpdyStream> & stream,base::StringPiece data)3847 StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
3848 base::StringPiece data)
3849 : StreamDelegateWithBody(stream, data) {}
3850
~StreamClosingDelegate()3851 virtual ~StreamClosingDelegate() {}
3852
set_stream_to_close(const base::WeakPtr<SpdyStream> & stream_to_close)3853 void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
3854 stream_to_close_ = stream_to_close;
3855 }
3856
OnDataSent()3857 virtual void OnDataSent() OVERRIDE {
3858 test::StreamDelegateWithBody::OnDataSent();
3859 if (stream_to_close_.get()) {
3860 stream_to_close_->Close();
3861 EXPECT_EQ(NULL, stream_to_close_.get());
3862 }
3863 }
3864
3865 private:
3866 base::WeakPtr<SpdyStream> stream_to_close_;
3867 };
3868
3869 // Cause a stall by reducing the flow control send window to
3870 // 0. Unstalling the session should properly handle deleted streams.
TEST_P(SpdySessionTest,SendWindowSizeIncreaseWithDeletedStreams)3871 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
3872 if (GetParam() < kProtoSPDY31)
3873 return;
3874
3875 const char kStreamUrl[] = "http://www.google.com/";
3876 GURL url(kStreamUrl);
3877
3878 session_deps_.host_resolver->set_synchronous_mode(true);
3879
3880 scoped_ptr<SpdyFrame> req1(
3881 spdy_util_.ConstructSpdyPost(
3882 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3883 scoped_ptr<SpdyFrame> req2(
3884 spdy_util_.ConstructSpdyPost(
3885 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
3886 scoped_ptr<SpdyFrame> req3(
3887 spdy_util_.ConstructSpdyPost(
3888 kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
3889 scoped_ptr<SpdyFrame> body2(
3890 spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
3891 MockWrite writes[] = {
3892 CreateMockWrite(*req1, 0),
3893 CreateMockWrite(*req2, 1),
3894 CreateMockWrite(*req3, 2),
3895 CreateMockWrite(*body2, 3),
3896 };
3897
3898 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3899 MockRead reads[] = {
3900 CreateMockRead(*resp2, 4),
3901 MockRead(ASYNC, 0, 0, 5), // EOF
3902 };
3903
3904 DeterministicSocketData data(reads, arraysize(reads),
3905 writes, arraysize(writes));
3906 MockConnect connect_data(SYNCHRONOUS, OK);
3907 data.set_connect_data(connect_data);
3908
3909 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3910
3911 CreateDeterministicNetworkSession();
3912 base::WeakPtr<SpdySession> session =
3913 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3914 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3915 session->flow_control_state());
3916
3917 base::WeakPtr<SpdyStream> stream1 =
3918 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3919 session, url, LOWEST, BoundNetLog());
3920 ASSERT_TRUE(stream1.get() != NULL);
3921
3922 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
3923 stream1->SetDelegate(&delegate1);
3924
3925 EXPECT_FALSE(stream1->HasUrlFromHeaders());
3926
3927 base::WeakPtr<SpdyStream> stream2 =
3928 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3929 session, url, LOWEST, BoundNetLog());
3930 ASSERT_TRUE(stream2.get() != NULL);
3931
3932 StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
3933 stream2->SetDelegate(&delegate2);
3934
3935 EXPECT_FALSE(stream2->HasUrlFromHeaders());
3936
3937 base::WeakPtr<SpdyStream> stream3 =
3938 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3939 session, url, LOWEST, BoundNetLog());
3940 ASSERT_TRUE(stream3.get() != NULL);
3941
3942 test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
3943 stream3->SetDelegate(&delegate3);
3944
3945 EXPECT_FALSE(stream3->HasUrlFromHeaders());
3946
3947 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
3948 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3949 EXPECT_FALSE(stream3->send_stalled_by_flow_control());
3950
3951 StallSessionSend(session.get());
3952
3953 scoped_ptr<SpdyHeaderBlock> headers1(
3954 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3955 EXPECT_EQ(ERR_IO_PENDING,
3956 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
3957 EXPECT_TRUE(stream1->HasUrlFromHeaders());
3958 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
3959
3960 data.RunFor(1);
3961 EXPECT_EQ(1u, stream1->stream_id());
3962 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
3963
3964 scoped_ptr<SpdyHeaderBlock> headers2(
3965 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3966 EXPECT_EQ(ERR_IO_PENDING,
3967 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
3968 EXPECT_TRUE(stream2->HasUrlFromHeaders());
3969 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
3970
3971 data.RunFor(1);
3972 EXPECT_EQ(3u, stream2->stream_id());
3973 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
3974
3975 scoped_ptr<SpdyHeaderBlock> headers3(
3976 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3977 EXPECT_EQ(ERR_IO_PENDING,
3978 stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
3979 EXPECT_TRUE(stream3->HasUrlFromHeaders());
3980 EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
3981
3982 data.RunFor(1);
3983 EXPECT_EQ(5u, stream3->stream_id());
3984 EXPECT_TRUE(stream3->send_stalled_by_flow_control());
3985
3986 SpdyStreamId stream_id1 = stream1->stream_id();
3987 SpdyStreamId stream_id2 = stream2->stream_id();
3988 SpdyStreamId stream_id3 = stream3->stream_id();
3989
3990 // Close stream1 preemptively.
3991 session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
3992 EXPECT_EQ(NULL, stream1.get());
3993
3994 EXPECT_FALSE(session->IsStreamActive(stream_id1));
3995 EXPECT_TRUE(session->IsStreamActive(stream_id2));
3996 EXPECT_TRUE(session->IsStreamActive(stream_id3));
3997
3998 // Unstall stream2, which should then close stream3.
3999 delegate2.set_stream_to_close(stream3);
4000 UnstallSessionSend(session.get(), kBodyDataSize);
4001
4002 data.RunFor(1);
4003 EXPECT_EQ(NULL, stream3.get());
4004
4005 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4006 EXPECT_FALSE(session->IsStreamActive(stream_id1));
4007 EXPECT_TRUE(session->IsStreamActive(stream_id2));
4008 EXPECT_FALSE(session->IsStreamActive(stream_id3));
4009
4010 data.RunFor(2);
4011 EXPECT_EQ(NULL, stream2.get());
4012
4013 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4014 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4015 EXPECT_EQ(OK, delegate3.WaitForClose());
4016
4017 EXPECT_TRUE(delegate1.send_headers_completed());
4018 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4019
4020 EXPECT_TRUE(delegate2.send_headers_completed());
4021 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4022 EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version"));
4023 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4024
4025 EXPECT_TRUE(delegate3.send_headers_completed());
4026 EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4027
4028 EXPECT_TRUE(data.at_write_eof());
4029 }
4030
4031 // Cause a stall by reducing the flow control send window to
4032 // 0. Unstalling the session should properly handle the session itself
4033 // being closed.
TEST_P(SpdySessionTest,SendWindowSizeIncreaseWithDeletedSession)4034 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4035 if (GetParam() < kProtoSPDY31)
4036 return;
4037
4038 const char kStreamUrl[] = "http://www.google.com/";
4039 GURL url(kStreamUrl);
4040
4041 session_deps_.host_resolver->set_synchronous_mode(true);
4042
4043 scoped_ptr<SpdyFrame> req1(
4044 spdy_util_.ConstructSpdyPost(
4045 kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4046 scoped_ptr<SpdyFrame> req2(
4047 spdy_util_.ConstructSpdyPost(
4048 kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4049 scoped_ptr<SpdyFrame> body1(
4050 spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4051 MockWrite writes[] = {
4052 CreateMockWrite(*req1, 0),
4053 CreateMockWrite(*req2, 1),
4054 };
4055
4056 MockRead reads[] = {
4057 MockRead(ASYNC, 0, 0, 2), // EOF
4058 };
4059
4060 DeterministicSocketData data(reads, arraysize(reads),
4061 writes, arraysize(writes));
4062 MockConnect connect_data(SYNCHRONOUS, OK);
4063 data.set_connect_data(connect_data);
4064
4065 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4066
4067 CreateDeterministicNetworkSession();
4068 base::WeakPtr<SpdySession> session =
4069 CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4070 EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4071 session->flow_control_state());
4072
4073 base::WeakPtr<SpdyStream> stream1 =
4074 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4075 session, url, LOWEST, BoundNetLog());
4076 ASSERT_TRUE(stream1.get() != NULL);
4077
4078 test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4079 stream1->SetDelegate(&delegate1);
4080
4081 EXPECT_FALSE(stream1->HasUrlFromHeaders());
4082
4083 base::WeakPtr<SpdyStream> stream2 =
4084 CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4085 session, url, LOWEST, BoundNetLog());
4086 ASSERT_TRUE(stream2.get() != NULL);
4087
4088 test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4089 stream2->SetDelegate(&delegate2);
4090
4091 EXPECT_FALSE(stream2->HasUrlFromHeaders());
4092
4093 EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4094 EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4095
4096 StallSessionSend(session.get());
4097
4098 scoped_ptr<SpdyHeaderBlock> headers1(
4099 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4100 EXPECT_EQ(ERR_IO_PENDING,
4101 stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4102 EXPECT_TRUE(stream1->HasUrlFromHeaders());
4103 EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4104
4105 data.RunFor(1);
4106 EXPECT_EQ(1u, stream1->stream_id());
4107 EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4108
4109 scoped_ptr<SpdyHeaderBlock> headers2(
4110 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4111 EXPECT_EQ(ERR_IO_PENDING,
4112 stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4113 EXPECT_TRUE(stream2->HasUrlFromHeaders());
4114 EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4115
4116 data.RunFor(1);
4117 EXPECT_EQ(3u, stream2->stream_id());
4118 EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4119
4120 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4121
4122 // Unstall stream1.
4123 UnstallSessionSend(session.get(), kBodyDataSize);
4124
4125 // Close the session (since we can't do it from within the delegate
4126 // method, since it's in the stream's loop).
4127 session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4128 EXPECT_TRUE(session == NULL);
4129
4130 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4131
4132 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4133 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4134
4135 EXPECT_TRUE(delegate1.send_headers_completed());
4136 EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4137
4138 EXPECT_TRUE(delegate2.send_headers_completed());
4139 EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4140
4141 EXPECT_TRUE(data.at_write_eof());
4142 }
4143
4144 } // namespace net
4145