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