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