Update To 11.40.268.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/base64.h"
8 #include "base/bind.h"
9 #include "base/callback.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/test/histogram_tester.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/ip_endpoint.h"
15 #include "net/base/net_log_unittest.h"
16 #include "net/base/request_priority.h"
17 #include "net/base/test_data_directory.h"
18 #include "net/base/test_data_stream.h"
19 #include "net/socket/client_socket_pool_manager.h"
20 #include "net/socket/next_proto.h"
21 #include "net/socket/socket_test_util.h"
22 #include "net/spdy/spdy_http_utils.h"
23 #include "net/spdy/spdy_session_pool.h"
24 #include "net/spdy/spdy_session_test_util.h"
25 #include "net/spdy/spdy_stream.h"
26 #include "net/spdy/spdy_stream_test_util.h"
27 #include "net/spdy/spdy_test_util_common.h"
28 #include "net/spdy/spdy_test_utils.h"
29 #include "net/test/cert_test_util.h"
30 #include "testing/platform_test.h"
31
32 namespace net {
33
34 namespace {
35
36 static const char kTestUrl[] = "http://www.example.org/";
37 static const char kTestHost[] = "www.example.org";
38 static const int kTestPort = 80;
39
40 const char kBodyData[] = "Body data";
41 const size_t kBodyDataSize = arraysize(kBodyData);
42 const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize);
43
44 static base::TimeDelta g_time_delta;
45 base::TimeTicks TheNearFuture() {
46   return base::TimeTicks::Now() + g_time_delta;
47 }
48
49 }  // namespace
50
51 class SpdySessionTest : public PlatformTest,
52                         public ::testing::WithParamInterface<NextProto> {
53  public:
54   // Functions used with RunResumeAfterUnstallTest().
55
56   void StallSessionOnly(SpdySession* session, SpdyStream* stream) {
57     StallSessionSend(session);
58   }
59
60   void StallStreamOnly(SpdySession* session, SpdyStream* stream) {
61     StallStreamSend(stream);
62   }
63
64   void StallSessionStream(SpdySession* session, SpdyStream* stream) {
65     StallSessionSend(session);
66     StallStreamSend(stream);
67   }
68
69   void StallStreamSession(SpdySession* session, SpdyStream* stream) {
70     StallStreamSend(stream);
71     StallSessionSend(session);
72   }
73
74   void UnstallSessionOnly(SpdySession* session,
75                           SpdyStream* stream,
76                           int32 delta_window_size) {
77     UnstallSessionSend(session, delta_window_size);
78   }
79
80   void UnstallStreamOnly(SpdySession* session,
81                          SpdyStream* stream,
82                          int32 delta_window_size) {
83     UnstallStreamSend(stream, delta_window_size);
84   }
85
86   void UnstallSessionStream(SpdySession* session,
87                             SpdyStream* stream,
88                             int32 delta_window_size) {
89     UnstallSessionSend(session, delta_window_size);
90     UnstallStreamSend(stream, delta_window_size);
91   }
92
93   void UnstallStreamSession(SpdySession* session,
94                             SpdyStream* stream,
95                             int32 delta_window_size) {
96     UnstallStreamSend(stream, delta_window_size);
97     UnstallSessionSend(session, delta_window_size);
98   }
99
100  protected:
101   SpdySessionTest()
102       : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
103             HttpNetworkSession::NORMAL_SOCKET_POOL)),
104         old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
105             HttpNetworkSession::NORMAL_SOCKET_POOL)),
106         spdy_util_(GetParam()),
107         session_deps_(GetParam()),
108         spdy_session_pool_(NULL),
109         test_url_(kTestUrl),
110         test_host_port_pair_(kTestHost, kTestPort),
111         key_(test_host_port_pair_, ProxyServer::Direct(),
112              PRIVACY_MODE_DISABLED) {
113   }
114
115   virtual ~SpdySessionTest() {
116     // Important to restore the per-pool limit first, since the pool limit must
117     // always be greater than group limit, and the tests reduce both limits.
118     ClientSocketPoolManager::set_max_sockets_per_pool(
119         HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
120     ClientSocketPoolManager::set_max_sockets_per_group(
121         HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
122   }
123
124   void SetUp() override { g_time_delta = base::TimeDelta(); }
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   ~StreamRequestDestroyingCallback() override {}
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(), 1U);
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(), 1U);
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   if (GetParam() <= kProtoSPDY31) {
1578     writes.push_back(CreateMockWrite(*server_settings_frame));
1579   }
1580
1581   session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize;
1582
1583   StaticSocketDataProvider data(reads, arraysize(reads),
1584                                 vector_as_array(&writes), writes.size());
1585   data.set_connect_data(connect_data);
1586   session_deps_.socket_factory->AddSocketDataProvider(&data);
1587
1588   CreateNetworkSession();
1589
1590   spdy_session_pool_->http_server_properties()->SetSpdySetting(
1591       test_host_port_pair_,
1592       SETTINGS_MAX_CONCURRENT_STREAMS,
1593       SETTINGS_FLAG_PLEASE_PERSIST,
1594       initial_max_concurrent_streams);
1595
1596   SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1597   pool_peer.SetEnableSendingInitialData(true);
1598
1599   base::WeakPtr<SpdySession> session =
1600       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1601
1602   base::MessageLoop::current()->RunUntilIdle();
1603   EXPECT_TRUE(data.at_write_eof());
1604 }
1605
1606 TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
1607   CreateNetworkSession();
1608
1609   base::WeakPtr<HttpServerProperties> test_http_server_properties =
1610       spdy_session_pool_->http_server_properties();
1611   SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
1612   test_http_server_properties->SetSpdySetting(
1613       test_host_port_pair_,
1614       SETTINGS_MAX_CONCURRENT_STREAMS,
1615       SETTINGS_FLAG_PLEASE_PERSIST,
1616       2);
1617   EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
1618       test_host_port_pair_).size());
1619   spdy_session_pool_->OnIPAddressChanged();
1620   EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
1621       test_host_port_pair_).size());
1622 }
1623
1624 TEST_P(SpdySessionTest, Initialize) {
1625   CapturingBoundNetLog log;
1626   session_deps_.net_log = log.bound().net_log();
1627   session_deps_.host_resolver->set_synchronous_mode(true);
1628
1629   MockConnect connect_data(SYNCHRONOUS, OK);
1630   MockRead reads[] = {
1631     MockRead(ASYNC, 0, 0)  // EOF
1632   };
1633
1634   StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1635   data.set_connect_data(connect_data);
1636   session_deps_.socket_factory->AddSocketDataProvider(&data);
1637
1638   CreateNetworkSession();
1639
1640   base::WeakPtr<SpdySession> session =
1641       CreateInsecureSpdySession(http_session_, key_, log.bound());
1642   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1643
1644   // Flush the read completion task.
1645   base::MessageLoop::current()->RunUntilIdle();
1646
1647   net::CapturingNetLog::CapturedEntryList entries;
1648   log.GetEntries(&entries);
1649   EXPECT_LT(0u, entries.size());
1650
1651   // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly.
1652   int pos = net::ExpectLogContainsSomewhere(
1653       entries, 0,
1654       net::NetLog::TYPE_SPDY_SESSION_INITIALIZED,
1655       net::NetLog::PHASE_NONE);
1656   EXPECT_LT(0, pos);
1657
1658   CapturingNetLog::CapturedEntry entry = entries[pos];
1659   NetLog::Source socket_source;
1660   EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1661                                                   &socket_source));
1662   EXPECT_TRUE(socket_source.IsValid());
1663   EXPECT_NE(log.bound().source().id, socket_source.id);
1664 }
1665
1666 TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
1667   session_deps_.host_resolver->set_synchronous_mode(true);
1668
1669   MockConnect connect_data(SYNCHRONOUS, OK);
1670   scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
1671   MockRead reads[] = {
1672     CreateMockRead(*goaway),
1673     MockRead(SYNCHRONOUS, 0, 0)  // EOF
1674   };
1675
1676   StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1677   data.set_connect_data(connect_data);
1678   session_deps_.socket_factory->AddSocketDataProvider(&data);
1679
1680   CreateNetworkSession();
1681
1682   CapturingBoundNetLog log;
1683   base::WeakPtr<SpdySession> session =
1684       CreateInsecureSpdySession(http_session_, key_, log.bound());
1685   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1686
1687   // Flush the read completion task.
1688   base::MessageLoop::current()->RunUntilIdle();
1689
1690   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1691   EXPECT_TRUE(session == NULL);
1692
1693   // Check that the NetLog was filled reasonably.
1694   net::CapturingNetLog::CapturedEntryList entries;
1695   log.GetEntries(&entries);
1696   EXPECT_LT(0u, entries.size());
1697
1698   // Check that we logged SPDY_SESSION_CLOSE correctly.
1699   int pos = net::ExpectLogContainsSomewhere(
1700       entries, 0,
1701       net::NetLog::TYPE_SPDY_SESSION_CLOSE,
1702       net::NetLog::PHASE_NONE);
1703
1704   if (pos < static_cast<int>(entries.size())) {
1705     CapturingNetLog::CapturedEntry entry = entries[pos];
1706     int error_code = 0;
1707     ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1708     EXPECT_EQ(OK, error_code);
1709   } else {
1710     ADD_FAILURE();
1711   }
1712 }
1713
1714 TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1715   session_deps_.host_resolver->set_synchronous_mode(true);
1716
1717   MockConnect connect_data(SYNCHRONOUS, OK);
1718   MockRead reads[] = {
1719       MockRead(SYNCHRONOUS, 0, 0)  // EOF
1720   };
1721
1722   StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1723   data.set_connect_data(connect_data);
1724   session_deps_.socket_factory->AddSocketDataProvider(&data);
1725
1726   CreateNetworkSession();
1727
1728   CapturingBoundNetLog log;
1729   base::WeakPtr<SpdySession> session =
1730       CreateInsecureSpdySession(http_session_, key_, log.bound());
1731   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1732
1733   // Flush the read completion task.
1734   base::MessageLoop::current()->RunUntilIdle();
1735
1736   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1737   EXPECT_TRUE(session == NULL);
1738
1739   // Check that the NetLog was filled reasonably.
1740   net::CapturingNetLog::CapturedEntryList entries;
1741   log.GetEntries(&entries);
1742   EXPECT_LT(0u, entries.size());
1743
1744   // Check that we logged SPDY_SESSION_CLOSE correctly.
1745   int pos =
1746       net::ExpectLogContainsSomewhere(entries,
1747                                       0,
1748                                       net::NetLog::TYPE_SPDY_SESSION_CLOSE,
1749                                       net::NetLog::PHASE_NONE);
1750
1751   if (pos < static_cast<int>(entries.size())) {
1752     CapturingNetLog::CapturedEntry entry = entries[pos];
1753     int error_code = 0;
1754     ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1755     EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1756   } else {
1757     ADD_FAILURE();
1758   }
1759 }
1760
1761 TEST_P(SpdySessionTest, SynCompressionHistograms) {
1762   session_deps_.enable_compression = true;
1763
1764   scoped_ptr<SpdyFrame> req(
1765       spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, MEDIUM, true));
1766   MockWrite writes[] = {
1767     CreateMockWrite(*req, 0),
1768   };
1769   MockRead reads[] = {
1770     MockRead(ASYNC, 0, 1)  // EOF
1771   };
1772   DeterministicSocketData data(reads, arraysize(reads),
1773                                writes, arraysize(writes));
1774   MockConnect connect_data(SYNCHRONOUS, OK);
1775   data.set_connect_data(connect_data);
1776   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1777
1778   CreateDeterministicNetworkSession();
1779   base::WeakPtr<SpdySession> session =
1780       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1781
1782   GURL url(kDefaultURL);
1783   base::WeakPtr<SpdyStream> spdy_stream =
1784       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1785                                 session, url, MEDIUM, BoundNetLog());
1786   test::StreamDelegateDoNothing delegate(spdy_stream);
1787   spdy_stream->SetDelegate(&delegate);
1788
1789   scoped_ptr<SpdyHeaderBlock> headers(
1790       spdy_util_.ConstructGetHeaderBlock(url.spec()));
1791   spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1792   EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1793
1794   // Write request headers & capture resulting histogram update.
1795   base::HistogramTester histogram_tester;
1796
1797   data.RunFor(1);
1798   // Regression test of compression performance under the request fixture.
1799   switch (spdy_util_.spdy_version()) {
1800     case SPDY2:
1801       histogram_tester.ExpectBucketCount(
1802           "Net.SpdySynStreamCompressionPercentage", 0, 1);
1803       break;
1804     case SPDY3:
1805       histogram_tester.ExpectBucketCount(
1806           "Net.SpdySynStreamCompressionPercentage", 30, 1);
1807       break;
1808     case SPDY4:
1809       histogram_tester.ExpectBucketCount(
1810           "Net.SpdySynStreamCompressionPercentage", 82, 1);
1811       break;
1812     case SPDY5:
1813       histogram_tester.ExpectBucketCount(
1814           "Net.SpdySynStreamCompressionPercentage", 82, 1);
1815       break;
1816     default:
1817       NOTREACHED();
1818   }
1819
1820   // Read and process EOF.
1821   data.RunFor(1);
1822   base::MessageLoop::current()->RunUntilIdle();
1823   EXPECT_TRUE(session == NULL);
1824 }
1825
1826 // Queue up a low-priority SYN_STREAM followed by a high-priority
1827 // one. The high priority one should still send first and receive
1828 // first.
1829 TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1830   // Construct the request.
1831   MockConnect connect_data(SYNCHRONOUS, OK);
1832   scoped_ptr<SpdyFrame> req_highest(
1833       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true));
1834   scoped_ptr<SpdyFrame> req_lowest(
1835       spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1836   MockWrite writes[] = {
1837     CreateMockWrite(*req_highest, 0),
1838     CreateMockWrite(*req_lowest, 1),
1839   };
1840
1841   scoped_ptr<SpdyFrame> resp_highest(
1842       spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1843   scoped_ptr<SpdyFrame> body_highest(
1844       spdy_util_.ConstructSpdyBodyFrame(1, true));
1845   scoped_ptr<SpdyFrame> resp_lowest(
1846       spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1847   scoped_ptr<SpdyFrame> body_lowest(
1848       spdy_util_.ConstructSpdyBodyFrame(3, true));
1849   MockRead reads[] = {
1850     CreateMockRead(*resp_highest, 2),
1851     CreateMockRead(*body_highest, 3),
1852     CreateMockRead(*resp_lowest, 4),
1853     CreateMockRead(*body_lowest, 5),
1854     MockRead(ASYNC, 0, 6)  // EOF
1855   };
1856
1857   session_deps_.host_resolver->set_synchronous_mode(true);
1858
1859   DeterministicSocketData data(reads, arraysize(reads),
1860                                writes, arraysize(writes));
1861   data.set_connect_data(connect_data);
1862   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1863
1864   CreateDeterministicNetworkSession();
1865
1866   base::WeakPtr<SpdySession> session =
1867       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1868
1869   GURL url(kDefaultURL);
1870
1871   base::WeakPtr<SpdyStream> spdy_stream_lowest =
1872       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1873                                 session, url, LOWEST, BoundNetLog());
1874   ASSERT_TRUE(spdy_stream_lowest);
1875   EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1876   test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1877   spdy_stream_lowest->SetDelegate(&delegate_lowest);
1878
1879   base::WeakPtr<SpdyStream> spdy_stream_highest =
1880       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1881                                 session, url, HIGHEST, BoundNetLog());
1882   ASSERT_TRUE(spdy_stream_highest);
1883   EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1884   test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1885   spdy_stream_highest->SetDelegate(&delegate_highest);
1886
1887   // Queue the lower priority one first.
1888
1889   scoped_ptr<SpdyHeaderBlock> headers_lowest(
1890       spdy_util_.ConstructGetHeaderBlock(url.spec()));
1891   spdy_stream_lowest->SendRequestHeaders(
1892       headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1893   EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1894
1895   scoped_ptr<SpdyHeaderBlock> headers_highest(
1896       spdy_util_.ConstructGetHeaderBlock(url.spec()));
1897   spdy_stream_highest->SendRequestHeaders(
1898       headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1899   EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1900
1901   data.RunFor(7);
1902
1903   EXPECT_FALSE(spdy_stream_lowest);
1904   EXPECT_FALSE(spdy_stream_highest);
1905   EXPECT_EQ(3u, delegate_lowest.stream_id());
1906   EXPECT_EQ(1u, delegate_highest.stream_id());
1907 }
1908
1909 TEST_P(SpdySessionTest, CancelStream) {
1910   MockConnect connect_data(SYNCHRONOUS, OK);
1911   // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1912   // Request 2, at LOWEST priority, will be a full request and will be id 1.
1913   scoped_ptr<SpdyFrame> req2(
1914       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1915   MockWrite writes[] = {
1916     CreateMockWrite(*req2, 0),
1917   };
1918
1919   scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1920   scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1921   MockRead reads[] = {
1922     CreateMockRead(*resp2, 1),
1923     CreateMockRead(*body2, 2),
1924     MockRead(ASYNC, 0, 3)  // EOF
1925   };
1926
1927   session_deps_.host_resolver->set_synchronous_mode(true);
1928
1929   DeterministicSocketData data(reads, arraysize(reads),
1930                                writes, arraysize(writes));
1931   data.set_connect_data(connect_data);
1932   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1933
1934   CreateDeterministicNetworkSession();
1935
1936   base::WeakPtr<SpdySession> session =
1937       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1938
1939   GURL url1(kDefaultURL);
1940   base::WeakPtr<SpdyStream> spdy_stream1 =
1941       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1942                                 session, url1, HIGHEST, BoundNetLog());
1943   ASSERT_TRUE(spdy_stream1.get() != NULL);
1944   EXPECT_EQ(0u, spdy_stream1->stream_id());
1945   test::StreamDelegateDoNothing delegate1(spdy_stream1);
1946   spdy_stream1->SetDelegate(&delegate1);
1947
1948   GURL url2(kDefaultURL);
1949   base::WeakPtr<SpdyStream> spdy_stream2 =
1950       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1951                                 session, url2, LOWEST, BoundNetLog());
1952   ASSERT_TRUE(spdy_stream2.get() != NULL);
1953   EXPECT_EQ(0u, spdy_stream2->stream_id());
1954   test::StreamDelegateDoNothing delegate2(spdy_stream2);
1955   spdy_stream2->SetDelegate(&delegate2);
1956
1957   scoped_ptr<SpdyHeaderBlock> headers(
1958       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1959   spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1960   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1961
1962   scoped_ptr<SpdyHeaderBlock> headers2(
1963       spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1964   spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1965   EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1966
1967   EXPECT_EQ(0u, spdy_stream1->stream_id());
1968
1969   spdy_stream1->Cancel();
1970   EXPECT_EQ(NULL, spdy_stream1.get());
1971
1972   EXPECT_EQ(0u, delegate1.stream_id());
1973
1974   data.RunFor(1);
1975
1976   EXPECT_EQ(0u, delegate1.stream_id());
1977   EXPECT_EQ(1u, delegate2.stream_id());
1978
1979   spdy_stream2->Cancel();
1980   EXPECT_EQ(NULL, spdy_stream2.get());
1981 }
1982
1983 // Create two streams that are set to re-close themselves on close,
1984 // and then close the session. Nothing should blow up. Also a
1985 // regression test for http://crbug.com/139518 .
1986 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1987   session_deps_.host_resolver->set_synchronous_mode(true);
1988
1989   MockConnect connect_data(SYNCHRONOUS, OK);
1990
1991   // No actual data will be sent.
1992   MockWrite writes[] = {
1993     MockWrite(ASYNC, 0, 1)  // EOF
1994   };
1995
1996   MockRead reads[] = {
1997     MockRead(ASYNC, 0, 0)  // EOF
1998   };
1999   DeterministicSocketData data(reads, arraysize(reads),
2000                                writes, arraysize(writes));
2001   data.set_connect_data(connect_data);
2002   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2003
2004   CreateDeterministicNetworkSession();
2005
2006   base::WeakPtr<SpdySession> session =
2007       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2008
2009   GURL url1(kDefaultURL);
2010   base::WeakPtr<SpdyStream> spdy_stream1 =
2011       CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2012                                 session, url1, HIGHEST, BoundNetLog());
2013   ASSERT_TRUE(spdy_stream1.get() != NULL);
2014   EXPECT_EQ(0u, spdy_stream1->stream_id());
2015
2016   GURL url2(kDefaultURL);
2017   base::WeakPtr<SpdyStream> spdy_stream2 =
2018       CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2019                                 session, url2, LOWEST, BoundNetLog());
2020   ASSERT_TRUE(spdy_stream2.get() != NULL);
2021   EXPECT_EQ(0u, spdy_stream2->stream_id());
2022
2023   test::ClosingDelegate delegate1(spdy_stream1);
2024   spdy_stream1->SetDelegate(&delegate1);
2025
2026   test::ClosingDelegate delegate2(spdy_stream2);
2027   spdy_stream2->SetDelegate(&delegate2);
2028
2029   scoped_ptr<SpdyHeaderBlock> headers(
2030       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2031   spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2032   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2033
2034   scoped_ptr<SpdyHeaderBlock> headers2(
2035       spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2036   spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2037   EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2038
2039   // Ensure that the streams have not yet been activated and assigned an id.
2040   EXPECT_EQ(0u, spdy_stream1->stream_id());
2041   EXPECT_EQ(0u, spdy_stream2->stream_id());
2042
2043   // Ensure we don't crash while closing the session.
2044   session->CloseSessionOnError(ERR_ABORTED, std::string());
2045
2046   EXPECT_EQ(NULL, spdy_stream1.get());
2047   EXPECT_EQ(NULL, spdy_stream2.get());
2048
2049   EXPECT_TRUE(delegate1.StreamIsClosed());
2050   EXPECT_TRUE(delegate2.StreamIsClosed());
2051
2052   base::MessageLoop::current()->RunUntilIdle();
2053   EXPECT_TRUE(session == NULL);
2054 }
2055
2056 // Create two streams that are set to close each other on close, and
2057 // then close the session. Nothing should blow up.
2058 TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
2059   session_deps_.host_resolver->set_synchronous_mode(true);
2060
2061   MockConnect connect_data(SYNCHRONOUS, OK);
2062
2063   // No actual data will be sent.
2064   MockWrite writes[] = {
2065     MockWrite(ASYNC, 0, 1)  // EOF
2066   };
2067
2068   MockRead reads[] = {
2069     MockRead(ASYNC, 0, 0)  // EOF
2070   };
2071   DeterministicSocketData data(reads, arraysize(reads),
2072                                writes, arraysize(writes));
2073   data.set_connect_data(connect_data);
2074   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2075
2076   CreateDeterministicNetworkSession();
2077
2078   base::WeakPtr<SpdySession> session =
2079       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2080
2081   GURL url1(kDefaultURL);
2082   base::WeakPtr<SpdyStream> spdy_stream1 =
2083       CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2084                                 session, url1, HIGHEST, BoundNetLog());
2085   ASSERT_TRUE(spdy_stream1.get() != NULL);
2086   EXPECT_EQ(0u, spdy_stream1->stream_id());
2087
2088   GURL url2(kDefaultURL);
2089   base::WeakPtr<SpdyStream> spdy_stream2 =
2090       CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2091                                 session, url2, LOWEST, BoundNetLog());
2092   ASSERT_TRUE(spdy_stream2.get() != NULL);
2093   EXPECT_EQ(0u, spdy_stream2->stream_id());
2094
2095   // Make |spdy_stream1| close |spdy_stream2|.
2096   test::ClosingDelegate delegate1(spdy_stream2);
2097   spdy_stream1->SetDelegate(&delegate1);
2098
2099   // Make |spdy_stream2| close |spdy_stream1|.
2100   test::ClosingDelegate delegate2(spdy_stream1);
2101   spdy_stream2->SetDelegate(&delegate2);
2102
2103   scoped_ptr<SpdyHeaderBlock> headers(
2104       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2105   spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2106   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2107
2108   scoped_ptr<SpdyHeaderBlock> headers2(
2109       spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2110   spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2111   EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2112
2113   // Ensure that the streams have not yet been activated and assigned an id.
2114   EXPECT_EQ(0u, spdy_stream1->stream_id());
2115   EXPECT_EQ(0u, spdy_stream2->stream_id());
2116
2117   // Ensure we don't crash while closing the session.
2118   session->CloseSessionOnError(ERR_ABORTED, std::string());
2119
2120   EXPECT_EQ(NULL, spdy_stream1.get());
2121   EXPECT_EQ(NULL, spdy_stream2.get());
2122
2123   EXPECT_TRUE(delegate1.StreamIsClosed());
2124   EXPECT_TRUE(delegate2.StreamIsClosed());
2125
2126   base::MessageLoop::current()->RunUntilIdle();
2127   EXPECT_TRUE(session == NULL);
2128 }
2129
2130 // Create two streams that are set to re-close themselves on close,
2131 // activate them, and then close the session. Nothing should blow up.
2132 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
2133   session_deps_.host_resolver->set_synchronous_mode(true);
2134
2135   MockConnect connect_data(SYNCHRONOUS, OK);
2136
2137   scoped_ptr<SpdyFrame> req1(
2138       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2139   scoped_ptr<SpdyFrame> req2(
2140       spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2141   MockWrite writes[] = {
2142     CreateMockWrite(*req1, 0),
2143     CreateMockWrite(*req2, 1),
2144   };
2145
2146   MockRead reads[] = {
2147     MockRead(ASYNC, 0, 2)  // EOF
2148   };
2149
2150   DeterministicSocketData data(reads, arraysize(reads),
2151                                writes, arraysize(writes));
2152   data.set_connect_data(connect_data);
2153   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2154
2155   CreateDeterministicNetworkSession();
2156
2157   base::WeakPtr<SpdySession> session =
2158       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2159
2160   GURL url1(kDefaultURL);
2161   base::WeakPtr<SpdyStream> spdy_stream1 =
2162       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2163                                 session, url1, MEDIUM, BoundNetLog());
2164   ASSERT_TRUE(spdy_stream1.get() != NULL);
2165   EXPECT_EQ(0u, spdy_stream1->stream_id());
2166
2167   GURL url2(kDefaultURL);
2168   base::WeakPtr<SpdyStream> spdy_stream2 =
2169       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2170                                 session, url2, MEDIUM, BoundNetLog());
2171   ASSERT_TRUE(spdy_stream2.get() != NULL);
2172   EXPECT_EQ(0u, spdy_stream2->stream_id());
2173
2174   test::ClosingDelegate delegate1(spdy_stream1);
2175   spdy_stream1->SetDelegate(&delegate1);
2176
2177   test::ClosingDelegate delegate2(spdy_stream2);
2178   spdy_stream2->SetDelegate(&delegate2);
2179
2180   scoped_ptr<SpdyHeaderBlock> headers(
2181       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2182   spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2183   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2184
2185   scoped_ptr<SpdyHeaderBlock> headers2(
2186       spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2187   spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2188   EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2189
2190   // Ensure that the streams have not yet been activated and assigned an id.
2191   EXPECT_EQ(0u, spdy_stream1->stream_id());
2192   EXPECT_EQ(0u, spdy_stream2->stream_id());
2193
2194   data.RunFor(2);
2195
2196   EXPECT_EQ(1u, spdy_stream1->stream_id());
2197   EXPECT_EQ(3u, spdy_stream2->stream_id());
2198
2199   // Ensure we don't crash while closing the session.
2200   session->CloseSessionOnError(ERR_ABORTED, std::string());
2201
2202   EXPECT_EQ(NULL, spdy_stream1.get());
2203   EXPECT_EQ(NULL, spdy_stream2.get());
2204
2205   EXPECT_TRUE(delegate1.StreamIsClosed());
2206   EXPECT_TRUE(delegate2.StreamIsClosed());
2207
2208   base::MessageLoop::current()->RunUntilIdle();
2209   EXPECT_TRUE(session == NULL);
2210 }
2211
2212 // Create two streams that are set to close each other on close,
2213 // activate them, and then close the session. Nothing should blow up.
2214 TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2215   session_deps_.host_resolver->set_synchronous_mode(true);
2216
2217   MockConnect connect_data(SYNCHRONOUS, OK);
2218
2219   scoped_ptr<SpdyFrame> req1(
2220       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2221   scoped_ptr<SpdyFrame> req2(
2222       spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2223   MockWrite writes[] = {
2224     CreateMockWrite(*req1, 0),
2225     CreateMockWrite(*req2, 1),
2226   };
2227
2228   MockRead reads[] = {
2229     MockRead(ASYNC, 0, 2)  // EOF
2230   };
2231
2232   DeterministicSocketData data(reads, arraysize(reads),
2233                                writes, arraysize(writes));
2234   data.set_connect_data(connect_data);
2235   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2236
2237   CreateDeterministicNetworkSession();
2238
2239   base::WeakPtr<SpdySession> session =
2240       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2241
2242   GURL url1(kDefaultURL);
2243   base::WeakPtr<SpdyStream> spdy_stream1 =
2244       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2245                                 session, url1, MEDIUM, BoundNetLog());
2246   ASSERT_TRUE(spdy_stream1.get() != NULL);
2247   EXPECT_EQ(0u, spdy_stream1->stream_id());
2248
2249   GURL url2(kDefaultURL);
2250   base::WeakPtr<SpdyStream> spdy_stream2 =
2251       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2252                                 session, url2, MEDIUM, BoundNetLog());
2253   ASSERT_TRUE(spdy_stream2.get() != NULL);
2254   EXPECT_EQ(0u, spdy_stream2->stream_id());
2255
2256   // Make |spdy_stream1| close |spdy_stream2|.
2257   test::ClosingDelegate delegate1(spdy_stream2);
2258   spdy_stream1->SetDelegate(&delegate1);
2259
2260   // Make |spdy_stream2| close |spdy_stream1|.
2261   test::ClosingDelegate delegate2(spdy_stream1);
2262   spdy_stream2->SetDelegate(&delegate2);
2263
2264   scoped_ptr<SpdyHeaderBlock> headers(
2265       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2266   spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2267   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2268
2269   scoped_ptr<SpdyHeaderBlock> headers2(
2270       spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2271   spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2272   EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2273
2274   // Ensure that the streams have not yet been activated and assigned an id.
2275   EXPECT_EQ(0u, spdy_stream1->stream_id());
2276   EXPECT_EQ(0u, spdy_stream2->stream_id());
2277
2278   data.RunFor(2);
2279
2280   EXPECT_EQ(1u, spdy_stream1->stream_id());
2281   EXPECT_EQ(3u, spdy_stream2->stream_id());
2282
2283   // Ensure we don't crash while closing the session.
2284   session->CloseSessionOnError(ERR_ABORTED, std::string());
2285
2286   EXPECT_EQ(NULL, spdy_stream1.get());
2287   EXPECT_EQ(NULL, spdy_stream2.get());
2288
2289   EXPECT_TRUE(delegate1.StreamIsClosed());
2290   EXPECT_TRUE(delegate2.StreamIsClosed());
2291
2292   base::MessageLoop::current()->RunUntilIdle();
2293   EXPECT_TRUE(session == NULL);
2294 }
2295
2296 // Delegate that closes a given session when the stream is closed.
2297 class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2298  public:
2299   SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2300                          const base::WeakPtr<SpdySession>& session_to_close)
2301       : StreamDelegateDoNothing(stream),
2302         session_to_close_(session_to_close) {}
2303
2304   ~SessionClosingDelegate() override {}
2305
2306   void OnClose(int status) override {
2307     session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2308   }
2309
2310  private:
2311   base::WeakPtr<SpdySession> session_to_close_;
2312 };
2313
2314 // Close an activated stream that closes its session. Nothing should
2315 // blow up. This is a regression test for http://crbug.com/263691 .
2316 TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2317   session_deps_.host_resolver->set_synchronous_mode(true);
2318
2319   MockConnect connect_data(SYNCHRONOUS, OK);
2320
2321   scoped_ptr<SpdyFrame> req(
2322       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2323   scoped_ptr<SpdyFrame> rst(
2324       spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2325   scoped_ptr<SpdyFrame> goaway(
2326       spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2327   // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2328   // despite being queued second.
2329   MockWrite writes[] = {
2330       CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 1),
2331       CreateMockWrite(*rst, 2),
2332   };
2333
2334   MockRead reads[] = {
2335       MockRead(ASYNC, 0, 3)  // EOF
2336   };
2337   DeterministicSocketData data(reads, arraysize(reads),
2338                                writes, arraysize(writes));
2339   data.set_connect_data(connect_data);
2340   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2341
2342   CreateDeterministicNetworkSession();
2343
2344   base::WeakPtr<SpdySession> session =
2345       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2346
2347   GURL url(kDefaultURL);
2348   base::WeakPtr<SpdyStream> spdy_stream =
2349       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2350                                 session, url, MEDIUM, BoundNetLog());
2351   ASSERT_TRUE(spdy_stream.get() != NULL);
2352   EXPECT_EQ(0u, spdy_stream->stream_id());
2353
2354   SessionClosingDelegate delegate(spdy_stream, session);
2355   spdy_stream->SetDelegate(&delegate);
2356
2357   scoped_ptr<SpdyHeaderBlock> headers(
2358       spdy_util_.ConstructGetHeaderBlock(url.spec()));
2359   spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2360   EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2361
2362   EXPECT_EQ(0u, spdy_stream->stream_id());
2363
2364   data.RunFor(1);
2365
2366   EXPECT_EQ(1u, spdy_stream->stream_id());
2367
2368   // Ensure we don't crash while closing the stream (which closes the
2369   // session).
2370   spdy_stream->Cancel();
2371
2372   EXPECT_EQ(NULL, spdy_stream.get());
2373   EXPECT_TRUE(delegate.StreamIsClosed());
2374
2375   data.RunFor(2);  // Write the RST_STREAM & GOAWAY.
2376   base::MessageLoop::current()->RunUntilIdle();
2377   EXPECT_TRUE(session == NULL);
2378 }
2379
2380 TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2381   session_deps_.host_resolver->set_synchronous_mode(true);
2382
2383   MockConnect connect_data(SYNCHRONOUS, OK);
2384
2385   // No actual data will be sent.
2386   MockWrite writes[] = {
2387     MockWrite(ASYNC, 0, 1)  // EOF
2388   };
2389
2390   MockRead reads[] = {
2391     MockRead(ASYNC, 0, 0)  // EOF
2392   };
2393   DeterministicSocketData data(reads, arraysize(reads),
2394                                writes, arraysize(writes));
2395   data.set_connect_data(connect_data);
2396   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2397
2398   // Load a cert that is valid for:
2399   //   www.example.org
2400   //   mail.example.org
2401   //   www.example.com
2402   base::FilePath certs_dir = GetTestCertsDirectory();
2403   scoped_refptr<X509Certificate> test_cert(
2404       ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2405   ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2406
2407   SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2408   ssl.cert = test_cert;
2409   session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2410
2411   CreateDeterministicNetworkSession();
2412
2413   base::WeakPtr<SpdySession> session =
2414       CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2415
2416   EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2417   EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2418   EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
2419   EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2420 }
2421
2422 TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2423   session_deps_.host_resolver->set_synchronous_mode(true);
2424
2425   MockConnect connect_data(SYNCHRONOUS, OK);
2426
2427   // No actual data will be sent.
2428   MockWrite writes[] = {
2429     MockWrite(ASYNC, 0, 1)  // EOF
2430   };
2431
2432   MockRead reads[] = {
2433     MockRead(ASYNC, 0, 0)  // EOF
2434   };
2435   DeterministicSocketData data(reads, arraysize(reads),
2436                                writes, arraysize(writes));
2437   data.set_connect_data(connect_data);
2438   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2439
2440   // Load a cert that is valid for:
2441   //   www.example.org
2442   //   mail.example.org
2443   //   www.example.com
2444   base::FilePath certs_dir = GetTestCertsDirectory();
2445   scoped_refptr<X509Certificate> test_cert(
2446       ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2447   ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2448
2449   SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2450   ssl.channel_id_sent = true;
2451   ssl.cert = test_cert;
2452   session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2453
2454   CreateDeterministicNetworkSession();
2455
2456   base::WeakPtr<SpdySession> session =
2457       CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2458
2459   EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2460   EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2461   EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2462   EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2463 }
2464
2465 TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2466   // TODO(rtenneti): Define a helper class/methods and move the common code in
2467   // this file.
2468   MockConnect connect_data(SYNCHRONOUS, OK);
2469
2470   SettingsMap new_settings;
2471   const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2472   const uint32 max_concurrent_streams = 1;
2473   new_settings[kSpdySettingsIds1] =
2474       SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2475
2476   scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
2477   scoped_ptr<SpdyFrame> req1(
2478       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2479   scoped_ptr<SpdyFrame> req2(
2480       spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
2481   scoped_ptr<SpdyFrame> req3(
2482       spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
2483   MockWrite writes[] = {
2484     CreateMockWrite(*settings_ack, 1),
2485     CreateMockWrite(*req1, 2),
2486     CreateMockWrite(*req2, 5),
2487     CreateMockWrite(*req3, 8),
2488   };
2489
2490   // Set up the socket so we read a SETTINGS frame that sets max concurrent
2491   // streams to 1.
2492   scoped_ptr<SpdyFrame> settings_frame(
2493       spdy_util_.ConstructSpdySettings(new_settings));
2494
2495   scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2496   scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2497
2498   scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2499   scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2500
2501   scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
2502   scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2503
2504   MockRead reads[] = {
2505     CreateMockRead(*settings_frame),
2506     CreateMockRead(*resp1, 3),
2507     CreateMockRead(*body1, 4),
2508     CreateMockRead(*resp2, 6),
2509     CreateMockRead(*body2, 7),
2510     CreateMockRead(*resp3, 9),
2511     CreateMockRead(*body3, 10),
2512     MockRead(ASYNC, 0, 11)  // EOF
2513   };
2514
2515   DeterministicSocketData data(reads, arraysize(reads),
2516                                writes, arraysize(writes));
2517   data.set_connect_data(connect_data);
2518   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2519
2520   CreateDeterministicNetworkSession();
2521
2522   base::WeakPtr<SpdySession> session =
2523       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2524
2525   // Read the settings frame.
2526   data.RunFor(1);
2527
2528   GURL url1(kDefaultURL);
2529   base::WeakPtr<SpdyStream> spdy_stream1 =
2530       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2531                                 session, url1, LOWEST, BoundNetLog());
2532   ASSERT_TRUE(spdy_stream1.get() != NULL);
2533   EXPECT_EQ(0u, spdy_stream1->stream_id());
2534   test::StreamDelegateDoNothing delegate1(spdy_stream1);
2535   spdy_stream1->SetDelegate(&delegate1);
2536
2537   TestCompletionCallback callback2;
2538   GURL url2(kDefaultURL);
2539   SpdyStreamRequest request2;
2540   ASSERT_EQ(ERR_IO_PENDING,
2541             request2.StartRequest(
2542                 SPDY_REQUEST_RESPONSE_STREAM,
2543                 session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2544
2545   TestCompletionCallback callback3;
2546   GURL url3(kDefaultURL);
2547   SpdyStreamRequest request3;
2548   ASSERT_EQ(ERR_IO_PENDING,
2549             request3.StartRequest(
2550                 SPDY_REQUEST_RESPONSE_STREAM,
2551                 session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2552
2553   EXPECT_EQ(0u, session->num_active_streams());
2554   EXPECT_EQ(1u, session->num_created_streams());
2555   EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2556
2557   scoped_ptr<SpdyHeaderBlock> headers(
2558       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2559   spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2560   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2561
2562   // Run until 1st stream is activated and then closed.
2563   EXPECT_EQ(0u, delegate1.stream_id());
2564   data.RunFor(4);
2565   EXPECT_EQ(NULL, spdy_stream1.get());
2566   EXPECT_EQ(1u, delegate1.stream_id());
2567
2568   EXPECT_EQ(0u, session->num_active_streams());
2569   EXPECT_EQ(0u, session->num_created_streams());
2570   EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2571
2572   // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2573   // create the 2nd stream.
2574   base::MessageLoop::current()->RunUntilIdle();
2575
2576   EXPECT_EQ(0u, session->num_active_streams());
2577   EXPECT_EQ(1u, session->num_created_streams());
2578   EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2579
2580   base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2581   test::StreamDelegateDoNothing delegate2(stream2);
2582   stream2->SetDelegate(&delegate2);
2583   scoped_ptr<SpdyHeaderBlock> headers2(
2584       spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2585   stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2586   EXPECT_TRUE(stream2->HasUrlFromHeaders());
2587
2588   // Run until 2nd stream is activated and then closed.
2589   EXPECT_EQ(0u, delegate2.stream_id());
2590   data.RunFor(3);
2591   EXPECT_EQ(NULL, stream2.get());
2592   EXPECT_EQ(3u, delegate2.stream_id());
2593
2594   EXPECT_EQ(0u, session->num_active_streams());
2595   EXPECT_EQ(0u, session->num_created_streams());
2596   EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2597
2598   // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2599   // create the 3rd stream.
2600   base::MessageLoop::current()->RunUntilIdle();
2601
2602   EXPECT_EQ(0u, session->num_active_streams());
2603   EXPECT_EQ(1u, session->num_created_streams());
2604   EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2605
2606   base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2607   test::StreamDelegateDoNothing delegate3(stream3);
2608   stream3->SetDelegate(&delegate3);
2609   scoped_ptr<SpdyHeaderBlock> headers3(
2610       spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2611   stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2612   EXPECT_TRUE(stream3->HasUrlFromHeaders());
2613
2614   // Run until 2nd stream is activated and then closed.
2615   EXPECT_EQ(0u, delegate3.stream_id());
2616   data.RunFor(3);
2617   EXPECT_EQ(NULL, stream3.get());
2618   EXPECT_EQ(5u, delegate3.stream_id());
2619
2620   EXPECT_EQ(0u, session->num_active_streams());
2621   EXPECT_EQ(0u, session->num_created_streams());
2622   EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2623
2624   data.RunFor(1);
2625 }
2626
2627 TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2628   session_deps_.host_resolver->set_synchronous_mode(true);
2629
2630   MockRead reads[] = {
2631     MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2632   };
2633
2634   StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2635   MockConnect connect_data(SYNCHRONOUS, OK);
2636
2637   data.set_connect_data(connect_data);
2638   session_deps_.socket_factory->AddSocketDataProvider(&data);
2639
2640   CreateNetworkSession();
2641
2642   base::WeakPtr<SpdySession> session =
2643       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2644
2645   // Leave room for only one more stream to be created.
2646   for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2647     base::WeakPtr<SpdyStream> spdy_stream =
2648         CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2649                                   session, test_url_, MEDIUM, BoundNetLog());
2650     ASSERT_TRUE(spdy_stream != NULL);
2651   }
2652
2653   GURL url1(kDefaultURL);
2654   base::WeakPtr<SpdyStream> spdy_stream1 =
2655       CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2656                                 session, url1, LOWEST, BoundNetLog());
2657   ASSERT_TRUE(spdy_stream1.get() != NULL);
2658   EXPECT_EQ(0u, spdy_stream1->stream_id());
2659
2660   TestCompletionCallback callback2;
2661   GURL url2(kDefaultURL);
2662   SpdyStreamRequest request2;
2663   ASSERT_EQ(ERR_IO_PENDING,
2664             request2.StartRequest(
2665                 SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2666                 callback2.callback()));
2667
2668   TestCompletionCallback callback3;
2669   GURL url3(kDefaultURL);
2670   SpdyStreamRequest request3;
2671   ASSERT_EQ(ERR_IO_PENDING,
2672             request3.StartRequest(
2673                 SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2674                 callback3.callback()));
2675
2676   EXPECT_EQ(0u, session->num_active_streams());
2677   EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2678   EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2679
2680   // Cancel the first stream; this will allow the second stream to be created.
2681   EXPECT_TRUE(spdy_stream1.get() != NULL);
2682   spdy_stream1->Cancel();
2683   EXPECT_EQ(NULL, spdy_stream1.get());
2684
2685   EXPECT_EQ(OK, callback2.WaitForResult());
2686   EXPECT_EQ(0u, session->num_active_streams());
2687   EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2688   EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2689
2690   // Cancel the second stream; this will allow the third stream to be created.
2691   base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2692   spdy_stream2->Cancel();
2693   EXPECT_EQ(NULL, spdy_stream2.get());
2694
2695   EXPECT_EQ(OK, callback3.WaitForResult());
2696   EXPECT_EQ(0u, session->num_active_streams());
2697   EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2698   EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2699
2700   // Cancel the third stream.
2701   base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2702   spdy_stream3->Cancel();
2703   EXPECT_EQ(NULL, spdy_stream3.get());
2704   EXPECT_EQ(0u, session->num_active_streams());
2705   EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
2706   EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2707 }
2708
2709 // Test that SpdySession::DoReadLoop reads data from the socket
2710 // without yielding.  This test makes 32k - 1 bytes of data available
2711 // on the socket for reading. It then verifies that it has read all
2712 // the available data without yielding.
2713 TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2714   MockConnect connect_data(SYNCHRONOUS, OK);
2715   BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2716
2717   scoped_ptr<SpdyFrame> req1(
2718       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2719   MockWrite writes[] = {
2720     CreateMockWrite(*req1, 0),
2721   };
2722
2723   // Build buffer of size kMaxReadBytesWithoutYielding / 4
2724   // (-spdy_data_frame_size).
2725   ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2726   const int kPayloadSize =
2727       kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2728   TestDataStream test_stream;
2729   scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2730   char* payload_data = payload->data();
2731   test_stream.GetBytes(payload_data, kPayloadSize);
2732
2733   scoped_ptr<SpdyFrame> partial_data_frame(
2734       framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2735   scoped_ptr<SpdyFrame> finish_data_frame(
2736       framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2737
2738   scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2739
2740   // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2741   // bytes.
2742   MockRead reads[] = {
2743     CreateMockRead(*resp1, 1),
2744     CreateMockRead(*partial_data_frame, 2),
2745     CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2746     CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2747     CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2748     MockRead(ASYNC, 0, 6)  // EOF
2749   };
2750
2751   // Create SpdySession and SpdyStream and send the request.
2752   DeterministicSocketData data(reads, arraysize(reads),
2753                                writes, arraysize(writes));
2754   data.set_connect_data(connect_data);
2755   session_deps_.host_resolver->set_synchronous_mode(true);
2756   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2757
2758   CreateDeterministicNetworkSession();
2759
2760   base::WeakPtr<SpdySession> session =
2761       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2762
2763   GURL url1(kDefaultURL);
2764   base::WeakPtr<SpdyStream> spdy_stream1 =
2765       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2766                                 session, url1, MEDIUM, BoundNetLog());
2767   ASSERT_TRUE(spdy_stream1.get() != NULL);
2768   EXPECT_EQ(0u, spdy_stream1->stream_id());
2769   test::StreamDelegateDoNothing delegate1(spdy_stream1);
2770   spdy_stream1->SetDelegate(&delegate1);
2771
2772   scoped_ptr<SpdyHeaderBlock> headers1(
2773       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2774   spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2775   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2776
2777   // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2778   // post a task.
2779   SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2780
2781   // Run until 1st read.
2782   EXPECT_EQ(0u, delegate1.stream_id());
2783   data.RunFor(2);
2784   EXPECT_EQ(1u, delegate1.stream_id());
2785   EXPECT_EQ(0u, observer.executed_count());
2786
2787   // Read all the data and verify SpdySession::DoReadLoop has not
2788   // posted a task.
2789   data.RunFor(4);
2790   EXPECT_EQ(NULL, spdy_stream1.get());
2791
2792   // Verify task observer's executed_count is zero, which indicates DoRead read
2793   // all the available data.
2794   EXPECT_EQ(0u, observer.executed_count());
2795   EXPECT_TRUE(data.at_write_eof());
2796   EXPECT_TRUE(data.at_read_eof());
2797 }
2798
2799 // Test that SpdySession::DoReadLoop yields while reading the
2800 // data. This test makes 32k + 1 bytes of data available on the socket
2801 // for reading. It then verifies that DoRead has yielded even though
2802 // there is data available for it to read (i.e, socket()->Read didn't
2803 // return ERR_IO_PENDING during socket reads).
2804 TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2805   MockConnect connect_data(SYNCHRONOUS, OK);
2806   BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2807
2808   scoped_ptr<SpdyFrame> req1(
2809       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2810   MockWrite writes[] = {
2811     CreateMockWrite(*req1, 0),
2812   };
2813
2814   // Build buffer of size kMaxReadBytesWithoutYielding / 4
2815   // (-spdy_data_frame_size).
2816   ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2817   const int kPayloadSize =
2818       kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2819   TestDataStream test_stream;
2820   scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2821   char* payload_data = payload->data();
2822   test_stream.GetBytes(payload_data, kPayloadSize);
2823
2824   scoped_ptr<SpdyFrame> partial_data_frame(
2825       framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2826   scoped_ptr<SpdyFrame> finish_data_frame(
2827       framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2828
2829   scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2830
2831   // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2832   MockRead reads[] = {
2833     CreateMockRead(*resp1, 1),
2834     CreateMockRead(*partial_data_frame, 2),
2835     CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2836     CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2837     CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2838     CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2839     MockRead(ASYNC, 0, 7)  // EOF
2840   };
2841
2842   // Create SpdySession and SpdyStream and send the request.
2843   DeterministicSocketData data(reads, arraysize(reads),
2844                                writes, arraysize(writes));
2845   data.set_connect_data(connect_data);
2846   session_deps_.host_resolver->set_synchronous_mode(true);
2847   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2848
2849   CreateDeterministicNetworkSession();
2850
2851   base::WeakPtr<SpdySession> session =
2852       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2853
2854   GURL url1(kDefaultURL);
2855   base::WeakPtr<SpdyStream> spdy_stream1 =
2856       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2857                                 session, url1, MEDIUM, BoundNetLog());
2858   ASSERT_TRUE(spdy_stream1.get() != NULL);
2859   EXPECT_EQ(0u, spdy_stream1->stream_id());
2860   test::StreamDelegateDoNothing delegate1(spdy_stream1);
2861   spdy_stream1->SetDelegate(&delegate1);
2862
2863   scoped_ptr<SpdyHeaderBlock> headers1(
2864       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2865   spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2866   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2867
2868   // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2869   // task.
2870   SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2871
2872   // Run until 1st read.
2873   EXPECT_EQ(0u, delegate1.stream_id());
2874   data.RunFor(2);
2875   EXPECT_EQ(1u, delegate1.stream_id());
2876   EXPECT_EQ(0u, observer.executed_count());
2877
2878   // Read all the data and verify SpdySession::DoReadLoop has posted a
2879   // task.
2880   data.RunFor(6);
2881   EXPECT_EQ(NULL, spdy_stream1.get());
2882
2883   // Verify task observer's executed_count is 1, which indicates DoRead has
2884   // posted only one task and thus yielded though there is data available for it
2885   // to read.
2886   EXPECT_EQ(1u, observer.executed_count());
2887   EXPECT_TRUE(data.at_write_eof());
2888   EXPECT_TRUE(data.at_read_eof());
2889 }
2890
2891 // Test that SpdySession::DoReadLoop() tests interactions of yielding
2892 // + async, by doing the following MockReads.
2893 //
2894 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2895 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2896 //
2897 // The above reads 26K synchronously. Since that is less that 32K, we
2898 // will attempt to read again. However, that DoRead() will return
2899 // ERR_IO_PENDING (because of async read), so DoReadLoop() will
2900 // yield. When we come back, DoRead() will read the results from the
2901 // async read, and rest of the data synchronously.
2902 TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2903   MockConnect connect_data(SYNCHRONOUS, OK);
2904   BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2905
2906   scoped_ptr<SpdyFrame> req1(
2907       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2908   MockWrite writes[] = {
2909     CreateMockWrite(*req1, 0),
2910   };
2911
2912   // Build buffer of size kMaxReadBytesWithoutYielding / 4
2913   // (-spdy_data_frame_size).
2914   ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2915   TestDataStream test_stream;
2916   const int kEightKPayloadSize =
2917       kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2918   scoped_refptr<net::IOBuffer> eightk_payload(
2919       new net::IOBuffer(kEightKPayloadSize));
2920   char* eightk_payload_data = eightk_payload->data();
2921   test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2922
2923   // Build buffer of 2k size.
2924   TestDataStream test_stream2;
2925   const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2926   scoped_refptr<net::IOBuffer> twok_payload(
2927       new net::IOBuffer(kTwoKPayloadSize));
2928   char* twok_payload_data = twok_payload->data();
2929   test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2930
2931   scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2932       1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2933   scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2934       1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2935   scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2936       1, "h", 1, DATA_FLAG_FIN));
2937
2938   scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2939
2940   MockRead reads[] = {
2941     CreateMockRead(*resp1, 1),
2942     CreateMockRead(*eightk_data_frame, 2),
2943     CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
2944     CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2945     CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
2946     CreateMockRead(*eightk_data_frame, 6, ASYNC),
2947     CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
2948     CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2949     CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2950     CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
2951     CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
2952     MockRead(ASYNC, 0, 12)  // EOF
2953   };
2954
2955   // Create SpdySession and SpdyStream and send the request.
2956   DeterministicSocketData data(reads, arraysize(reads),
2957                                writes, arraysize(writes));
2958   data.set_connect_data(connect_data);
2959   session_deps_.host_resolver->set_synchronous_mode(true);
2960   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2961
2962   CreateDeterministicNetworkSession();
2963
2964   base::WeakPtr<SpdySession> session =
2965       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2966
2967   GURL url1(kDefaultURL);
2968   base::WeakPtr<SpdyStream> spdy_stream1 =
2969       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2970                                 session, url1, MEDIUM, BoundNetLog());
2971   ASSERT_TRUE(spdy_stream1.get() != NULL);
2972   EXPECT_EQ(0u, spdy_stream1->stream_id());
2973   test::StreamDelegateDoNothing delegate1(spdy_stream1);
2974   spdy_stream1->SetDelegate(&delegate1);
2975
2976   scoped_ptr<SpdyHeaderBlock> headers1(
2977       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2978   spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2979   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2980
2981   // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2982   // posting of tasks.
2983   SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2984
2985   // Run until 1st read.
2986   EXPECT_EQ(0u, delegate1.stream_id());
2987   data.RunFor(2);
2988   EXPECT_EQ(1u, delegate1.stream_id());
2989   EXPECT_EQ(0u, observer.executed_count());
2990
2991   // Read all the data and verify SpdySession::DoReadLoop has posted a
2992   // task.
2993   data.RunFor(12);
2994   EXPECT_EQ(NULL, spdy_stream1.get());
2995
2996   // Verify task observer's executed_count is 1, which indicates DoRead has
2997   // posted only one task and thus yielded though there is data available for
2998   // it to read.
2999   EXPECT_EQ(1u, observer.executed_count());
3000   EXPECT_TRUE(data.at_write_eof());
3001   EXPECT_TRUE(data.at_read_eof());
3002 }
3003
3004 // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
3005 // nothing blows up.
3006 TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
3007   MockConnect connect_data(SYNCHRONOUS, OK);
3008   BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3009
3010   scoped_ptr<SpdyFrame> req1(
3011       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3012   MockWrite writes[] = {
3013     CreateMockWrite(*req1, 0),
3014   };
3015
3016   scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3017   scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
3018   scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
3019
3020   MockRead reads[] = {
3021     CreateMockRead(*resp1, 1),
3022     CreateMockRead(*body1, 2),
3023     CreateMockRead(*goaway, 3),
3024   };
3025
3026   // Create SpdySession and SpdyStream and send the request.
3027   DeterministicSocketData data(reads, arraysize(reads),
3028                                writes, arraysize(writes));
3029   data.set_connect_data(connect_data);
3030   session_deps_.host_resolver->set_synchronous_mode(true);
3031   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3032
3033   CreateDeterministicNetworkSession();
3034
3035   base::WeakPtr<SpdySession> session =
3036       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3037
3038   GURL url1(kDefaultURL);
3039   base::WeakPtr<SpdyStream> spdy_stream1 =
3040       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3041                                 session, url1, MEDIUM, BoundNetLog());
3042   test::StreamDelegateDoNothing delegate1(spdy_stream1);
3043   spdy_stream1->SetDelegate(&delegate1);
3044   ASSERT_TRUE(spdy_stream1.get() != NULL);
3045   EXPECT_EQ(0u, spdy_stream1->stream_id());
3046
3047   scoped_ptr<SpdyHeaderBlock> headers1(
3048       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3049   spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
3050   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3051
3052   // Run until 1st read.
3053   EXPECT_EQ(0u, spdy_stream1->stream_id());
3054   data.RunFor(1);
3055   EXPECT_EQ(1u, spdy_stream1->stream_id());
3056
3057   // Run until GoAway.
3058   data.RunFor(3);
3059   EXPECT_EQ(NULL, spdy_stream1.get());
3060   EXPECT_TRUE(data.at_write_eof());
3061   EXPECT_TRUE(data.at_read_eof());
3062   EXPECT_TRUE(session == NULL);
3063 }
3064
3065 // Within this framework, a SpdySession should be initialized with
3066 // flow control disabled for protocol version 2, with flow control
3067 // enabled only for streams for protocol version 3, and with flow
3068 // control enabled for streams and sessions for higher versions.
3069 TEST_P(SpdySessionTest, ProtocolNegotiation) {
3070   session_deps_.host_resolver->set_synchronous_mode(true);
3071
3072   MockConnect connect_data(SYNCHRONOUS, OK);
3073   MockRead reads[] = {
3074     MockRead(SYNCHRONOUS, 0, 0)  // EOF
3075   };
3076   StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3077   data.set_connect_data(connect_data);
3078   session_deps_.socket_factory->AddSocketDataProvider(&data);
3079
3080   CreateNetworkSession();
3081   base::WeakPtr<SpdySession> session =
3082       CreateFakeSpdySession(spdy_session_pool_, key_);
3083
3084   EXPECT_EQ(spdy_util_.spdy_version(),
3085             session->buffered_spdy_framer_->protocol_version());
3086   if (GetParam() == kProtoDeprecatedSPDY2) {
3087     EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state());
3088     EXPECT_EQ(0, session->session_send_window_size_);
3089     EXPECT_EQ(0, session->session_recv_window_size_);
3090   } else if (GetParam() == kProtoSPDY3) {
3091     EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
3092     EXPECT_EQ(0, session->session_send_window_size_);
3093     EXPECT_EQ(0, session->session_recv_window_size_);
3094   } else {
3095     EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3096               session->flow_control_state());
3097     EXPECT_EQ(kSpdySessionInitialWindowSize,
3098               session->session_send_window_size_);
3099     EXPECT_EQ(kSpdySessionInitialWindowSize,
3100               session->session_recv_window_size_);
3101   }
3102   EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3103 }
3104
3105 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3106 // pointers to the idle session are currently held.
3107 TEST_P(SpdySessionTest, CloseOneIdleConnection) {
3108   ClientSocketPoolManager::set_max_sockets_per_group(
3109       HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3110   ClientSocketPoolManager::set_max_sockets_per_pool(
3111       HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3112
3113   MockConnect connect_data(SYNCHRONOUS, OK);
3114   MockRead reads[] = {
3115     MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
3116   };
3117   StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3118   data.set_connect_data(connect_data);
3119   session_deps_.socket_factory->AddSocketDataProvider(&data);
3120   session_deps_.socket_factory->AddSocketDataProvider(&data);
3121
3122   CreateNetworkSession();
3123
3124   TransportClientSocketPool* pool =
3125       http_session_->GetTransportSocketPool(
3126           HttpNetworkSession::NORMAL_SOCKET_POOL);
3127
3128   // Create an idle SPDY session.
3129   SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3130                       PRIVACY_MODE_DISABLED);
3131   base::WeakPtr<SpdySession> session1 =
3132       CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3133   EXPECT_FALSE(pool->IsStalled());
3134
3135   // Trying to create a new connection should cause the pool to be stalled, and
3136   // post a task asynchronously to try and close the session.
3137   TestCompletionCallback callback2;
3138   HostPortPair host_port2("2.com", 80);
3139   scoped_refptr<TransportSocketParams> params2(
3140       new TransportSocketParams(
3141           host_port2, false, false, OnHostResolutionCallback(),
3142           TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3143   scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3144   EXPECT_EQ(ERR_IO_PENDING,
3145             connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3146                               callback2.callback(), pool, BoundNetLog()));
3147   EXPECT_TRUE(pool->IsStalled());
3148
3149   // The socket pool should close the connection asynchronously and establish a
3150   // new connection.
3151   EXPECT_EQ(OK, callback2.WaitForResult());
3152   EXPECT_FALSE(pool->IsStalled());
3153   EXPECT_TRUE(session1 == NULL);
3154 }
3155
3156 // Tests the case of a non-SPDY request closing an idle SPDY session when no
3157 // pointers to the idle session are currently held, in the case the SPDY session
3158 // has an alias.
3159 TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
3160   ClientSocketPoolManager::set_max_sockets_per_group(
3161       HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3162   ClientSocketPoolManager::set_max_sockets_per_pool(
3163       HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3164
3165   MockConnect connect_data(SYNCHRONOUS, OK);
3166   MockRead reads[] = {
3167     MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
3168   };
3169   StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3170   data.set_connect_data(connect_data);
3171   session_deps_.socket_factory->AddSocketDataProvider(&data);
3172   session_deps_.socket_factory->AddSocketDataProvider(&data);
3173
3174   session_deps_.host_resolver->set_synchronous_mode(true);
3175   session_deps_.host_resolver->rules()->AddIPLiteralRule(
3176       "1.com", "192.168.0.2", std::string());
3177   session_deps_.host_resolver->rules()->AddIPLiteralRule(
3178       "2.com", "192.168.0.2", std::string());
3179   // Not strictly needed.
3180   session_deps_.host_resolver->rules()->AddIPLiteralRule(
3181       "3.com", "192.168.0.3", std::string());
3182
3183   CreateNetworkSession();
3184
3185   TransportClientSocketPool* pool =
3186       http_session_->GetTransportSocketPool(
3187           HttpNetworkSession::NORMAL_SOCKET_POOL);
3188
3189   // Create an idle SPDY session.
3190   SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3191                       PRIVACY_MODE_DISABLED);
3192   base::WeakPtr<SpdySession> session1 =
3193       CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3194   EXPECT_FALSE(pool->IsStalled());
3195
3196   // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3197   SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3198                       PRIVACY_MODE_DISABLED);
3199   HostResolver::RequestInfo info(key2.host_port_pair());
3200   AddressList addresses;
3201   // Pre-populate the DNS cache, since a synchronous resolution is required in
3202   // order to create the alias.
3203   session_deps_.host_resolver->Resolve(info,
3204                                        DEFAULT_PRIORITY,
3205                                        &addresses,
3206                                        CompletionCallback(),
3207                                        NULL,
3208                                        BoundNetLog());
3209   // Get a session for |key2|, which should return the session created earlier.
3210   base::WeakPtr<SpdySession> session2 =
3211       spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3212   ASSERT_EQ(session1.get(), session2.get());
3213   EXPECT_FALSE(pool->IsStalled());
3214
3215   // Trying to create a new connection should cause the pool to be stalled, and
3216   // post a task asynchronously to try and close the session.
3217   TestCompletionCallback callback3;
3218   HostPortPair host_port3("3.com", 80);
3219   scoped_refptr<TransportSocketParams> params3(
3220       new TransportSocketParams(
3221           host_port3, false, false, OnHostResolutionCallback(),
3222           TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3223   scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3224   EXPECT_EQ(ERR_IO_PENDING,
3225             connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3226                               callback3.callback(), pool, BoundNetLog()));
3227   EXPECT_TRUE(pool->IsStalled());
3228
3229   // The socket pool should close the connection asynchronously and establish a
3230   // new connection.
3231   EXPECT_EQ(OK, callback3.WaitForResult());
3232   EXPECT_FALSE(pool->IsStalled());
3233   EXPECT_TRUE(session1 == NULL);
3234   EXPECT_TRUE(session2 == NULL);
3235 }
3236
3237 // Tests that when a SPDY session becomes idle, it closes itself if there is
3238 // a lower layer pool stalled on the per-pool socket limit.
3239 TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3240   ClientSocketPoolManager::set_max_sockets_per_group(
3241       HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3242   ClientSocketPoolManager::set_max_sockets_per_pool(
3243       HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3244
3245   MockConnect connect_data(SYNCHRONOUS, OK);
3246   MockRead reads[] = {
3247     MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
3248   };
3249   scoped_ptr<SpdyFrame> req1(
3250       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3251   scoped_ptr<SpdyFrame> cancel1(
3252       spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3253   MockWrite writes[] = {
3254     CreateMockWrite(*req1, 1),
3255     CreateMockWrite(*cancel1, 1),
3256   };
3257   StaticSocketDataProvider data(reads, arraysize(reads),
3258                                 writes, arraysize(writes));
3259   data.set_connect_data(connect_data);
3260   session_deps_.socket_factory->AddSocketDataProvider(&data);
3261
3262   MockRead http_reads[] = {
3263     MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
3264   };
3265   StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
3266                                      NULL, 0);
3267   http_data.set_connect_data(connect_data);
3268   session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3269
3270
3271   CreateNetworkSession();
3272
3273   TransportClientSocketPool* pool =
3274       http_session_->GetTransportSocketPool(
3275           HttpNetworkSession::NORMAL_SOCKET_POOL);
3276
3277   // Create a SPDY session.
3278   GURL url1(kDefaultURL);
3279   SpdySessionKey key1(HostPortPair(url1.host(), 80),
3280                       ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3281   base::WeakPtr<SpdySession> session1 =
3282       CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3283   EXPECT_FALSE(pool->IsStalled());
3284
3285   // Create a stream using the session, and send a request.
3286
3287   TestCompletionCallback callback1;
3288   base::WeakPtr<SpdyStream> spdy_stream1 =
3289       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3290                                 session1, url1, DEFAULT_PRIORITY,
3291                                 BoundNetLog());
3292   ASSERT_TRUE(spdy_stream1.get());
3293   test::StreamDelegateDoNothing delegate1(spdy_stream1);
3294   spdy_stream1->SetDelegate(&delegate1);
3295
3296   scoped_ptr<SpdyHeaderBlock> headers1(
3297       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3298   EXPECT_EQ(ERR_IO_PENDING,
3299             spdy_stream1->SendRequestHeaders(
3300                 headers1.Pass(), NO_MORE_DATA_TO_SEND));
3301   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3302
3303   base::MessageLoop::current()->RunUntilIdle();
3304
3305   // Trying to create a new connection should cause the pool to be stalled, and
3306   // post a task asynchronously to try and close the session.
3307   TestCompletionCallback callback2;
3308   HostPortPair host_port2("2.com", 80);
3309   scoped_refptr<TransportSocketParams> params2(
3310       new TransportSocketParams(
3311           host_port2, false, false, OnHostResolutionCallback(),
3312           TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3313   scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3314   EXPECT_EQ(ERR_IO_PENDING,
3315             connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3316                               callback2.callback(), pool, BoundNetLog()));
3317   EXPECT_TRUE(pool->IsStalled());
3318
3319   // Running the message loop should cause the socket pool to ask the SPDY
3320   // session to close an idle socket, but since the socket is in use, nothing
3321   // happens.
3322   base::RunLoop().RunUntilIdle();
3323   EXPECT_TRUE(pool->IsStalled());
3324   EXPECT_FALSE(callback2.have_result());
3325
3326   // Cancelling the request should result in the session's socket being
3327   // closed, since the pool is stalled.
3328   ASSERT_TRUE(spdy_stream1.get());
3329   spdy_stream1->Cancel();
3330   base::RunLoop().RunUntilIdle();
3331   ASSERT_FALSE(pool->IsStalled());
3332   EXPECT_EQ(OK, callback2.WaitForResult());
3333 }
3334
3335 // Verify that SpdySessionKey and therefore SpdySession is different when
3336 // privacy mode is enabled or disabled.
3337 TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3338   CreateDeterministicNetworkSession();
3339
3340   HostPortPair host_port_pair("www.google.com", 443);
3341   SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3342                                      PRIVACY_MODE_ENABLED);
3343   SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3344                                      PRIVACY_MODE_DISABLED);
3345
3346   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3347   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3348
3349   // Add SpdySession with PrivacyMode Enabled to the pool.
3350   base::WeakPtr<SpdySession> session_privacy_enabled =
3351       CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3352
3353   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3354   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3355
3356   // Add SpdySession with PrivacyMode Disabled to the pool.
3357   base::WeakPtr<SpdySession> session_privacy_disabled =
3358       CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3359
3360   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3361   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3362
3363   session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3364   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3365   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3366
3367   session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3368   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3369   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3370 }
3371
3372 // Delegate that creates another stream when its stream is closed.
3373 class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3374  public:
3375   StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3376                          const base::WeakPtr<SpdySession>& session)
3377       : StreamDelegateDoNothing(stream),
3378         session_(session) {}
3379
3380   ~StreamCreatingDelegate() override {}
3381
3382   void OnClose(int status) override {
3383     GURL url(kDefaultURL);
3384     ignore_result(
3385         CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3386                                   session_, url, MEDIUM, BoundNetLog()));
3387   }
3388
3389  private:
3390   const base::WeakPtr<SpdySession> session_;
3391 };
3392
3393 // Create another stream in response to a stream being reset. Nothing
3394 // should blow up. This is a regression test for
3395 // http://crbug.com/263690 .
3396 TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3397   session_deps_.host_resolver->set_synchronous_mode(true);
3398
3399   MockConnect connect_data(SYNCHRONOUS, OK);
3400
3401   scoped_ptr<SpdyFrame> req(
3402       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3403   MockWrite writes[] = {
3404     CreateMockWrite(*req, 0),
3405   };
3406
3407   scoped_ptr<SpdyFrame> rst(
3408       spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3409   MockRead reads[] = {
3410     CreateMockRead(*rst, 1),
3411     MockRead(ASYNC, 0, 2)  // EOF
3412   };
3413   DeterministicSocketData data(reads, arraysize(reads),
3414                                writes, arraysize(writes));
3415   data.set_connect_data(connect_data);
3416   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3417
3418   CreateDeterministicNetworkSession();
3419
3420   base::WeakPtr<SpdySession> session =
3421       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3422
3423   GURL url(kDefaultURL);
3424   base::WeakPtr<SpdyStream> spdy_stream =
3425       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3426                                 session, url, MEDIUM, BoundNetLog());
3427   ASSERT_TRUE(spdy_stream.get() != NULL);
3428   EXPECT_EQ(0u, spdy_stream->stream_id());
3429
3430   StreamCreatingDelegate delegate(spdy_stream, session);
3431   spdy_stream->SetDelegate(&delegate);
3432
3433   scoped_ptr<SpdyHeaderBlock> headers(
3434       spdy_util_.ConstructGetHeaderBlock(url.spec()));
3435   spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3436   EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3437
3438   EXPECT_EQ(0u, spdy_stream->stream_id());
3439
3440   data.RunFor(1);
3441
3442   EXPECT_EQ(1u, spdy_stream->stream_id());
3443
3444   // Cause the stream to be reset, which should cause another stream
3445   // to be created.
3446   data.RunFor(1);
3447
3448   EXPECT_EQ(NULL, spdy_stream.get());
3449   EXPECT_TRUE(delegate.StreamIsClosed());
3450   EXPECT_EQ(0u, session->num_active_streams());
3451   EXPECT_EQ(1u, session->num_created_streams());
3452 }
3453
3454 // The tests below are only for SPDY/3 and above.
3455
3456 TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3457   if (GetParam() < kProtoSPDY3)
3458     return;
3459
3460   // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3461   // gets sent.
3462   SettingsMap new_settings;
3463   int32 window_size = 1;
3464   new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3465       SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3466
3467   // Set up the socket so we read a SETTINGS frame that sets
3468   // INITIAL_WINDOW_SIZE.
3469   MockConnect connect_data(SYNCHRONOUS, OK);
3470   scoped_ptr<SpdyFrame> settings_frame(
3471       spdy_util_.ConstructSpdySettings(new_settings));
3472   MockRead reads[] = {
3473     CreateMockRead(*settings_frame, 0),
3474     MockRead(ASYNC, 0, 1)  // EOF
3475   };
3476
3477   scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3478   MockWrite writes[] = {
3479     CreateMockWrite(*settings_ack, 2),
3480   };
3481
3482   session_deps_.host_resolver->set_synchronous_mode(true);
3483
3484   DeterministicSocketData data(reads, arraysize(reads),
3485                                writes, arraysize(writes));
3486   data.set_connect_data(connect_data);
3487   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3488
3489   CreateDeterministicNetworkSession();
3490
3491   base::WeakPtr<SpdySession> session =
3492       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3493   base::WeakPtr<SpdyStream> spdy_stream1 =
3494       CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3495                                 session, test_url_, MEDIUM, BoundNetLog());
3496   ASSERT_TRUE(spdy_stream1.get() != NULL);
3497   TestCompletionCallback callback1;
3498   EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3499
3500   data.RunFor(1);  // Process the SETTINGS frame, but not the EOF
3501   base::MessageLoop::current()->RunUntilIdle();
3502   EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3503   EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3504
3505   // Release the first one, this will allow the second to be created.
3506   spdy_stream1->Cancel();
3507   EXPECT_EQ(NULL, spdy_stream1.get());
3508
3509   base::WeakPtr<SpdyStream> spdy_stream2 =
3510       CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3511                                 session, test_url_, MEDIUM, BoundNetLog());
3512   ASSERT_TRUE(spdy_stream2.get() != NULL);
3513   EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3514   spdy_stream2->Cancel();
3515   EXPECT_EQ(NULL, spdy_stream2.get());
3516 }
3517
3518 // The tests below are only for SPDY/3.1 and above.
3519
3520 // SpdySession::{Increase,Decrease}RecvWindowSize should properly
3521 // adjust the session receive window size for SPDY 3.1 and higher. In
3522 // addition, SpdySession::IncreaseRecvWindowSize should trigger
3523 // sending a WINDOW_UPDATE frame for a large enough delta.
3524 TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3525   if (GetParam() < kProtoSPDY31)
3526     return;
3527
3528   session_deps_.host_resolver->set_synchronous_mode(true);
3529
3530   const int32 delta_window_size = 100;
3531
3532   MockConnect connect_data(SYNCHRONOUS, OK);
3533   MockRead reads[] = {
3534     MockRead(ASYNC, 0, 1)  // EOF
3535   };
3536   scoped_ptr<SpdyFrame> window_update(
3537       spdy_util_.ConstructSpdyWindowUpdate(
3538           kSessionFlowControlStreamId,
3539           kSpdySessionInitialWindowSize + delta_window_size));
3540   MockWrite writes[] = {
3541     CreateMockWrite(*window_update, 0),
3542   };
3543   DeterministicSocketData data(reads, arraysize(reads),
3544                                writes, arraysize(writes));
3545   data.set_connect_data(connect_data);
3546   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3547
3548   CreateDeterministicNetworkSession();
3549   base::WeakPtr<SpdySession> session =
3550       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3551   EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3552             session->flow_control_state());
3553
3554   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3555   EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3556
3557   session->IncreaseRecvWindowSize(delta_window_size);
3558   EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3559             session->session_recv_window_size_);
3560   EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3561
3562   // Should trigger sending a WINDOW_UPDATE frame.
3563   session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize);
3564   EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size +
3565             kSpdySessionInitialWindowSize,
3566             session->session_recv_window_size_);
3567   EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3568
3569   data.RunFor(1);
3570
3571   // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3572   session->in_io_loop_ = true;
3573   session->DecreaseRecvWindowSize(
3574       kSpdySessionInitialWindowSize + delta_window_size +
3575       kSpdySessionInitialWindowSize);
3576   session->in_io_loop_ = false;
3577   EXPECT_EQ(0, session->session_recv_window_size_);
3578   EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3579 }
3580
3581 // SpdySession::{Increase,Decrease}SendWindowSize should properly
3582 // adjust the session send window size when the "enable_spdy_31" flag
3583 // is set.
3584 TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3585   if (GetParam() < kProtoSPDY31)
3586     return;
3587
3588   session_deps_.host_resolver->set_synchronous_mode(true);
3589
3590   MockConnect connect_data(SYNCHRONOUS, OK);
3591   MockRead reads[] = {
3592     MockRead(SYNCHRONOUS, 0, 0)  // EOF
3593   };
3594   StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3595   data.set_connect_data(connect_data);
3596   session_deps_.socket_factory->AddSocketDataProvider(&data);
3597
3598   CreateNetworkSession();
3599   base::WeakPtr<SpdySession> session =
3600       CreateFakeSpdySession(spdy_session_pool_, key_);
3601   EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3602             session->flow_control_state());
3603
3604   const int32 delta_window_size = 100;
3605
3606   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3607
3608   session->IncreaseSendWindowSize(delta_window_size);
3609   EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3610             session->session_send_window_size_);
3611
3612   session->DecreaseSendWindowSize(delta_window_size);
3613   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3614 }
3615
3616 // Incoming data for an inactive stream should not cause the session
3617 // receive window size to decrease, but it should cause the unacked
3618 // bytes to increase.
3619 TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3620   if (GetParam() < kProtoSPDY31)
3621     return;
3622
3623   session_deps_.host_resolver->set_synchronous_mode(true);
3624
3625   MockConnect connect_data(SYNCHRONOUS, OK);
3626   scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3627   MockRead reads[] = {
3628     CreateMockRead(*resp, 0),
3629     MockRead(ASYNC, 0, 1)  // EOF
3630   };
3631   DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3632   data.set_connect_data(connect_data);
3633   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3634
3635   CreateDeterministicNetworkSession();
3636   base::WeakPtr<SpdySession> session =
3637       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3638   EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3639             session->flow_control_state());
3640
3641   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3642   EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3643
3644   data.RunFor(1);
3645
3646   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3647   EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3648
3649   data.RunFor(1);
3650 }
3651
3652 // A delegate that drops any received data.
3653 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3654  public:
3655   DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3656                            base::StringPiece data)
3657       : StreamDelegateSendImmediate(stream, data) {}
3658
3659   ~DropReceivedDataDelegate() override {}
3660
3661   // Drop any received data.
3662   void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override {}
3663 };
3664
3665 // Send data back and forth but use a delegate that drops its received
3666 // data. The receive window should still increase to its original
3667 // value, i.e. we shouldn't "leak" receive window bytes.
3668 TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3669   if (GetParam() < kProtoSPDY31)
3670     return;
3671
3672   const char kStreamUrl[] = "http://www.google.com/";
3673
3674   const int32 msg_data_size = 100;
3675   const std::string msg_data(msg_data_size, 'a');
3676
3677   MockConnect connect_data(SYNCHRONOUS, OK);
3678
3679   scoped_ptr<SpdyFrame> req(
3680       spdy_util_.ConstructSpdyPost(
3681           kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3682   scoped_ptr<SpdyFrame> msg(
3683       spdy_util_.ConstructSpdyBodyFrame(
3684           1, msg_data.data(), msg_data_size, false));
3685   MockWrite writes[] = {
3686     CreateMockWrite(*req, 0),
3687     CreateMockWrite(*msg, 2),
3688   };
3689
3690   scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3691   scoped_ptr<SpdyFrame> echo(
3692       spdy_util_.ConstructSpdyBodyFrame(
3693           1, msg_data.data(), msg_data_size, false));
3694   scoped_ptr<SpdyFrame> window_update(
3695       spdy_util_.ConstructSpdyWindowUpdate(
3696           kSessionFlowControlStreamId, msg_data_size));
3697   MockRead reads[] = {
3698     CreateMockRead(*resp, 1),
3699     CreateMockRead(*echo, 3),
3700     MockRead(ASYNC, 0, 4)  // EOF
3701   };
3702
3703   // Create SpdySession and SpdyStream and send the request.
3704   DeterministicSocketData data(reads, arraysize(reads),
3705                                writes, arraysize(writes));
3706   data.set_connect_data(connect_data);
3707   session_deps_.host_resolver->set_synchronous_mode(true);
3708   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3709
3710   CreateDeterministicNetworkSession();
3711
3712   base::WeakPtr<SpdySession> session =
3713       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3714
3715   GURL url(kStreamUrl);
3716   base::WeakPtr<SpdyStream> stream =
3717       CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3718                                 session, url, MEDIUM, BoundNetLog());
3719   ASSERT_TRUE(stream.get() != NULL);
3720   EXPECT_EQ(0u, stream->stream_id());
3721
3722   DropReceivedDataDelegate delegate(stream, msg_data);
3723   stream->SetDelegate(&delegate);
3724
3725   scoped_ptr<SpdyHeaderBlock> headers(
3726       spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3727   EXPECT_EQ(ERR_IO_PENDING,
3728             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3729   EXPECT_TRUE(stream->HasUrlFromHeaders());
3730
3731   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3732   EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3733
3734   data.RunFor(4);
3735
3736   EXPECT_TRUE(data.at_write_eof());
3737   EXPECT_TRUE(data.at_read_eof());
3738
3739   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3740   EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3741
3742   stream->Close();
3743   EXPECT_EQ(NULL, stream.get());
3744
3745   EXPECT_EQ(OK, delegate.WaitForClose());
3746
3747   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3748   EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3749 }
3750
3751 // Send data back and forth but close the stream before its data frame
3752 // can be written to the socket. The send window should then increase
3753 // to its original value, i.e. we shouldn't "leak" send window bytes.
3754 TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3755   if (GetParam() < kProtoSPDY31)
3756     return;
3757
3758   const char kStreamUrl[] = "http://www.google.com/";
3759
3760   const int32 msg_data_size = 100;
3761   const std::string msg_data(msg_data_size, 'a');
3762
3763   MockConnect connect_data(SYNCHRONOUS, OK);
3764
3765   scoped_ptr<SpdyFrame> req(
3766       spdy_util_.ConstructSpdyPost(
3767           kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3768   MockWrite writes[] = {
3769     CreateMockWrite(*req, 0),
3770   };
3771
3772   scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3773   MockRead reads[] = {
3774     CreateMockRead(*resp, 1),
3775     MockRead(ASYNC, 0, 2)  // EOF
3776   };
3777
3778   // Create SpdySession and SpdyStream and send the request.
3779   DeterministicSocketData data(reads, arraysize(reads),
3780                                writes, arraysize(writes));
3781   data.set_connect_data(connect_data);
3782   session_deps_.host_resolver->set_synchronous_mode(true);
3783   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3784
3785   CreateDeterministicNetworkSession();
3786
3787   base::WeakPtr<SpdySession> session =
3788       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3789
3790   GURL url(kStreamUrl);
3791   base::WeakPtr<SpdyStream> stream =
3792       CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3793                                 session, url, MEDIUM, BoundNetLog());
3794   ASSERT_TRUE(stream.get() != NULL);
3795   EXPECT_EQ(0u, stream->stream_id());
3796
3797   test::StreamDelegateSendImmediate delegate(stream, msg_data);
3798   stream->SetDelegate(&delegate);
3799
3800   scoped_ptr<SpdyHeaderBlock> headers(
3801       spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3802   EXPECT_EQ(ERR_IO_PENDING,
3803             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3804   EXPECT_TRUE(stream->HasUrlFromHeaders());
3805
3806   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3807
3808   data.RunFor(1);
3809
3810   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3811
3812   data.RunFor(1);
3813
3814   EXPECT_TRUE(data.at_write_eof());
3815   EXPECT_TRUE(data.at_read_eof());
3816
3817   EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3818             session->session_send_window_size_);
3819
3820   // Closing the stream should increase the session's send window.
3821   stream->Close();
3822   EXPECT_EQ(NULL, stream.get());
3823
3824   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3825
3826   EXPECT_EQ(OK, delegate.WaitForClose());
3827 }
3828
3829 // Send data back and forth; the send and receive windows should
3830 // change appropriately.
3831 TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
3832   if (GetParam() < kProtoSPDY31)
3833     return;
3834
3835   const char kStreamUrl[] = "http://www.google.com/";
3836
3837   const int32 msg_data_size = 100;
3838   const std::string msg_data(msg_data_size, 'a');
3839
3840   MockConnect connect_data(SYNCHRONOUS, OK);
3841
3842   scoped_ptr<SpdyFrame> req(
3843       spdy_util_.ConstructSpdyPost(
3844           kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3845   scoped_ptr<SpdyFrame> msg(
3846       spdy_util_.ConstructSpdyBodyFrame(
3847           1, msg_data.data(), msg_data_size, false));
3848   MockWrite writes[] = {
3849     CreateMockWrite(*req, 0),
3850     CreateMockWrite(*msg, 2),
3851   };
3852
3853   scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3854   scoped_ptr<SpdyFrame> echo(
3855       spdy_util_.ConstructSpdyBodyFrame(
3856           1, msg_data.data(), msg_data_size, false));
3857   scoped_ptr<SpdyFrame> window_update(
3858       spdy_util_.ConstructSpdyWindowUpdate(
3859           kSessionFlowControlStreamId, msg_data_size));
3860   MockRead reads[] = {
3861     CreateMockRead(*resp, 1),
3862     CreateMockRead(*echo, 3),
3863     CreateMockRead(*window_update, 4),
3864     MockRead(ASYNC, 0, 5)  // EOF
3865   };
3866
3867   // Create SpdySession and SpdyStream and send the request.
3868   DeterministicSocketData data(reads, arraysize(reads),
3869                                writes, arraysize(writes));
3870   data.set_connect_data(connect_data);
3871   session_deps_.host_resolver->set_synchronous_mode(true);
3872   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3873
3874   CreateDeterministicNetworkSession();
3875
3876   base::WeakPtr<SpdySession> session =
3877       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3878
3879   GURL url(kStreamUrl);
3880   base::WeakPtr<SpdyStream> stream =
3881       CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3882                                 session, url, MEDIUM, BoundNetLog());
3883   ASSERT_TRUE(stream.get() != NULL);
3884   EXPECT_EQ(0u, stream->stream_id());
3885
3886   test::StreamDelegateSendImmediate delegate(stream, msg_data);
3887   stream->SetDelegate(&delegate);
3888
3889   scoped_ptr<SpdyHeaderBlock> headers(
3890       spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3891   EXPECT_EQ(ERR_IO_PENDING,
3892             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3893   EXPECT_TRUE(stream->HasUrlFromHeaders());
3894
3895   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3896   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3897   EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3898
3899   data.RunFor(1);
3900
3901   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3902   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3903   EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3904
3905   data.RunFor(1);
3906
3907   EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3908             session->session_send_window_size_);
3909   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3910   EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3911
3912   data.RunFor(1);
3913
3914   EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3915             session->session_send_window_size_);
3916   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3917   EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3918
3919   data.RunFor(1);
3920
3921   EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3922             session->session_send_window_size_);
3923   EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3924             session->session_recv_window_size_);
3925   EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3926
3927   data.RunFor(1);
3928
3929   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3930   EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3931             session->session_recv_window_size_);
3932   EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3933
3934   EXPECT_TRUE(data.at_write_eof());
3935   EXPECT_TRUE(data.at_read_eof());
3936
3937   EXPECT_EQ(msg_data, delegate.TakeReceivedData());
3938
3939   // Draining the delegate's read queue should increase the session's
3940   // receive window.
3941   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3942   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3943   EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3944
3945   stream->Close();
3946   EXPECT_EQ(NULL, stream.get());
3947
3948   EXPECT_EQ(OK, delegate.WaitForClose());
3949
3950   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3951   EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3952   EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3953 }
3954
3955 // Given a stall function and an unstall function, runs a test to make
3956 // sure that a stream resumes after unstall.
3957 void SpdySessionTest::RunResumeAfterUnstallTest(
3958     const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
3959     const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
3960         unstall_function) {
3961   const char kStreamUrl[] = "http://www.google.com/";
3962   GURL url(kStreamUrl);
3963
3964   session_deps_.host_resolver->set_synchronous_mode(true);
3965
3966   scoped_ptr<SpdyFrame> req(
3967       spdy_util_.ConstructSpdyPost(
3968           kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3969   scoped_ptr<SpdyFrame> body(
3970       spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3971   MockWrite writes[] = {
3972     CreateMockWrite(*req, 0),
3973     CreateMockWrite(*body, 1),
3974   };
3975
3976   scoped_ptr<SpdyFrame> resp(
3977       spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3978   scoped_ptr<SpdyFrame> echo(
3979       spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
3980   MockRead reads[] = {
3981     CreateMockRead(*resp, 2),
3982     MockRead(ASYNC, 0, 0, 3), // EOF
3983   };
3984
3985   DeterministicSocketData data(reads, arraysize(reads),
3986                                writes, arraysize(writes));
3987   MockConnect connect_data(SYNCHRONOUS, OK);
3988   data.set_connect_data(connect_data);
3989
3990   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3991
3992   CreateDeterministicNetworkSession();
3993   base::WeakPtr<SpdySession> session =
3994       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3995   EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3996             session->flow_control_state());
3997
3998   base::WeakPtr<SpdyStream> stream =
3999       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4000                                 session, url, LOWEST, BoundNetLog());
4001   ASSERT_TRUE(stream.get() != NULL);
4002
4003   test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
4004   stream->SetDelegate(&delegate);
4005
4006   EXPECT_FALSE(stream->HasUrlFromHeaders());
4007   EXPECT_FALSE(stream->send_stalled_by_flow_control());
4008
4009   scoped_ptr<SpdyHeaderBlock> headers(
4010       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4011   EXPECT_EQ(ERR_IO_PENDING,
4012             stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4013   EXPECT_TRUE(stream->HasUrlFromHeaders());
4014   EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
4015
4016   stall_function.Run(session.get(), stream.get());
4017
4018   data.RunFor(1);
4019
4020   EXPECT_TRUE(stream->send_stalled_by_flow_control());
4021
4022   unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
4023
4024   EXPECT_FALSE(stream->send_stalled_by_flow_control());
4025
4026   data.RunFor(3);
4027
4028   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
4029
4030   EXPECT_TRUE(delegate.send_headers_completed());
4031   EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
4032   EXPECT_EQ(std::string(), delegate.TakeReceivedData());
4033   EXPECT_TRUE(data.at_write_eof());
4034 }
4035
4036 // Run the resume-after-unstall test with all possible stall and
4037 // unstall sequences.
4038
4039 TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
4040   if (GetParam() < kProtoSPDY31)
4041     return;
4042
4043   RunResumeAfterUnstallTest(
4044       base::Bind(&SpdySessionTest::StallSessionOnly,
4045                  base::Unretained(this)),
4046       base::Bind(&SpdySessionTest::UnstallSessionOnly,
4047                  base::Unretained(this)));
4048 }
4049
4050 // Equivalent to
4051 // SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4052 TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
4053   if (GetParam() < kProtoSPDY31)
4054     return;
4055
4056   RunResumeAfterUnstallTest(
4057       base::Bind(&SpdySessionTest::StallStreamOnly,
4058                  base::Unretained(this)),
4059       base::Bind(&SpdySessionTest::UnstallStreamOnly,
4060                  base::Unretained(this)));
4061 }
4062
4063 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4064   if (GetParam() < kProtoSPDY31)
4065     return;
4066
4067   RunResumeAfterUnstallTest(
4068       base::Bind(&SpdySessionTest::StallSessionStream,
4069                  base::Unretained(this)),
4070       base::Bind(&SpdySessionTest::UnstallSessionStream,
4071                  base::Unretained(this)));
4072 }
4073
4074 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4075   if (GetParam() < kProtoSPDY31)
4076     return;
4077
4078   RunResumeAfterUnstallTest(
4079       base::Bind(&SpdySessionTest::StallStreamSession,
4080                  base::Unretained(this)),
4081       base::Bind(&SpdySessionTest::UnstallSessionStream,
4082                  base::Unretained(this)));
4083 }
4084
4085 TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4086   if (GetParam() < kProtoSPDY31)
4087     return;
4088
4089   RunResumeAfterUnstallTest(
4090       base::Bind(&SpdySessionTest::StallStreamSession,
4091                  base::Unretained(this)),
4092       base::Bind(&SpdySessionTest::UnstallStreamSession,
4093                  base::Unretained(this)));
4094 }
4095
4096 TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4097   if (GetParam() < kProtoSPDY31)
4098     return;
4099
4100   RunResumeAfterUnstallTest(
4101       base::Bind(&SpdySessionTest::StallSessionStream,
4102                  base::Unretained(this)),
4103       base::Bind(&SpdySessionTest::UnstallStreamSession,
4104                  base::Unretained(this)));
4105 }
4106
4107 // Cause a stall by reducing the flow control send window to 0. The
4108 // streams should resume in priority order when that window is then
4109 // increased.
4110 TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4111   if (GetParam() < kProtoSPDY31)
4112     return;
4113
4114   const char kStreamUrl[] = "http://www.google.com/";
4115   GURL url(kStreamUrl);
4116
4117   session_deps_.host_resolver->set_synchronous_mode(true);
4118
4119   scoped_ptr<SpdyFrame> req1(
4120       spdy_util_.ConstructSpdyPost(
4121           kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4122   scoped_ptr<SpdyFrame> req2(
4123       spdy_util_.ConstructSpdyPost(
4124           kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
4125   scoped_ptr<SpdyFrame> body1(
4126       spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4127   scoped_ptr<SpdyFrame> body2(
4128       spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4129   MockWrite writes[] = {
4130     CreateMockWrite(*req1, 0),
4131     CreateMockWrite(*req2, 1),
4132     CreateMockWrite(*body2, 2),
4133     CreateMockWrite(*body1, 3),
4134   };
4135
4136   scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4137   scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4138   MockRead reads[] = {
4139     CreateMockRead(*resp1, 4),
4140     CreateMockRead(*resp2, 5),
4141     MockRead(ASYNC, 0, 0, 6), // EOF
4142   };
4143
4144   DeterministicSocketData data(reads, arraysize(reads),
4145                                writes, arraysize(writes));
4146   MockConnect connect_data(SYNCHRONOUS, OK);
4147   data.set_connect_data(connect_data);
4148
4149   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4150
4151   CreateDeterministicNetworkSession();
4152   base::WeakPtr<SpdySession> session =
4153       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4154   EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4155             session->flow_control_state());
4156
4157   base::WeakPtr<SpdyStream> stream1 =
4158       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4159                                 session, url, LOWEST, BoundNetLog());
4160   ASSERT_TRUE(stream1.get() != NULL);
4161
4162   test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4163   stream1->SetDelegate(&delegate1);
4164
4165   EXPECT_FALSE(stream1->HasUrlFromHeaders());
4166
4167   base::WeakPtr<SpdyStream> stream2 =
4168       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4169                                 session, url, MEDIUM, BoundNetLog());
4170   ASSERT_TRUE(stream2.get() != NULL);
4171
4172   test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4173   stream2->SetDelegate(&delegate2);
4174
4175   EXPECT_FALSE(stream2->HasUrlFromHeaders());
4176
4177   EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4178   EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4179
4180   StallSessionSend(session.get());
4181
4182   scoped_ptr<SpdyHeaderBlock> headers1(
4183       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4184   EXPECT_EQ(ERR_IO_PENDING,
4185             stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4186   EXPECT_TRUE(stream1->HasUrlFromHeaders());
4187   EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4188
4189   data.RunFor(1);
4190   EXPECT_EQ(1u, stream1->stream_id());
4191   EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4192
4193   scoped_ptr<SpdyHeaderBlock> headers2(
4194       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4195   EXPECT_EQ(ERR_IO_PENDING,
4196             stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4197   EXPECT_TRUE(stream2->HasUrlFromHeaders());
4198   EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4199
4200   data.RunFor(1);
4201   EXPECT_EQ(3u, stream2->stream_id());
4202   EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4203
4204   // This should unstall only stream2.
4205   UnstallSessionSend(session.get(), kBodyDataSize);
4206
4207   EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4208   EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4209
4210   data.RunFor(1);
4211
4212   EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4213   EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4214
4215   // This should then unstall stream1.
4216   UnstallSessionSend(session.get(), kBodyDataSize);
4217
4218   EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4219   EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4220
4221   data.RunFor(4);
4222
4223   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4224   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4225
4226   EXPECT_TRUE(delegate1.send_headers_completed());
4227   EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4228   EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4229
4230   EXPECT_TRUE(delegate2.send_headers_completed());
4231   EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4232   EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4233
4234   EXPECT_TRUE(data.at_write_eof());
4235 }
4236
4237 // Delegate that closes a given stream after sending its body.
4238 class StreamClosingDelegate : public test::StreamDelegateWithBody {
4239  public:
4240   StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4241                         base::StringPiece data)
4242       : StreamDelegateWithBody(stream, data) {}
4243
4244   ~StreamClosingDelegate() override {}
4245
4246   void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4247     stream_to_close_ = stream_to_close;
4248   }
4249
4250   void OnDataSent() override {
4251     test::StreamDelegateWithBody::OnDataSent();
4252     if (stream_to_close_.get()) {
4253       stream_to_close_->Close();
4254       EXPECT_EQ(NULL, stream_to_close_.get());
4255     }
4256   }
4257
4258  private:
4259   base::WeakPtr<SpdyStream> stream_to_close_;
4260 };
4261
4262 // Cause a stall by reducing the flow control send window to
4263 // 0. Unstalling the session should properly handle deleted streams.
4264 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4265   if (GetParam() < kProtoSPDY31)
4266     return;
4267
4268   const char kStreamUrl[] = "http://www.google.com/";
4269   GURL url(kStreamUrl);
4270
4271   session_deps_.host_resolver->set_synchronous_mode(true);
4272
4273   scoped_ptr<SpdyFrame> req1(
4274       spdy_util_.ConstructSpdyPost(
4275           kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4276   scoped_ptr<SpdyFrame> req2(
4277       spdy_util_.ConstructSpdyPost(
4278           kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4279   scoped_ptr<SpdyFrame> req3(
4280       spdy_util_.ConstructSpdyPost(
4281           kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
4282   scoped_ptr<SpdyFrame> body2(
4283       spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4284   MockWrite writes[] = {
4285     CreateMockWrite(*req1, 0),
4286     CreateMockWrite(*req2, 1),
4287     CreateMockWrite(*req3, 2),
4288     CreateMockWrite(*body2, 3),
4289   };
4290
4291   scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4292   MockRead reads[] = {
4293     CreateMockRead(*resp2, 4),
4294     MockRead(ASYNC, 0, 0, 5), // EOF
4295   };
4296
4297   DeterministicSocketData data(reads, arraysize(reads),
4298                                writes, arraysize(writes));
4299   MockConnect connect_data(SYNCHRONOUS, OK);
4300   data.set_connect_data(connect_data);
4301
4302   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4303
4304   CreateDeterministicNetworkSession();
4305   base::WeakPtr<SpdySession> session =
4306       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4307   EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4308             session->flow_control_state());
4309
4310   base::WeakPtr<SpdyStream> stream1 =
4311       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4312                                 session, url, LOWEST, BoundNetLog());
4313   ASSERT_TRUE(stream1.get() != NULL);
4314
4315   test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4316   stream1->SetDelegate(&delegate1);
4317
4318   EXPECT_FALSE(stream1->HasUrlFromHeaders());
4319
4320   base::WeakPtr<SpdyStream> stream2 =
4321       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4322                                 session, url, LOWEST, BoundNetLog());
4323   ASSERT_TRUE(stream2.get() != NULL);
4324
4325   StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4326   stream2->SetDelegate(&delegate2);
4327
4328   EXPECT_FALSE(stream2->HasUrlFromHeaders());
4329
4330   base::WeakPtr<SpdyStream> stream3 =
4331       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4332                                 session, url, LOWEST, BoundNetLog());
4333   ASSERT_TRUE(stream3.get() != NULL);
4334
4335   test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4336   stream3->SetDelegate(&delegate3);
4337
4338   EXPECT_FALSE(stream3->HasUrlFromHeaders());
4339
4340   EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4341   EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4342   EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4343
4344   StallSessionSend(session.get());
4345
4346   scoped_ptr<SpdyHeaderBlock> headers1(
4347       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4348   EXPECT_EQ(ERR_IO_PENDING,
4349             stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4350   EXPECT_TRUE(stream1->HasUrlFromHeaders());
4351   EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4352
4353   data.RunFor(1);
4354   EXPECT_EQ(1u, stream1->stream_id());
4355   EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4356
4357   scoped_ptr<SpdyHeaderBlock> headers2(
4358       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4359   EXPECT_EQ(ERR_IO_PENDING,
4360             stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4361   EXPECT_TRUE(stream2->HasUrlFromHeaders());
4362   EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4363
4364   data.RunFor(1);
4365   EXPECT_EQ(3u, stream2->stream_id());
4366   EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4367
4368   scoped_ptr<SpdyHeaderBlock> headers3(
4369       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4370   EXPECT_EQ(ERR_IO_PENDING,
4371             stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4372   EXPECT_TRUE(stream3->HasUrlFromHeaders());
4373   EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4374
4375   data.RunFor(1);
4376   EXPECT_EQ(5u, stream3->stream_id());
4377   EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4378
4379   SpdyStreamId stream_id1 = stream1->stream_id();
4380   SpdyStreamId stream_id2 = stream2->stream_id();
4381   SpdyStreamId stream_id3 = stream3->stream_id();
4382
4383   // Close stream1 preemptively.
4384   session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4385   EXPECT_EQ(NULL, stream1.get());
4386
4387   EXPECT_FALSE(session->IsStreamActive(stream_id1));
4388   EXPECT_TRUE(session->IsStreamActive(stream_id2));
4389   EXPECT_TRUE(session->IsStreamActive(stream_id3));
4390
4391   // Unstall stream2, which should then close stream3.
4392   delegate2.set_stream_to_close(stream3);
4393   UnstallSessionSend(session.get(), kBodyDataSize);
4394
4395   data.RunFor(1);
4396   EXPECT_EQ(NULL, stream3.get());
4397
4398   EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4399   EXPECT_FALSE(session->IsStreamActive(stream_id1));
4400   EXPECT_TRUE(session->IsStreamActive(stream_id2));
4401   EXPECT_FALSE(session->IsStreamActive(stream_id3));
4402
4403   data.RunFor(2);
4404   EXPECT_EQ(NULL, stream2.get());
4405
4406   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4407   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4408   EXPECT_EQ(OK, delegate3.WaitForClose());
4409
4410   EXPECT_TRUE(delegate1.send_headers_completed());
4411   EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4412
4413   EXPECT_TRUE(delegate2.send_headers_completed());
4414   EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4415   EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4416
4417   EXPECT_TRUE(delegate3.send_headers_completed());
4418   EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4419
4420   EXPECT_TRUE(data.at_write_eof());
4421 }
4422
4423 // Cause a stall by reducing the flow control send window to
4424 // 0. Unstalling the session should properly handle the session itself
4425 // being closed.
4426 TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4427   if (GetParam() < kProtoSPDY31)
4428     return;
4429
4430   const char kStreamUrl[] = "http://www.google.com/";
4431   GURL url(kStreamUrl);
4432
4433   session_deps_.host_resolver->set_synchronous_mode(true);
4434
4435   scoped_ptr<SpdyFrame> req1(
4436       spdy_util_.ConstructSpdyPost(
4437           kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4438   scoped_ptr<SpdyFrame> req2(
4439       spdy_util_.ConstructSpdyPost(
4440           kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4441   scoped_ptr<SpdyFrame> body1(
4442       spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4443   MockWrite writes[] = {
4444     CreateMockWrite(*req1, 0),
4445     CreateMockWrite(*req2, 1),
4446   };
4447
4448   MockRead reads[] = {
4449     MockRead(ASYNC, 0, 0, 2), // EOF
4450   };
4451
4452   DeterministicSocketData data(reads, arraysize(reads),
4453                                writes, arraysize(writes));
4454   MockConnect connect_data(SYNCHRONOUS, OK);
4455   data.set_connect_data(connect_data);
4456
4457   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4458
4459   CreateDeterministicNetworkSession();
4460   base::WeakPtr<SpdySession> session =
4461       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4462   EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4463             session->flow_control_state());
4464
4465   base::WeakPtr<SpdyStream> stream1 =
4466       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4467                                 session, url, LOWEST, BoundNetLog());
4468   ASSERT_TRUE(stream1.get() != NULL);
4469
4470   test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4471   stream1->SetDelegate(&delegate1);
4472
4473   EXPECT_FALSE(stream1->HasUrlFromHeaders());
4474
4475   base::WeakPtr<SpdyStream> stream2 =
4476       CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4477                                 session, url, LOWEST, BoundNetLog());
4478   ASSERT_TRUE(stream2.get() != NULL);
4479
4480   test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4481   stream2->SetDelegate(&delegate2);
4482
4483   EXPECT_FALSE(stream2->HasUrlFromHeaders());
4484
4485   EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4486   EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4487
4488   StallSessionSend(session.get());
4489
4490   scoped_ptr<SpdyHeaderBlock> headers1(
4491       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4492   EXPECT_EQ(ERR_IO_PENDING,
4493             stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4494   EXPECT_TRUE(stream1->HasUrlFromHeaders());
4495   EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4496
4497   data.RunFor(1);
4498   EXPECT_EQ(1u, stream1->stream_id());
4499   EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4500
4501   scoped_ptr<SpdyHeaderBlock> headers2(
4502       spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4503   EXPECT_EQ(ERR_IO_PENDING,
4504             stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4505   EXPECT_TRUE(stream2->HasUrlFromHeaders());
4506   EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4507
4508   data.RunFor(1);
4509   EXPECT_EQ(3u, stream2->stream_id());
4510   EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4511
4512   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4513
4514   // Unstall stream1.
4515   UnstallSessionSend(session.get(), kBodyDataSize);
4516
4517   // Close the session (since we can't do it from within the delegate
4518   // method, since it's in the stream's loop).
4519   session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4520   base::RunLoop().RunUntilIdle();
4521   EXPECT_TRUE(session == NULL);
4522
4523   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4524
4525   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4526   EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4527
4528   EXPECT_TRUE(delegate1.send_headers_completed());
4529   EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4530
4531   EXPECT_TRUE(delegate2.send_headers_completed());
4532   EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4533
4534   EXPECT_TRUE(data.at_write_eof());
4535 }
4536
4537 TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4538   if (GetParam() < kProtoSPDY31)
4539     return;
4540
4541   MockConnect connect_data(SYNCHRONOUS, OK);
4542
4543   scoped_ptr<SpdyFrame> req(
4544       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4545   scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4546       0,
4547       GOAWAY_FLOW_CONTROL_ERROR,
4548       "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4549       "the receive window size of 1"));
4550   MockWrite writes[] = {
4551       CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
4552   };
4553
4554   scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4555   scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4556   MockRead reads[] = {
4557       CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
4558   };
4559
4560   DeterministicSocketData data(
4561       reads, arraysize(reads), writes, arraysize(writes));
4562   data.set_connect_data(connect_data);
4563   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4564
4565   CreateDeterministicNetworkSession();
4566
4567   base::WeakPtr<SpdySession> session =
4568       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4569
4570   GURL url(kDefaultURL);
4571   base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4572       SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
4573   ASSERT_TRUE(spdy_stream.get() != NULL);
4574   test::StreamDelegateDoNothing delegate(spdy_stream);
4575   spdy_stream->SetDelegate(&delegate);
4576
4577   scoped_ptr<SpdyHeaderBlock> headers(
4578       spdy_util_.ConstructGetHeaderBlock(url.spec()));
4579   spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4580
4581   data.RunFor(1);  // Write request.
4582
4583   // Put session on the edge of overflowing it's recv window.
4584   session->session_recv_window_size_ = 1;
4585
4586   // Read response headers & body. Body overflows the session window, and a
4587   // goaway is written.
4588   data.RunFor(3);
4589   base::MessageLoop::current()->RunUntilIdle();
4590
4591   EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4592   EXPECT_TRUE(session == NULL);
4593 }
4594
4595 TEST_P(SpdySessionTest, SplitHeaders) {
4596   GURL kStreamUrl("http://www.google.com/foo.dat");
4597   SpdyHeaderBlock headers;
4598   spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4599   headers["alpha"] = "beta";
4600
4601   SpdyHeaderBlock request_headers;
4602   SpdyHeaderBlock response_headers;
4603
4604   SplitPushedHeadersToRequestAndResponse(
4605       headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4606
4607   SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4608   std::string alpha_val =
4609       (it == response_headers.end()) ? std::string() : it->second;
4610   EXPECT_EQ("beta", alpha_val);
4611
4612   GURL request_url =
4613       GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4614   EXPECT_EQ(kStreamUrl, request_url);
4615 }
4616
4617 // Regression. Sorta. Push streams and client streams were sharing a single
4618 // limit for a long time.
4619 TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4620   SettingsMap new_settings;
4621   new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4622       SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4623   scoped_ptr<SpdyFrame> settings_frame(
4624       spdy_util_.ConstructSpdySettings(new_settings));
4625   scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4626       NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4627   MockRead reads[] = {
4628       CreateMockRead(*settings_frame), CreateMockRead(*pushed, 3),
4629       MockRead(ASYNC, 0, 4),
4630   };
4631
4632   scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4633   scoped_ptr<SpdyFrame> req(
4634       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4635   MockWrite writes[] = {
4636       CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4637   };
4638
4639   DeterministicSocketData data(
4640       reads, arraysize(reads), writes, arraysize(writes));
4641   MockConnect connect_data(SYNCHRONOUS, OK);
4642   data.set_connect_data(connect_data);
4643   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4644
4645   CreateDeterministicNetworkSession();
4646
4647   base::WeakPtr<SpdySession> session =
4648       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4649
4650   // Read the settings frame.
4651   data.RunFor(1);
4652
4653   GURL url1(kDefaultURL);
4654   base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4655       SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4656   ASSERT_TRUE(spdy_stream1.get() != NULL);
4657   EXPECT_EQ(0u, spdy_stream1->stream_id());
4658   test::StreamDelegateDoNothing delegate1(spdy_stream1);
4659   spdy_stream1->SetDelegate(&delegate1);
4660
4661   EXPECT_EQ(0u, session->num_active_streams());
4662   EXPECT_EQ(1u, session->num_created_streams());
4663   EXPECT_EQ(0u, session->num_pushed_streams());
4664   EXPECT_EQ(0u, session->num_active_pushed_streams());
4665
4666   scoped_ptr<SpdyHeaderBlock> headers(
4667       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4668   spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4669   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4670
4671   // Run until 1st stream is activated.
4672   EXPECT_EQ(0u, delegate1.stream_id());
4673   data.RunFor(2);
4674   EXPECT_EQ(1u, delegate1.stream_id());
4675   EXPECT_EQ(1u, session->num_active_streams());
4676   EXPECT_EQ(0u, session->num_created_streams());
4677   EXPECT_EQ(0u, session->num_pushed_streams());
4678   EXPECT_EQ(0u, session->num_active_pushed_streams());
4679
4680   // Run until pushed stream is created.
4681   data.RunFor(1);
4682   EXPECT_EQ(2u, session->num_active_streams());
4683   EXPECT_EQ(0u, session->num_created_streams());
4684   EXPECT_EQ(1u, session->num_pushed_streams());
4685   EXPECT_EQ(1u, session->num_active_pushed_streams());
4686
4687   // Second stream should not be stalled, although we have 2 active streams, but
4688   // one of them is push stream and should not be taken into account when we
4689   // create streams on the client.
4690   base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4691       SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4692   EXPECT_TRUE(spdy_stream2.get() != NULL);
4693   EXPECT_EQ(2u, session->num_active_streams());
4694   EXPECT_EQ(1u, session->num_created_streams());
4695   EXPECT_EQ(1u, session->num_pushed_streams());
4696   EXPECT_EQ(1u, session->num_active_pushed_streams());
4697
4698   // Read EOF.
4699   data.RunFor(1);
4700 }
4701
4702 TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4703   scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4704       NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4705   scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4706       NULL, 0, 4, 1, "http://www.google.com/b.dat"));
4707   MockRead reads[] = {
4708       CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4709       MockRead(ASYNC, 0, 4),
4710   };
4711
4712   scoped_ptr<SpdyFrame> req(
4713       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4714   scoped_ptr<SpdyFrame> rst(
4715       spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4716   MockWrite writes[] = {
4717       CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4718   };
4719
4720   DeterministicSocketData data(
4721       reads, arraysize(reads), writes, arraysize(writes));
4722   MockConnect connect_data(SYNCHRONOUS, OK);
4723   data.set_connect_data(connect_data);
4724   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4725
4726   CreateDeterministicNetworkSession();
4727
4728   base::WeakPtr<SpdySession> session =
4729       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4730   session->set_max_concurrent_pushed_streams(1);
4731
4732   GURL url1(kDefaultURL);
4733   base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4734       SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4735   ASSERT_TRUE(spdy_stream1.get() != NULL);
4736   EXPECT_EQ(0u, spdy_stream1->stream_id());
4737   test::StreamDelegateDoNothing delegate1(spdy_stream1);
4738   spdy_stream1->SetDelegate(&delegate1);
4739
4740   EXPECT_EQ(0u, session->num_active_streams());
4741   EXPECT_EQ(1u, session->num_created_streams());
4742   EXPECT_EQ(0u, session->num_pushed_streams());
4743   EXPECT_EQ(0u, session->num_active_pushed_streams());
4744
4745   scoped_ptr<SpdyHeaderBlock> headers(
4746       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4747   spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4748   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4749
4750   // Run until 1st stream is activated.
4751   EXPECT_EQ(0u, delegate1.stream_id());
4752   data.RunFor(1);
4753   EXPECT_EQ(1u, delegate1.stream_id());
4754   EXPECT_EQ(1u, session->num_active_streams());
4755   EXPECT_EQ(0u, session->num_created_streams());
4756   EXPECT_EQ(0u, session->num_pushed_streams());
4757   EXPECT_EQ(0u, session->num_active_pushed_streams());
4758
4759   // Run until pushed stream is created.
4760   data.RunFor(1);
4761   EXPECT_EQ(2u, session->num_active_streams());
4762   EXPECT_EQ(0u, session->num_created_streams());
4763   EXPECT_EQ(1u, session->num_pushed_streams());
4764   EXPECT_EQ(1u, session->num_active_pushed_streams());
4765
4766   // Reset incoming pushed stream.
4767   data.RunFor(2);
4768   EXPECT_EQ(2u, session->num_active_streams());
4769   EXPECT_EQ(0u, session->num_created_streams());
4770   EXPECT_EQ(1u, session->num_pushed_streams());
4771   EXPECT_EQ(1u, session->num_active_pushed_streams());
4772
4773   // Read EOF.
4774   data.RunFor(1);
4775 }
4776
4777 TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4778   // Streams in reserved remote state exist only in SPDY4.
4779   if (spdy_util_.spdy_version() < SPDY4)
4780     return;
4781
4782   scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4783       NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4784   scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4785   spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
4786                                  push_headers.get());
4787   scoped_ptr<SpdyFrame> push_b(
4788       spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4789   scoped_ptr<SpdyFrame> headers_b(
4790       spdy_util_.ConstructSpdyPushHeaders(4, NULL, 0));
4791   MockRead reads[] = {
4792       CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4793       CreateMockRead(*headers_b, 3), MockRead(ASYNC, 0, 5),
4794   };
4795
4796   scoped_ptr<SpdyFrame> req(
4797       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4798   scoped_ptr<SpdyFrame> rst(
4799       spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4800   MockWrite writes[] = {
4801       CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
4802   };
4803
4804   DeterministicSocketData data(
4805       reads, arraysize(reads), writes, arraysize(writes));
4806   MockConnect connect_data(SYNCHRONOUS, OK);
4807   data.set_connect_data(connect_data);
4808   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4809
4810   CreateDeterministicNetworkSession();
4811
4812   base::WeakPtr<SpdySession> session =
4813       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4814   session->set_max_concurrent_pushed_streams(1);
4815
4816   GURL url1(kDefaultURL);
4817   base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4818       SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4819   ASSERT_TRUE(spdy_stream1.get() != NULL);
4820   EXPECT_EQ(0u, spdy_stream1->stream_id());
4821   test::StreamDelegateDoNothing delegate1(spdy_stream1);
4822   spdy_stream1->SetDelegate(&delegate1);
4823
4824   EXPECT_EQ(0u, session->num_active_streams());
4825   EXPECT_EQ(1u, session->num_created_streams());
4826   EXPECT_EQ(0u, session->num_pushed_streams());
4827   EXPECT_EQ(0u, session->num_active_pushed_streams());
4828
4829   scoped_ptr<SpdyHeaderBlock> headers(
4830       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4831   spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4832   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4833
4834   // Run until 1st stream is activated.
4835   EXPECT_EQ(0u, delegate1.stream_id());
4836   data.RunFor(1);
4837   EXPECT_EQ(1u, delegate1.stream_id());
4838   EXPECT_EQ(1u, session->num_active_streams());
4839   EXPECT_EQ(0u, session->num_created_streams());
4840   EXPECT_EQ(0u, session->num_pushed_streams());
4841   EXPECT_EQ(0u, session->num_active_pushed_streams());
4842
4843   // Run until pushed stream is created.
4844   data.RunFor(1);
4845   EXPECT_EQ(2u, session->num_active_streams());
4846   EXPECT_EQ(0u, session->num_created_streams());
4847   EXPECT_EQ(1u, session->num_pushed_streams());
4848   EXPECT_EQ(1u, session->num_active_pushed_streams());
4849
4850   // Accept promised stream. It should not count towards pushed stream limit.
4851   data.RunFor(1);
4852   EXPECT_EQ(3u, session->num_active_streams());
4853   EXPECT_EQ(0u, session->num_created_streams());
4854   EXPECT_EQ(2u, session->num_pushed_streams());
4855   EXPECT_EQ(1u, session->num_active_pushed_streams());
4856
4857   // Reset last pushed stream upon headers reception as it is going to be 2nd,
4858   // while we accept only one.
4859   data.RunFor(2);
4860   EXPECT_EQ(2u, session->num_active_streams());
4861   EXPECT_EQ(0u, session->num_created_streams());
4862   EXPECT_EQ(1u, session->num_pushed_streams());
4863   EXPECT_EQ(1u, session->num_active_pushed_streams());
4864
4865   // Read EOF.
4866   data.RunFor(1);
4867 }
4868
4869 TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
4870   // Streams in reserved remote state exist only in SPDY4.
4871   if (spdy_util_.spdy_version() < SPDY4)
4872     return;
4873
4874   const char kPushedUrl[] = "http://www.google.com/a.dat";
4875   scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4876   spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
4877   scoped_ptr<SpdyFrame> push_promise(
4878       spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
4879   scoped_ptr<SpdyFrame> headers_frame(
4880       spdy_util_.ConstructSpdyPushHeaders(2, NULL, 0));
4881   MockRead reads[] = {
4882       CreateMockRead(*push_promise, 1), CreateMockRead(*headers_frame, 2),
4883       MockRead(ASYNC, 0, 4),
4884   };
4885
4886   scoped_ptr<SpdyFrame> req(
4887       spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4888   scoped_ptr<SpdyFrame> rst(
4889       spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
4890   MockWrite writes[] = {
4891       CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4892   };
4893
4894   DeterministicSocketData data(
4895       reads, arraysize(reads), writes, arraysize(writes));
4896   MockConnect connect_data(SYNCHRONOUS, OK);
4897   data.set_connect_data(connect_data);
4898   session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4899
4900   CreateDeterministicNetworkSession();
4901
4902   base::WeakPtr<SpdySession> session =
4903       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4904
4905   GURL url1(kDefaultURL);
4906   base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4907       SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4908   ASSERT_TRUE(spdy_stream1.get() != NULL);
4909   EXPECT_EQ(0u, spdy_stream1->stream_id());
4910   test::StreamDelegateDoNothing delegate1(spdy_stream1);
4911   spdy_stream1->SetDelegate(&delegate1);
4912
4913   EXPECT_EQ(0u, session->num_active_streams());
4914   EXPECT_EQ(1u, session->num_created_streams());
4915   EXPECT_EQ(0u, session->num_pushed_streams());
4916   EXPECT_EQ(0u, session->num_active_pushed_streams());
4917
4918   scoped_ptr<SpdyHeaderBlock> headers(
4919       spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4920   spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4921   EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4922
4923   // Run until 1st stream is activated.
4924   EXPECT_EQ(0u, delegate1.stream_id());
4925   data.RunFor(1);
4926   EXPECT_EQ(1u, delegate1.stream_id());
4927   EXPECT_EQ(1u, session->num_active_streams());
4928   EXPECT_EQ(0u, session->num_created_streams());
4929   EXPECT_EQ(0u, session->num_pushed_streams());
4930   EXPECT_EQ(0u, session->num_active_pushed_streams());
4931
4932   // Run until pushed stream is created.
4933   data.RunFor(1);
4934   EXPECT_EQ(2u, session->num_active_streams());
4935   EXPECT_EQ(0u, session->num_created_streams());
4936   EXPECT_EQ(1u, session->num_pushed_streams());
4937   EXPECT_EQ(0u, session->num_active_pushed_streams());
4938
4939   base::WeakPtr<SpdyStream> pushed_stream;
4940   int rv =
4941       session->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
4942   ASSERT_EQ(OK, rv);
4943   ASSERT_TRUE(pushed_stream.get() != NULL);
4944   test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
4945   pushed_stream->SetDelegate(&delegate2);
4946
4947   // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4948   // that all our counters are in consistent state.
4949   data.RunFor(1);
4950   EXPECT_EQ(1u, session->num_active_streams());
4951   EXPECT_EQ(0u, session->num_created_streams());
4952   EXPECT_EQ(0u, session->num_pushed_streams());
4953   EXPECT_EQ(0u, session->num_active_pushed_streams());
4954
4955   // Read EOF.
4956   data.RunFor(2);
4957 }
4958
4959 TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
4960   session_deps_.host_resolver->set_synchronous_mode(true);
4961
4962   MockRead reads[] = {
4963       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
4964   };
4965
4966   StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
4967
4968   MockConnect connect_data(SYNCHRONOUS, OK);
4969   data.set_connect_data(connect_data);
4970   session_deps_.socket_factory->AddSocketDataProvider(&data);
4971
4972   CreateNetworkSession();
4973   base::WeakPtr<SpdySession> session =
4974       CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4975
4976   session->stream_hi_water_mark_ = 5;
4977   // Low client (odd) ids are fine.
4978   EXPECT_TRUE(session->OnUnknownFrame(3, 0));
4979   // Client id exceeding watermark.
4980   EXPECT_FALSE(session->OnUnknownFrame(9, 0));
4981
4982   session->last_accepted_push_stream_id_ = 6;
4983   // Low server (even) ids are fine.
4984   EXPECT_TRUE(session->OnUnknownFrame(2, 0));
4985   // Server id exceeding last accepted id.
4986   EXPECT_FALSE(session->OnUnknownFrame(8, 0));
4987 }
4988
4989 TEST(MapFramerErrorToProtocolError, MapsValues) {
4990   CHECK_EQ(
4991       SPDY_ERROR_INVALID_CONTROL_FRAME,
4992       MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4993   CHECK_EQ(
4994       SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4995       MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4996   CHECK_EQ(
4997       SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
4998       MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
4999   CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
5000            MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
5001 }
5002
5003 TEST(MapFramerErrorToNetError, MapsValue) {
5004   CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
5005            MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
5006   CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5007            MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
5008   CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5009            MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
5010   CHECK_EQ(
5011       ERR_SPDY_FRAME_SIZE_ERROR,
5012       MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
5013 }
5014
5015 TEST(MapRstStreamStatusToProtocolError, MapsValues) {
5016   CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
5017            MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
5018   CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
5019            MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
5020   CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
5021            MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
5022 }
5023
5024 TEST(MapNetErrorToGoAwayStatus, MapsValue) {
5025   CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
5026            MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
5027   CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
5028            MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
5029   CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
5030            MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
5031   CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
5032            MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
5033   CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
5034            MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
5035   CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
5036 }
5037
5038 TEST(CanPoolTest, CanPool) {
5039   // Load a cert that is valid for:
5040   //   www.example.org
5041   //   mail.example.org
5042   //   www.example.com
5043
5044   TransportSecurityState tss;
5045   SSLInfo ssl_info;
5046   ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5047                                      "spdy_pooling.pem");
5048
5049   EXPECT_TRUE(SpdySession::CanPool(
5050       &tss, ssl_info, "www.example.org", "www.example.org"));
5051   EXPECT_TRUE(SpdySession::CanPool(
5052       &tss, ssl_info, "www.example.org", "mail.example.org"));
5053   EXPECT_TRUE(SpdySession::CanPool(
5054       &tss, ssl_info, "www.example.org", "mail.example.com"));
5055   EXPECT_FALSE(SpdySession::CanPool(
5056       &tss, ssl_info, "www.example.org", "mail.google.com"));
5057 }
5058
5059 TEST(CanPoolTest, CanNotPoolWithCertErrors) {
5060   // Load a cert that is valid for:
5061   //   www.example.org
5062   //   mail.example.org
5063   //   www.example.com
5064
5065   TransportSecurityState tss;
5066   SSLInfo ssl_info;
5067   ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5068                                      "spdy_pooling.pem");
5069   ssl_info.cert_status = CERT_STATUS_REVOKED;
5070
5071   EXPECT_FALSE(SpdySession::CanPool(
5072       &tss, ssl_info, "www.example.org", "mail.example.org"));
5073 }
5074
5075 TEST(CanPoolTest, CanNotPoolWithClientCerts) {
5076   // Load a cert that is valid for:
5077   //   www.example.org
5078   //   mail.example.org
5079   //   www.example.com
5080
5081   TransportSecurityState tss;
5082   SSLInfo ssl_info;
5083   ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5084                                      "spdy_pooling.pem");
5085   ssl_info.client_cert_sent = true;
5086
5087   EXPECT_FALSE(SpdySession::CanPool(
5088       &tss, ssl_info, "www.example.org", "mail.example.org"));
5089 }
5090
5091 TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
5092   // Load a cert that is valid for:
5093   //   www.example.org
5094   //   mail.example.org
5095   //   www.example.com
5096
5097   TransportSecurityState tss;
5098   SSLInfo ssl_info;
5099   ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5100                                      "spdy_pooling.pem");
5101   ssl_info.channel_id_sent = true;
5102
5103   EXPECT_TRUE(SpdySession::CanPool(
5104       &tss, ssl_info, "www.example.org", "mail.example.org"));
5105   EXPECT_FALSE(SpdySession::CanPool(
5106       &tss, ssl_info, "www.example.org", "www.example.com"));
5107 }
5108
5109 TEST(CanPoolTest, CanNotPoolWithBadPins) {
5110   uint8 primary_pin = 1;
5111   uint8 backup_pin = 2;
5112   uint8 bad_pin = 3;
5113   TransportSecurityState tss;
5114   test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5115
5116   SSLInfo ssl_info;
5117   ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5118                                      "spdy_pooling.pem");
5119   ssl_info.is_issued_by_known_root = true;
5120   ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
5121
5122   EXPECT_FALSE(SpdySession::CanPool(
5123       &tss, ssl_info, "www.example.org", "mail.example.org"));
5124 }
5125
5126 TEST(CanPoolTest, CanPoolWithAcceptablePins) {
5127   uint8 primary_pin = 1;
5128   uint8 backup_pin = 2;
5129   TransportSecurityState tss;
5130   test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5131
5132   SSLInfo ssl_info;
5133   ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5134                                      "spdy_pooling.pem");
5135   ssl_info.is_issued_by_known_root = true;
5136   ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
5137
5138   EXPECT_TRUE(SpdySession::CanPool(
5139       &tss, ssl_info, "www.example.org", "mail.example.org"));
5140 }
5141
5142 }  // namespace net