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