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