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