spdy_session_unittest.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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 read completion 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(ERR_CONNECTION_CLOSED, 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(ERR_CONNECTION_CLOSED, 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 read completion 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 read completion 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 read completion task.
1709  base::MessageLoop::current()->RunUntilIdle();
1710
1711  session->CloseSessionOnError(ERR_ABORTED, std::string());
1712}
1713
1714// Test that SpdySession::DoReadLoop reads data from the socket
1715// without yielding.  This test makes 32k - 1 bytes of data available
1716// on the socket for reading. It then verifies that it has read all
1717// the available data without yielding.
1718TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
1719  MockConnect connect_data(SYNCHRONOUS, OK);
1720  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
1721
1722  scoped_ptr<SpdyFrame> req1(
1723      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1724  MockWrite writes[] = {
1725    CreateMockWrite(*req1, 0),
1726  };
1727
1728  // Build buffer of size kMaxReadBytesWithoutYielding / 4
1729  // (-spdy_data_frame_size).
1730  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
1731  const int kPayloadSize =
1732      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
1733  TestDataStream test_stream;
1734  scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
1735  char* payload_data = payload->data();
1736  test_stream.GetBytes(payload_data, kPayloadSize);
1737
1738  scoped_ptr<SpdyFrame> partial_data_frame(
1739      framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
1740  scoped_ptr<SpdyFrame> finish_data_frame(
1741      framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
1742
1743  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1744
1745  // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
1746  // bytes.
1747  MockRead reads[] = {
1748    CreateMockRead(*resp1, 1),
1749    CreateMockRead(*partial_data_frame, 2),
1750    CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
1751    CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
1752    CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
1753    MockRead(ASYNC, 0, 6)  // EOF
1754  };
1755
1756  // Create SpdySession and SpdyStream and send the request.
1757  DeterministicSocketData data(reads, arraysize(reads),
1758                               writes, arraysize(writes));
1759  data.set_connect_data(connect_data);
1760  session_deps_.host_resolver->set_synchronous_mode(true);
1761  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1762
1763  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1764  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1765
1766  CreateDeterministicNetworkSession();
1767
1768  scoped_refptr<SpdySession> session =
1769      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1770
1771  GURL url1("http://www.google.com");
1772  base::WeakPtr<SpdyStream> spdy_stream1 =
1773      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1774                                session, url1, MEDIUM, BoundNetLog());
1775  ASSERT_TRUE(spdy_stream1.get() != NULL);
1776  EXPECT_EQ(0u, spdy_stream1->stream_id());
1777  test::StreamDelegateDoNothing delegate1(spdy_stream1);
1778  spdy_stream1->SetDelegate(&delegate1);
1779
1780  scoped_ptr<SpdyHeaderBlock> headers1(
1781      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1782  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
1783  EXPECT_TRUE(spdy_stream1->HasUrl());
1784
1785  // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
1786  // post a task.
1787  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
1788
1789  // Run until 1st read.
1790  EXPECT_EQ(0u, delegate1.stream_id());
1791  data.RunFor(2);
1792  EXPECT_EQ(1u, delegate1.stream_id());
1793  EXPECT_EQ(0u, observer.executed_count());
1794
1795  // Read all the data and verify SpdySession::DoReadLoop has not
1796  // posted a task.
1797  data.RunFor(4);
1798  EXPECT_EQ(NULL, spdy_stream1.get());
1799
1800  // Verify task observer's executed_count is zero, which indicates DoRead read
1801  // all the available data.
1802  EXPECT_EQ(0u, observer.executed_count());
1803  EXPECT_TRUE(data.at_write_eof());
1804  EXPECT_TRUE(data.at_read_eof());
1805}
1806
1807// Test that SpdySession::DoReadLoop yields while reading the
1808// data. This test makes 32k + 1 bytes of data available on the socket
1809// for reading. It then verifies that DoRead has yielded even though
1810// there is data available for it to read (i.e, socket()->Read didn't
1811// return ERR_IO_PENDING during socket reads).
1812TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
1813  MockConnect connect_data(SYNCHRONOUS, OK);
1814  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
1815
1816  scoped_ptr<SpdyFrame> req1(
1817      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1818  MockWrite writes[] = {
1819    CreateMockWrite(*req1, 0),
1820  };
1821
1822  // Build buffer of size kMaxReadBytesWithoutYielding / 4
1823  // (-spdy_data_frame_size).
1824  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
1825  const int kPayloadSize =
1826      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
1827  TestDataStream test_stream;
1828  scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
1829  char* payload_data = payload->data();
1830  test_stream.GetBytes(payload_data, kPayloadSize);
1831
1832  scoped_ptr<SpdyFrame> partial_data_frame(
1833      framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
1834  scoped_ptr<SpdyFrame> finish_data_frame(
1835      framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
1836
1837  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1838
1839  // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
1840  MockRead reads[] = {
1841    CreateMockRead(*resp1, 1),
1842    CreateMockRead(*partial_data_frame, 2),
1843    CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
1844    CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
1845    CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
1846    CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
1847    MockRead(ASYNC, 0, 7)  // EOF
1848  };
1849
1850  // Create SpdySession and SpdyStream and send the request.
1851  DeterministicSocketData data(reads, arraysize(reads),
1852                               writes, arraysize(writes));
1853  data.set_connect_data(connect_data);
1854  session_deps_.host_resolver->set_synchronous_mode(true);
1855  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1856
1857  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1858  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1859
1860  CreateDeterministicNetworkSession();
1861
1862  scoped_refptr<SpdySession> session =
1863      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1864
1865  GURL url1("http://www.google.com");
1866  base::WeakPtr<SpdyStream> spdy_stream1 =
1867      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1868                                session, url1, MEDIUM, BoundNetLog());
1869  ASSERT_TRUE(spdy_stream1.get() != NULL);
1870  EXPECT_EQ(0u, spdy_stream1->stream_id());
1871  test::StreamDelegateDoNothing delegate1(spdy_stream1);
1872  spdy_stream1->SetDelegate(&delegate1);
1873
1874  scoped_ptr<SpdyHeaderBlock> headers1(
1875      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1876  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
1877  EXPECT_TRUE(spdy_stream1->HasUrl());
1878
1879  // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
1880  // task.
1881  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
1882
1883  // Run until 1st read.
1884  EXPECT_EQ(0u, delegate1.stream_id());
1885  data.RunFor(2);
1886  EXPECT_EQ(1u, delegate1.stream_id());
1887  EXPECT_EQ(0u, observer.executed_count());
1888
1889  // Read all the data and verify SpdySession::DoReadLoop has posted a
1890  // task.
1891  data.RunFor(6);
1892  EXPECT_EQ(NULL, spdy_stream1.get());
1893
1894  // Verify task observer's executed_count is 1, which indicates DoRead has
1895  // posted only one task and thus yielded though there is data available for it
1896  // to read.
1897  EXPECT_EQ(1u, observer.executed_count());
1898  EXPECT_TRUE(data.at_write_eof());
1899  EXPECT_TRUE(data.at_read_eof());
1900}
1901
1902// Test that SpdySession::DoReadLoop() tests interactions of yielding
1903// + async, by doing the following MockReads.
1904//
1905// MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
1906// ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
1907//
1908// The above reads 26K synchronously. Since that is less that 32K, we
1909// will attempt to read again. However, that DoRead() will return
1910// ERR_IO_PENDING (because of async read), so DoReadLoop() will
1911// yield. When we come back, DoRead() will read the results from the
1912// async read, and rest of the data synchronously.
1913TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
1914  MockConnect connect_data(SYNCHRONOUS, OK);
1915  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
1916
1917  scoped_ptr<SpdyFrame> req1(
1918      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1919  MockWrite writes[] = {
1920    CreateMockWrite(*req1, 0),
1921  };
1922
1923  // Build buffer of size kMaxReadBytesWithoutYielding / 4
1924  // (-spdy_data_frame_size).
1925  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
1926  TestDataStream test_stream;
1927  const int kEightKPayloadSize =
1928      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
1929  scoped_refptr<net::IOBuffer> eightk_payload(
1930      new net::IOBuffer(kEightKPayloadSize));
1931  char* eightk_payload_data = eightk_payload->data();
1932  test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
1933
1934  // Build buffer of 2k size.
1935  TestDataStream test_stream2;
1936  const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
1937  scoped_refptr<net::IOBuffer> twok_payload(
1938      new net::IOBuffer(kTwoKPayloadSize));
1939  char* twok_payload_data = twok_payload->data();
1940  test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
1941
1942  scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
1943      1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
1944  scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
1945      1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
1946  scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
1947      1, "h", 1, DATA_FLAG_FIN));
1948
1949  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1950
1951  MockRead reads[] = {
1952    CreateMockRead(*resp1, 1),
1953    CreateMockRead(*eightk_data_frame, 2),
1954    CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
1955    CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
1956    CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
1957    CreateMockRead(*eightk_data_frame, 6, ASYNC),
1958    CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
1959    CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
1960    CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
1961    CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
1962    CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
1963    MockRead(ASYNC, 0, 12)  // EOF
1964  };
1965
1966  // Create SpdySession and SpdyStream and send the request.
1967  DeterministicSocketData data(reads, arraysize(reads),
1968                               writes, arraysize(writes));
1969  data.set_connect_data(connect_data);
1970  session_deps_.host_resolver->set_synchronous_mode(true);
1971  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1972
1973  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1974  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1975
1976  CreateDeterministicNetworkSession();
1977
1978  scoped_refptr<SpdySession> session =
1979      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1980
1981  GURL url1("http://www.google.com");
1982  base::WeakPtr<SpdyStream> spdy_stream1 =
1983      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1984                                session, url1, MEDIUM, BoundNetLog());
1985  ASSERT_TRUE(spdy_stream1.get() != NULL);
1986  EXPECT_EQ(0u, spdy_stream1->stream_id());
1987  test::StreamDelegateDoNothing delegate1(spdy_stream1);
1988  spdy_stream1->SetDelegate(&delegate1);
1989
1990  scoped_ptr<SpdyHeaderBlock> headers1(
1991      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1992  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
1993  EXPECT_TRUE(spdy_stream1->HasUrl());
1994
1995  // Set up the TaskObserver to monitor SpdySession::DoReadLoop
1996  // posting of tasks.
1997  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
1998
1999  // Run until 1st read.
2000  EXPECT_EQ(0u, delegate1.stream_id());
2001  data.RunFor(2);
2002  EXPECT_EQ(1u, delegate1.stream_id());
2003  EXPECT_EQ(0u, observer.executed_count());
2004
2005  // Read all the data and verify SpdySession::DoReadLoop has posted a
2006  // task.
2007  data.RunFor(12);
2008  EXPECT_EQ(NULL, spdy_stream1.get());
2009
2010  // Verify task observer's executed_count is 1, which indicates DoRead has
2011  // posted only one task and thus yielded though there is data available for
2012  // it to read.
2013  EXPECT_EQ(1u, observer.executed_count());
2014  EXPECT_TRUE(data.at_write_eof());
2015  EXPECT_TRUE(data.at_read_eof());
2016}
2017
2018// Send a GoAway frame when SpdySession is in DoReadLoop. If
2019// scoped_refptr to <SpdySession> is deleted from
2020// SpdySession::DoReadLoop(), we get a crash because GoAway could
2021// delete the SpdySession from the SpdySessionPool and the last
2022// reference to SpdySession.
2023TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
2024  MockConnect connect_data(SYNCHRONOUS, OK);
2025  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2026
2027  scoped_ptr<SpdyFrame> req1(
2028      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2029  MockWrite writes[] = {
2030    CreateMockWrite(*req1, 0),
2031  };
2032
2033  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2034  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2035  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
2036
2037  MockRead reads[] = {
2038    CreateMockRead(*resp1, 1),
2039    CreateMockRead(*body1, 2),
2040    CreateMockRead(*goaway, 3),
2041    MockRead(ASYNC, 0, 4)  // EOF
2042  };
2043
2044  // Create SpdySession and SpdyStream and send the request.
2045  DeterministicSocketData data(reads, arraysize(reads),
2046                               writes, arraysize(writes));
2047  data.set_connect_data(connect_data);
2048  session_deps_.host_resolver->set_synchronous_mode(true);
2049  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2050
2051  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2052  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2053
2054  CreateDeterministicNetworkSession();
2055
2056  scoped_refptr<SpdySession> session =
2057      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2058
2059  GURL url1("http://www.google.com");
2060  base::WeakPtr<SpdyStream> spdy_stream1 =
2061      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2062                                session, url1, MEDIUM, BoundNetLog());
2063  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2064  spdy_stream1->SetDelegate(&delegate1);
2065  session = NULL;
2066  ASSERT_TRUE(spdy_stream1.get() != NULL);
2067  EXPECT_EQ(0u, spdy_stream1->stream_id());
2068
2069  scoped_ptr<SpdyHeaderBlock> headers1(
2070      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2071  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2072  EXPECT_TRUE(spdy_stream1->HasUrl());
2073
2074  // Run until 1st read.
2075  EXPECT_EQ(0u, spdy_stream1->stream_id());
2076  data.RunFor(1);
2077  EXPECT_EQ(1u, spdy_stream1->stream_id());
2078
2079  // Only references to SpdySession are held by DoReadLoop and
2080  // SpdySessionPool. If DoReadLoop doesn't hold the reference, we get a
2081  // crash if SpdySession is deleted from the SpdySessionPool.
2082
2083  // Run until GoAway.
2084  data.RunFor(4);
2085  EXPECT_EQ(NULL, spdy_stream1.get());
2086  EXPECT_TRUE(data.at_write_eof());
2087  EXPECT_TRUE(data.at_read_eof());
2088}
2089
2090// Within this framework, a SpdySession should be initialized with
2091// flow control disabled for protocol version 2, with flow control
2092// enabled only for streams for protocol version 3, and with flow
2093// control enabled for streams and sessions for higher versions.
2094TEST_P(SpdySessionTest, ProtocolNegotiation) {
2095  session_deps_.host_resolver->set_synchronous_mode(true);
2096
2097  MockConnect connect_data(SYNCHRONOUS, OK);
2098  MockRead reads[] = {
2099    MockRead(SYNCHRONOUS, 0, 0)  // EOF
2100  };
2101  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2102  data.set_connect_data(connect_data);
2103  session_deps_.socket_factory->AddSocketDataProvider(&data);
2104
2105  CreateNetworkSession();
2106  scoped_refptr<SpdySession> session =
2107      CreateFakeSpdySession(spdy_session_pool_, key_);
2108
2109  EXPECT_EQ(spdy_util_.spdy_version(),
2110            session->buffered_spdy_framer_->protocol_version());
2111  if (GetParam() == kProtoSPDY2) {
2112    EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state());
2113    EXPECT_EQ(0, session->session_send_window_size_);
2114    EXPECT_EQ(0, session->session_recv_window_size_);
2115  } else if (GetParam() == kProtoSPDY3) {
2116    EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
2117    EXPECT_EQ(0, session->session_send_window_size_);
2118    EXPECT_EQ(0, session->session_recv_window_size_);
2119  } else {
2120    EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
2121              session->flow_control_state());
2122    EXPECT_EQ(kSpdySessionInitialWindowSize,
2123              session->session_send_window_size_);
2124    EXPECT_EQ(kSpdySessionInitialWindowSize,
2125              session->session_recv_window_size_);
2126  }
2127  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2128}
2129
2130// Tests the case of a non-SPDY request closing an idle SPDY session when no
2131// pointers to the idle session are currently held.
2132TEST_P(SpdySessionTest, CloseOneIdleConnection) {
2133  ClientSocketPoolManager::set_max_sockets_per_group(
2134      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2135  ClientSocketPoolManager::set_max_sockets_per_pool(
2136      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2137
2138  MockConnect connect_data(SYNCHRONOUS, OK);
2139  MockRead reads[] = {
2140    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2141  };
2142  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2143  data.set_connect_data(connect_data);
2144  session_deps_.socket_factory->AddSocketDataProvider(&data);
2145  session_deps_.socket_factory->AddSocketDataProvider(&data);
2146
2147  CreateNetworkSession();
2148
2149  TransportClientSocketPool* pool =
2150      http_session_->GetTransportSocketPool(
2151          HttpNetworkSession::NORMAL_SOCKET_POOL);
2152
2153  // Create an idle SPDY session.
2154  SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2155                      kPrivacyModeDisabled);
2156  scoped_refptr<SpdySession> session1 =
2157      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2158  EXPECT_FALSE(pool->IsStalled());
2159  // Release the pointer to the session so it can be closed.
2160  session1 = NULL;
2161
2162  // Trying to create a new connection should cause the pool to be stalled, and
2163  // post a task asynchronously to try and close the session.
2164  TestCompletionCallback callback2;
2165  HostPortPair host_port2("2.com", 80);
2166  scoped_refptr<TransportSocketParams> params2(
2167      new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false,
2168                                OnHostResolutionCallback()));
2169  scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
2170  EXPECT_EQ(ERR_IO_PENDING,
2171            connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
2172                              callback2.callback(), pool, BoundNetLog()));
2173  EXPECT_TRUE(pool->IsStalled());
2174
2175  // The socket pool should close the connection asynchronously and establish a
2176  // new connection.
2177  EXPECT_EQ(OK, callback2.WaitForResult());
2178  EXPECT_FALSE(pool->IsStalled());
2179}
2180
2181// Tests the case of a non-SPDY request closing an idle SPDY session when no
2182// pointers to the idle session are currently held, in the case the SPDY session
2183// has an alias.
2184TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
2185  ClientSocketPoolManager::set_max_sockets_per_group(
2186      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2187  ClientSocketPoolManager::set_max_sockets_per_pool(
2188      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2189
2190  MockConnect connect_data(SYNCHRONOUS, OK);
2191  MockRead reads[] = {
2192    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2193  };
2194  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2195  data.set_connect_data(connect_data);
2196  session_deps_.socket_factory->AddSocketDataProvider(&data);
2197  session_deps_.socket_factory->AddSocketDataProvider(&data);
2198
2199  session_deps_.host_resolver->set_synchronous_mode(true);
2200  session_deps_.host_resolver->rules()->AddIPLiteralRule(
2201      "1.com", "192.168.0.2", std::string());
2202  session_deps_.host_resolver->rules()->AddIPLiteralRule(
2203      "2.com", "192.168.0.2", std::string());
2204  // Not strictly needed.
2205  session_deps_.host_resolver->rules()->AddIPLiteralRule(
2206      "3.com", "192.168.0.3", std::string());
2207
2208  CreateNetworkSession();
2209
2210  TransportClientSocketPool* pool =
2211      http_session_->GetTransportSocketPool(
2212          HttpNetworkSession::NORMAL_SOCKET_POOL);
2213
2214  // Create an idle SPDY session.
2215  SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2216                      kPrivacyModeDisabled);
2217  scoped_refptr<SpdySession> session1 =
2218      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2219  EXPECT_FALSE(pool->IsStalled());
2220
2221  // Set up an alias for the idle SPDY session, increasing its ref count to 2.
2222  SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
2223                      kPrivacyModeDisabled);
2224  HostResolver::RequestInfo info(key2.host_port_pair());
2225  AddressList addresses;
2226  // Pre-populate the DNS cache, since a synchronous resolution is required in
2227  // order to create the alias.
2228  session_deps_.host_resolver->Resolve(
2229      info, &addresses, CompletionCallback(), NULL, BoundNetLog());
2230  // Get a session for |key2|, which should return the session created earlier.
2231  scoped_refptr<SpdySession> session2 =
2232      spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
2233  ASSERT_EQ(session1.get(), session2.get());
2234  EXPECT_FALSE(pool->IsStalled());
2235
2236  // Release both the pointers to the session so it can be closed.
2237  session1 = NULL;
2238  session2 = NULL;
2239
2240  // Trying to create a new connection should cause the pool to be stalled, and
2241  // post a task asynchronously to try and close the session.
2242  TestCompletionCallback callback3;
2243  HostPortPair host_port3("3.com", 80);
2244  scoped_refptr<TransportSocketParams> params3(
2245      new TransportSocketParams(host_port3, DEFAULT_PRIORITY, false, false,
2246                                OnHostResolutionCallback()));
2247  scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
2248  EXPECT_EQ(ERR_IO_PENDING,
2249            connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
2250                              callback3.callback(), pool, BoundNetLog()));
2251  EXPECT_TRUE(pool->IsStalled());
2252
2253  // The socket pool should close the connection asynchronously and establish a
2254  // new connection.
2255  EXPECT_EQ(OK, callback3.WaitForResult());
2256  EXPECT_FALSE(pool->IsStalled());
2257}
2258
2259// Tests the case of a non-SPDY request closing an idle SPDY session when a
2260// pointer to the idle session is still held.
2261TEST_P(SpdySessionTest, CloseOneIdleConnectionSessionStillHeld) {
2262  ClientSocketPoolManager::set_max_sockets_per_group(
2263      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2264  ClientSocketPoolManager::set_max_sockets_per_pool(
2265      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2266
2267  MockConnect connect_data(SYNCHRONOUS, OK);
2268  MockRead reads[] = {
2269    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2270  };
2271  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2272  data.set_connect_data(connect_data);
2273  session_deps_.socket_factory->AddSocketDataProvider(&data);
2274  session_deps_.socket_factory->AddSocketDataProvider(&data);
2275
2276  CreateNetworkSession();
2277
2278  TransportClientSocketPool* pool =
2279      http_session_->GetTransportSocketPool(
2280          HttpNetworkSession::NORMAL_SOCKET_POOL);
2281
2282  // Create an idle SPDY session.
2283  SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2284                      kPrivacyModeDisabled);
2285  scoped_refptr<SpdySession> session1 =
2286      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2287  EXPECT_FALSE(pool->IsStalled());
2288
2289  // Trying to create a new connection should cause the pool to be stalled, and
2290  // post a task asynchronously to try and close the session.
2291  TestCompletionCallback callback2;
2292  HostPortPair host_port2("2.com", 80);
2293  scoped_refptr<TransportSocketParams> params2(
2294      new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false,
2295                                OnHostResolutionCallback()));
2296  scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
2297  EXPECT_EQ(ERR_IO_PENDING,
2298            connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
2299                              callback2.callback(), pool, BoundNetLog()));
2300  EXPECT_TRUE(pool->IsStalled());
2301
2302  // Running the message loop should cause the session to prepare to be closed,
2303  // but since there's still an outstanding reference, it should not be closed
2304  // yet.
2305  base::RunLoop().RunUntilIdle();
2306  EXPECT_TRUE(pool->IsStalled());
2307  EXPECT_FALSE(callback2.have_result());
2308
2309  // Release the pointer to the session so it can be closed.
2310  session1 = NULL;
2311  EXPECT_EQ(OK, callback2.WaitForResult());
2312  EXPECT_FALSE(pool->IsStalled());
2313}
2314
2315// Tests that a non-SPDY request can't close a SPDY session that's currently in
2316// use.
2317TEST_P(SpdySessionTest, CloseOneIdleConnectionFailsWhenSessionInUse) {
2318  ClientSocketPoolManager::set_max_sockets_per_group(
2319      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2320  ClientSocketPoolManager::set_max_sockets_per_pool(
2321      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2322
2323  MockConnect connect_data(SYNCHRONOUS, OK);
2324  MockRead reads[] = {
2325    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2326  };
2327  scoped_ptr<SpdyFrame> req1(
2328      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2329  scoped_ptr<SpdyFrame> cancel1(
2330      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2331  MockWrite writes[] = {
2332    CreateMockWrite(*req1, 1),
2333    CreateMockWrite(*cancel1, 1),
2334  };
2335  StaticSocketDataProvider data(reads, arraysize(reads),
2336                                     writes, arraysize(writes));
2337  data.set_connect_data(connect_data);
2338  session_deps_.socket_factory->AddSocketDataProvider(&data);
2339
2340  CreateNetworkSession();
2341
2342  TransportClientSocketPool* pool =
2343      http_session_->GetTransportSocketPool(
2344          HttpNetworkSession::NORMAL_SOCKET_POOL);
2345
2346  // Create a SPDY session.
2347  GURL url1("http://www.google.com");
2348  SpdySessionKey key1(HostPortPair(url1.host(), 80),
2349                      ProxyServer::Direct(), kPrivacyModeDisabled);
2350  scoped_refptr<SpdySession> session1 =
2351      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2352  EXPECT_FALSE(pool->IsStalled());
2353
2354  // Create a stream using the session, and send a request.
2355
2356  TestCompletionCallback callback1;
2357  base::WeakPtr<SpdyStream> spdy_stream1 =
2358      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2359                                session1, url1, DEFAULT_PRIORITY,
2360                                BoundNetLog());
2361  ASSERT_TRUE(spdy_stream1.get());
2362  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2363  spdy_stream1->SetDelegate(&delegate1);
2364
2365  scoped_ptr<SpdyHeaderBlock> headers1(
2366      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2367  EXPECT_EQ(ERR_IO_PENDING,
2368            spdy_stream1->SendRequestHeaders(
2369                headers1.Pass(), NO_MORE_DATA_TO_SEND));
2370  EXPECT_TRUE(spdy_stream1->HasUrl());
2371
2372  base::MessageLoop::current()->RunUntilIdle();
2373
2374  // Release the session, so holding onto a pointer here does not affect
2375  // anything.
2376  session1 = NULL;
2377
2378  // Trying to create a new connection should cause the pool to be stalled, and
2379  // post a task asynchronously to try and close the session.
2380  TestCompletionCallback callback2;
2381  HostPortPair host_port2("2.com", 80);
2382  scoped_refptr<TransportSocketParams> params2(
2383      new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false,
2384                                OnHostResolutionCallback()));
2385  scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
2386  EXPECT_EQ(ERR_IO_PENDING,
2387            connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
2388                              callback2.callback(), pool, BoundNetLog()));
2389  EXPECT_TRUE(pool->IsStalled());
2390
2391  // Running the message loop should cause the socket pool to ask the SPDY
2392  // session to close an idle socket, but since the socket is in use, nothing
2393  // happens.
2394  base::RunLoop().RunUntilIdle();
2395  EXPECT_TRUE(pool->IsStalled());
2396  EXPECT_FALSE(callback2.have_result());
2397
2398  // Cancelling the request should still not release the session's socket,
2399  // since the session is still kept alive by the SpdySessionPool.
2400  ASSERT_TRUE(spdy_stream1.get());
2401  spdy_stream1->Cancel();
2402  base::RunLoop().RunUntilIdle();
2403  EXPECT_TRUE(pool->IsStalled());
2404  EXPECT_FALSE(callback2.have_result());
2405}
2406
2407// Verify that SpdySessionKey and therefore SpdySession is different when
2408// privacy mode is enabled or disabled.
2409TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
2410  CreateDeterministicNetworkSession();
2411
2412  HostPortPair host_port_pair("www.google.com", 443);
2413  SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
2414                                     kPrivacyModeEnabled);
2415  SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
2416                                     kPrivacyModeDisabled);
2417
2418  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
2419  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2420
2421  // Add SpdySession with PrivacyMode Enabled to the pool.
2422  scoped_refptr<SpdySession> session_privacy_enabled =
2423      CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
2424
2425  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
2426  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2427
2428  // Add SpdySession with PrivacyMode Disabled to the pool.
2429  scoped_refptr<SpdySession> session_privacy_disabled =
2430      CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
2431
2432  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
2433  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2434
2435  session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
2436  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
2437  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2438
2439  session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
2440  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
2441  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2442}
2443
2444// The tests below are only for SPDY/3 and above.
2445
2446TEST_P(SpdySessionTest, SendCredentials) {
2447  if (GetParam() < kProtoSPDY3)
2448    return;
2449
2450  MockConnect connect_data(SYNCHRONOUS, OK);
2451  MockRead reads[] = {
2452    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2453  };
2454  SettingsMap settings;
2455  scoped_ptr<SpdyFrame> settings_frame(
2456      spdy_util_.ConstructSpdySettings(settings));
2457  MockWrite writes[] = {
2458    CreateMockWrite(*settings_frame),
2459  };
2460  StaticSocketDataProvider data(reads, arraysize(reads),
2461                                writes, arraysize(writes));
2462  data.set_connect_data(connect_data);
2463  session_deps_.socket_factory->AddSocketDataProvider(&data);
2464
2465  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2466  ssl.channel_id_sent = true;
2467  ssl.protocol_negotiated = GetParam();
2468  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2469
2470  CreateNetworkSession();
2471
2472  const GURL kTestUrl("https://www.foo.com");
2473  HostPortPair test_host_port_pair(kTestUrl.host(), 443);
2474  SpdySessionKey key(test_host_port_pair, ProxyServer::Direct(),
2475                     kPrivacyModeDisabled);
2476
2477  scoped_refptr<SpdySession> session =
2478      CreateSecureSpdySession(http_session_, key, BoundNetLog());
2479
2480  EXPECT_TRUE(session->NeedsCredentials());
2481
2482  // Flush the read completion task.
2483  base::MessageLoop::current()->RunUntilIdle();
2484
2485  session->CloseSessionOnError(ERR_ABORTED, std::string());
2486  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key));
2487}
2488
2489TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
2490  if (GetParam() < kProtoSPDY3)
2491    return;
2492
2493  // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
2494  // gets sent.
2495  SettingsMap new_settings;
2496  int32 window_size = 1;
2497  new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
2498      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
2499
2500  // Set up the socket so we read a SETTINGS frame that sets
2501  // INITIAL_WINDOW_SIZE.
2502  MockConnect connect_data(SYNCHRONOUS, OK);
2503  scoped_ptr<SpdyFrame> settings_frame(
2504      spdy_util_.ConstructSpdySettings(new_settings));
2505  MockRead reads[] = {
2506    CreateMockRead(*settings_frame, 0),
2507    MockRead(ASYNC, 0, 1)  // EOF
2508  };
2509
2510  session_deps_.host_resolver->set_synchronous_mode(true);
2511
2512  scoped_ptr<DeterministicSocketData> data(
2513      new DeterministicSocketData(reads, arraysize(reads), NULL, 0));
2514  data->set_connect_data(connect_data);
2515  session_deps_.deterministic_socket_factory->AddSocketDataProvider(data.get());
2516
2517  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2518  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2519
2520  CreateDeterministicNetworkSession();
2521
2522  scoped_refptr<SpdySession> session =
2523      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2524  base::WeakPtr<SpdyStream> spdy_stream1 =
2525      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2526                                session, test_url_, MEDIUM, BoundNetLog());
2527  ASSERT_TRUE(spdy_stream1.get() != NULL);
2528  TestCompletionCallback callback1;
2529  EXPECT_NE(spdy_stream1->send_window_size(), window_size);
2530
2531  data->RunFor(1);  // Process the SETTINGS frame, but not the EOF
2532  base::MessageLoop::current()->RunUntilIdle();
2533  EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
2534  EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
2535
2536  // Release the first one, this will allow the second to be created.
2537  spdy_stream1->Cancel();
2538  EXPECT_EQ(NULL, spdy_stream1.get());
2539
2540  base::WeakPtr<SpdyStream> spdy_stream2 =
2541      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2542                                session, test_url_, MEDIUM, BoundNetLog());
2543  ASSERT_TRUE(spdy_stream2.get() != NULL);
2544  EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
2545  spdy_stream2->Cancel();
2546  EXPECT_EQ(NULL, spdy_stream2.get());
2547}
2548
2549// The tests below are only for SPDY/3.1 and above.
2550
2551// SpdySession::{Increase,Decrease}RecvWindowSize should properly
2552// adjust the session receive window size for SPDY 3.1 and higher. In
2553// addition, SpdySession::IncreaseRecvWindowSize should trigger
2554// sending a WINDOW_UPDATE frame for a large enough delta.
2555TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
2556  if (GetParam() < kProtoSPDY31)
2557    return;
2558
2559  session_deps_.host_resolver->set_synchronous_mode(true);
2560
2561  const int32 delta_window_size = 100;
2562
2563  MockConnect connect_data(SYNCHRONOUS, OK);
2564  MockRead reads[] = {
2565    MockRead(ASYNC, 0, 1)  // EOF
2566  };
2567  scoped_ptr<SpdyFrame> window_update(
2568      spdy_util_.ConstructSpdyWindowUpdate(
2569          kSessionFlowControlStreamId,
2570          kSpdySessionInitialWindowSize + delta_window_size));
2571  MockWrite writes[] = {
2572    CreateMockWrite(*window_update, 0),
2573  };
2574  DeterministicSocketData data(reads, arraysize(reads),
2575                               writes, arraysize(writes));
2576  data.set_connect_data(connect_data);
2577  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2578
2579  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2580  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2581
2582  CreateDeterministicNetworkSession();
2583  scoped_refptr<SpdySession> session =
2584      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2585  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
2586            session->flow_control_state());
2587
2588  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
2589  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2590
2591  session->IncreaseRecvWindowSize(delta_window_size);
2592  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
2593            session->session_recv_window_size_);
2594  EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
2595
2596  // Should trigger sending a WINDOW_UPDATE frame.
2597  session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize);
2598  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size +
2599            kSpdySessionInitialWindowSize,
2600            session->session_recv_window_size_);
2601  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2602
2603  data.RunFor(1);
2604
2605  session->DecreaseRecvWindowSize(
2606      kSpdySessionInitialWindowSize + delta_window_size +
2607      kSpdySessionInitialWindowSize);
2608  EXPECT_EQ(0, session->session_recv_window_size_);
2609  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2610}
2611
2612// SpdySession::{Increase,Decrease}SendWindowSize should properly
2613// adjust the session send window size when the "enable_spdy_31" flag
2614// is set.
2615TEST_P(SpdySessionTest, AdjustSendWindowSize) {
2616  if (GetParam() < kProtoSPDY31)
2617    return;
2618
2619  session_deps_.host_resolver->set_synchronous_mode(true);
2620
2621  MockConnect connect_data(SYNCHRONOUS, OK);
2622  MockRead reads[] = {
2623    MockRead(SYNCHRONOUS, 0, 0)  // EOF
2624  };
2625  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2626  data.set_connect_data(connect_data);
2627  session_deps_.socket_factory->AddSocketDataProvider(&data);
2628
2629  CreateNetworkSession();
2630  scoped_refptr<SpdySession> session =
2631      CreateFakeSpdySession(spdy_session_pool_, key_);
2632  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
2633            session->flow_control_state());
2634
2635  const int32 delta_window_size = 100;
2636
2637  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
2638
2639  session->IncreaseSendWindowSize(delta_window_size);
2640  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
2641            session->session_send_window_size_);
2642
2643  session->DecreaseSendWindowSize(delta_window_size);
2644  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
2645}
2646
2647// Incoming data for an inactive stream should not cause the session
2648// receive window size to decrease.
2649TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
2650  if (GetParam() < kProtoSPDY31)
2651    return;
2652
2653  session_deps_.host_resolver->set_synchronous_mode(true);
2654
2655  MockConnect connect_data(SYNCHRONOUS, OK);
2656  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
2657  MockRead reads[] = {
2658    CreateMockRead(*resp, 0),
2659    MockRead(ASYNC, 0, 1)  // EOF
2660  };
2661  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
2662  data.set_connect_data(connect_data);
2663  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2664
2665  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2666  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2667
2668  CreateDeterministicNetworkSession();
2669  scoped_refptr<SpdySession> session =
2670      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2671  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
2672            session->flow_control_state());
2673
2674  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
2675  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2676
2677  data.RunFor(2);
2678
2679  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
2680  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2681}
2682
2683// A delegate that drops any received data.
2684class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
2685 public:
2686  DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
2687                           base::StringPiece data)
2688      : StreamDelegateSendImmediate(stream, data) {}
2689
2690  virtual ~DropReceivedDataDelegate() {}
2691
2692  // Drop any received data.
2693  virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) OVERRIDE {}
2694};
2695
2696// Send data back and forth but use a delegate that drops its received
2697// data. The receive window should still increase to its original
2698// value, i.e. we shouldn't "leak" receive window bytes.
2699TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
2700  if (GetParam() < kProtoSPDY31)
2701    return;
2702
2703  const char kStreamUrl[] = "http://www.google.com/";
2704
2705  const int32 msg_data_size = 100;
2706  const std::string msg_data(msg_data_size, 'a');
2707
2708  MockConnect connect_data(SYNCHRONOUS, OK);
2709
2710  scoped_ptr<SpdyFrame> req(
2711      spdy_util_.ConstructSpdyPost(
2712          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
2713  scoped_ptr<SpdyFrame> msg(
2714      spdy_util_.ConstructSpdyBodyFrame(
2715          1, msg_data.data(), msg_data_size, false));
2716  MockWrite writes[] = {
2717    CreateMockWrite(*req, 0),
2718    CreateMockWrite(*msg, 2),
2719  };
2720
2721  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2722  scoped_ptr<SpdyFrame> echo(
2723      spdy_util_.ConstructSpdyBodyFrame(
2724          1, msg_data.data(), msg_data_size, false));
2725  scoped_ptr<SpdyFrame> window_update(
2726      spdy_util_.ConstructSpdyWindowUpdate(
2727          kSessionFlowControlStreamId, msg_data_size));
2728  MockRead reads[] = {
2729    CreateMockRead(*resp, 1),
2730    CreateMockRead(*echo, 3),
2731    MockRead(ASYNC, 0, 4)  // EOF
2732  };
2733
2734  // Create SpdySession and SpdyStream and send the request.
2735  DeterministicSocketData data(reads, arraysize(reads),
2736                               writes, arraysize(writes));
2737  data.set_connect_data(connect_data);
2738  session_deps_.host_resolver->set_synchronous_mode(true);
2739  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2740
2741  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2742  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2743
2744  CreateDeterministicNetworkSession();
2745
2746  scoped_refptr<SpdySession> session =
2747      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2748
2749  GURL url(kStreamUrl);
2750  base::WeakPtr<SpdyStream> stream =
2751      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2752                                session, url, MEDIUM, BoundNetLog());
2753  ASSERT_TRUE(stream.get() != NULL);
2754  EXPECT_EQ(0u, stream->stream_id());
2755
2756  DropReceivedDataDelegate delegate(stream, msg_data);
2757  stream->SetDelegate(&delegate);
2758
2759  scoped_ptr<SpdyHeaderBlock> headers(
2760      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
2761  EXPECT_EQ(ERR_IO_PENDING,
2762            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
2763  EXPECT_TRUE(stream->HasUrl());
2764
2765  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
2766  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2767
2768  data.RunFor(4);
2769
2770  EXPECT_TRUE(data.at_write_eof());
2771  EXPECT_TRUE(data.at_read_eof());
2772
2773  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
2774  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
2775
2776  stream->Close();
2777  EXPECT_EQ(NULL, stream.get());
2778
2779  EXPECT_EQ(OK, delegate.WaitForClose());
2780
2781  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
2782  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
2783}
2784
2785// Send data back and forth but close the stream before its data frame
2786// can be written to the socket. The send window should then increase
2787// to its original value, i.e. we shouldn't "leak" send window bytes.
2788TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
2789  if (GetParam() < kProtoSPDY31)
2790    return;
2791
2792  const char kStreamUrl[] = "http://www.google.com/";
2793
2794  const int32 msg_data_size = 100;
2795  const std::string msg_data(msg_data_size, 'a');
2796
2797  MockConnect connect_data(SYNCHRONOUS, OK);
2798
2799  scoped_ptr<SpdyFrame> req(
2800      spdy_util_.ConstructSpdyPost(
2801          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
2802  MockWrite writes[] = {
2803    CreateMockWrite(*req, 0),
2804  };
2805
2806  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2807  MockRead reads[] = {
2808    CreateMockRead(*resp, 1),
2809    MockRead(ASYNC, 0, 2)  // EOF
2810  };
2811
2812  // Create SpdySession and SpdyStream and send the request.
2813  DeterministicSocketData data(reads, arraysize(reads),
2814                               writes, arraysize(writes));
2815  data.set_connect_data(connect_data);
2816  session_deps_.host_resolver->set_synchronous_mode(true);
2817  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2818
2819  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2820  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2821
2822  CreateDeterministicNetworkSession();
2823
2824  scoped_refptr<SpdySession> session =
2825      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2826
2827  GURL url(kStreamUrl);
2828  base::WeakPtr<SpdyStream> stream =
2829      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2830                                session, url, MEDIUM, BoundNetLog());
2831  ASSERT_TRUE(stream.get() != NULL);
2832  EXPECT_EQ(0u, stream->stream_id());
2833
2834  test::StreamDelegateSendImmediate delegate(stream, msg_data);
2835  stream->SetDelegate(&delegate);
2836
2837  scoped_ptr<SpdyHeaderBlock> headers(
2838      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
2839  EXPECT_EQ(ERR_IO_PENDING,
2840            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
2841  EXPECT_TRUE(stream->HasUrl());
2842
2843  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
2844
2845  data.RunFor(1);
2846
2847  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
2848
2849  data.RunFor(1);
2850
2851  EXPECT_TRUE(data.at_write_eof());
2852  EXPECT_TRUE(data.at_read_eof());
2853
2854  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
2855            session->session_send_window_size_);
2856
2857  // Closing the stream should increase the session's send window.
2858  stream->Close();
2859  EXPECT_EQ(NULL, stream.get());
2860
2861  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
2862
2863  EXPECT_EQ(OK, delegate.WaitForClose());
2864}
2865
2866// Send data back and forth; the send and receive windows should
2867// change appropriately.
2868TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
2869  if (GetParam() < kProtoSPDY31)
2870    return;
2871
2872  const char kStreamUrl[] = "http://www.google.com/";
2873
2874  const int32 msg_data_size = 100;
2875  const std::string msg_data(msg_data_size, 'a');
2876
2877  MockConnect connect_data(SYNCHRONOUS, OK);
2878
2879  scoped_ptr<SpdyFrame> req(
2880      spdy_util_.ConstructSpdyPost(
2881          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
2882  scoped_ptr<SpdyFrame> msg(
2883      spdy_util_.ConstructSpdyBodyFrame(
2884          1, msg_data.data(), msg_data_size, false));
2885  MockWrite writes[] = {
2886    CreateMockWrite(*req, 0),
2887    CreateMockWrite(*msg, 2),
2888  };
2889
2890  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2891  scoped_ptr<SpdyFrame> echo(
2892      spdy_util_.ConstructSpdyBodyFrame(
2893          1, msg_data.data(), msg_data_size, false));
2894  scoped_ptr<SpdyFrame> window_update(
2895      spdy_util_.ConstructSpdyWindowUpdate(
2896          kSessionFlowControlStreamId, msg_data_size));
2897  MockRead reads[] = {
2898    CreateMockRead(*resp, 1),
2899    CreateMockRead(*echo, 3),
2900    CreateMockRead(*window_update, 4),
2901    MockRead(ASYNC, 0, 5)  // EOF
2902  };
2903
2904  // Create SpdySession and SpdyStream and send the request.
2905  DeterministicSocketData data(reads, arraysize(reads),
2906                               writes, arraysize(writes));
2907  data.set_connect_data(connect_data);
2908  session_deps_.host_resolver->set_synchronous_mode(true);
2909  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2910
2911  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2912  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2913
2914  CreateDeterministicNetworkSession();
2915
2916  scoped_refptr<SpdySession> session =
2917      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2918
2919  GURL url(kStreamUrl);
2920  base::WeakPtr<SpdyStream> stream =
2921      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2922                                session, url, MEDIUM, BoundNetLog());
2923  ASSERT_TRUE(stream.get() != NULL);
2924  EXPECT_EQ(0u, stream->stream_id());
2925
2926  test::StreamDelegateSendImmediate delegate(stream, msg_data);
2927  stream->SetDelegate(&delegate);
2928
2929  scoped_ptr<SpdyHeaderBlock> headers(
2930      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
2931  EXPECT_EQ(ERR_IO_PENDING,
2932            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
2933  EXPECT_TRUE(stream->HasUrl());
2934
2935  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
2936  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
2937  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2938
2939  data.RunFor(1);
2940
2941  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
2942  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
2943  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2944
2945  data.RunFor(1);
2946
2947  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
2948            session->session_send_window_size_);
2949  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
2950  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2951
2952  data.RunFor(1);
2953
2954  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
2955            session->session_send_window_size_);
2956  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
2957  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2958
2959  data.RunFor(1);
2960
2961  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
2962            session->session_send_window_size_);
2963  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
2964            session->session_recv_window_size_);
2965  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2966
2967  data.RunFor(1);
2968
2969  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
2970  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
2971            session->session_recv_window_size_);
2972  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
2973
2974  EXPECT_TRUE(data.at_write_eof());
2975  EXPECT_TRUE(data.at_read_eof());
2976
2977  EXPECT_EQ(msg_data, delegate.TakeReceivedData());
2978
2979  // Draining the delegate's read queue should increase the session's
2980  // receive window.
2981  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
2982  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
2983  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
2984
2985  stream->Close();
2986  EXPECT_EQ(NULL, stream.get());
2987
2988  EXPECT_EQ(OK, delegate.WaitForClose());
2989
2990  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
2991  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
2992  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
2993}
2994
2995// Given a stall function and an unstall function, runs a test to make
2996// sure that a stream resumes after unstall.
2997void SpdySessionTest::RunResumeAfterUnstallTest(
2998    const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
2999    const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
3000        unstall_function) {
3001  const char kStreamUrl[] = "http://www.google.com/";
3002  GURL url(kStreamUrl);
3003
3004  session_deps_.host_resolver->set_synchronous_mode(true);
3005
3006  scoped_ptr<SpdyFrame> req(
3007      spdy_util_.ConstructSpdyPost(
3008          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3009  scoped_ptr<SpdyFrame> body(
3010      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3011  MockWrite writes[] = {
3012    CreateMockWrite(*req, 0),
3013    CreateMockWrite(*body, 1),
3014  };
3015
3016  scoped_ptr<SpdyFrame> resp(
3017      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3018  scoped_ptr<SpdyFrame> echo(
3019      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
3020  MockRead reads[] = {
3021    CreateMockRead(*resp, 2),
3022    MockRead(ASYNC, 0, 0, 3), // EOF
3023  };
3024
3025  DeterministicSocketData data(reads, arraysize(reads),
3026                               writes, arraysize(writes));
3027  MockConnect connect_data(SYNCHRONOUS, OK);
3028  data.set_connect_data(connect_data);
3029
3030  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3031
3032  CreateDeterministicNetworkSession();
3033  scoped_refptr<SpdySession> session =
3034      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3035  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3036            session->flow_control_state());
3037
3038  base::WeakPtr<SpdyStream> stream =
3039      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3040                                session, url, LOWEST, BoundNetLog());
3041  ASSERT_TRUE(stream.get() != NULL);
3042
3043  test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
3044  stream->SetDelegate(&delegate);
3045
3046  EXPECT_FALSE(stream->HasUrl());
3047  EXPECT_FALSE(stream->send_stalled_by_flow_control());
3048
3049  scoped_ptr<SpdyHeaderBlock> headers(
3050      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3051  EXPECT_EQ(ERR_IO_PENDING,
3052            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3053  EXPECT_TRUE(stream->HasUrl());
3054  EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
3055
3056  stall_function.Run(session.get(), stream.get());
3057
3058  data.RunFor(1);
3059
3060  EXPECT_TRUE(stream->send_stalled_by_flow_control());
3061
3062  unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
3063
3064  EXPECT_FALSE(stream->send_stalled_by_flow_control());
3065
3066  data.RunFor(3);
3067
3068  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
3069
3070  EXPECT_TRUE(delegate.send_headers_completed());
3071  EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
3072  EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version"));
3073  EXPECT_EQ(std::string(), delegate.TakeReceivedData());
3074  EXPECT_TRUE(data.at_write_eof());
3075}
3076
3077// Run the resume-after-unstall test with all possible stall and
3078// unstall sequences.
3079
3080TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
3081  if (GetParam() < kProtoSPDY31)
3082    return;
3083
3084  RunResumeAfterUnstallTest(
3085      base::Bind(&SpdySessionTest::StallSessionOnly,
3086                 base::Unretained(this)),
3087      base::Bind(&SpdySessionTest::UnstallSessionOnly,
3088                 base::Unretained(this)));
3089}
3090
3091// Equivalent to
3092// SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
3093TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
3094  if (GetParam() < kProtoSPDY31)
3095    return;
3096
3097  RunResumeAfterUnstallTest(
3098      base::Bind(&SpdySessionTest::StallStreamOnly,
3099                 base::Unretained(this)),
3100      base::Bind(&SpdySessionTest::UnstallStreamOnly,
3101                 base::Unretained(this)));
3102}
3103
3104TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
3105  if (GetParam() < kProtoSPDY31)
3106    return;
3107
3108  RunResumeAfterUnstallTest(
3109      base::Bind(&SpdySessionTest::StallSessionStream,
3110                 base::Unretained(this)),
3111      base::Bind(&SpdySessionTest::UnstallSessionStream,
3112                 base::Unretained(this)));
3113}
3114
3115TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
3116  if (GetParam() < kProtoSPDY31)
3117    return;
3118
3119  RunResumeAfterUnstallTest(
3120      base::Bind(&SpdySessionTest::StallStreamSession,
3121                 base::Unretained(this)),
3122      base::Bind(&SpdySessionTest::UnstallSessionStream,
3123                 base::Unretained(this)));
3124}
3125
3126TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
3127  if (GetParam() < kProtoSPDY31)
3128    return;
3129
3130  RunResumeAfterUnstallTest(
3131      base::Bind(&SpdySessionTest::StallStreamSession,
3132                 base::Unretained(this)),
3133      base::Bind(&SpdySessionTest::UnstallStreamSession,
3134                 base::Unretained(this)));
3135}
3136
3137TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
3138  if (GetParam() < kProtoSPDY31)
3139    return;
3140
3141  RunResumeAfterUnstallTest(
3142      base::Bind(&SpdySessionTest::StallSessionStream,
3143                 base::Unretained(this)),
3144      base::Bind(&SpdySessionTest::UnstallStreamSession,
3145                 base::Unretained(this)));
3146}
3147
3148// Cause a stall by reducing the flow control send window to 0. The
3149// streams should resume in priority order when that window is then
3150// increased.
3151TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
3152  if (GetParam() < kProtoSPDY31)
3153    return;
3154
3155  const char kStreamUrl[] = "http://www.google.com/";
3156  GURL url(kStreamUrl);
3157
3158  session_deps_.host_resolver->set_synchronous_mode(true);
3159
3160  scoped_ptr<SpdyFrame> req1(
3161      spdy_util_.ConstructSpdyPost(
3162          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3163  scoped_ptr<SpdyFrame> req2(
3164      spdy_util_.ConstructSpdyPost(
3165          kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
3166  scoped_ptr<SpdyFrame> body1(
3167      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3168  scoped_ptr<SpdyFrame> body2(
3169      spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
3170  MockWrite writes[] = {
3171    CreateMockWrite(*req1, 0),
3172    CreateMockWrite(*req2, 1),
3173    CreateMockWrite(*body2, 2),
3174    CreateMockWrite(*body1, 3),
3175  };
3176
3177  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3178  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3179  MockRead reads[] = {
3180    CreateMockRead(*resp1, 4),
3181    CreateMockRead(*resp2, 5),
3182    MockRead(ASYNC, 0, 0, 6), // EOF
3183  };
3184
3185  DeterministicSocketData data(reads, arraysize(reads),
3186                               writes, arraysize(writes));
3187  MockConnect connect_data(SYNCHRONOUS, OK);
3188  data.set_connect_data(connect_data);
3189
3190  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3191
3192  CreateDeterministicNetworkSession();
3193  scoped_refptr<SpdySession> session =
3194      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3195  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3196            session->flow_control_state());
3197
3198  base::WeakPtr<SpdyStream> stream1 =
3199      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3200                                session, url, LOWEST, BoundNetLog());
3201  ASSERT_TRUE(stream1.get() != NULL);
3202
3203  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
3204  stream1->SetDelegate(&delegate1);
3205
3206  EXPECT_FALSE(stream1->HasUrl());
3207
3208  base::WeakPtr<SpdyStream> stream2 =
3209      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3210                                session, url, MEDIUM, BoundNetLog());
3211  ASSERT_TRUE(stream2.get() != NULL);
3212
3213  test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
3214  stream2->SetDelegate(&delegate2);
3215
3216  EXPECT_FALSE(stream2->HasUrl());
3217
3218  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
3219  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3220
3221  StallSessionSend(session.get());
3222
3223  scoped_ptr<SpdyHeaderBlock> headers1(
3224      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3225  EXPECT_EQ(ERR_IO_PENDING,
3226            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
3227  EXPECT_TRUE(stream1->HasUrl());
3228  EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec());
3229
3230  data.RunFor(1);
3231  EXPECT_EQ(1u, stream1->stream_id());
3232  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
3233
3234  scoped_ptr<SpdyHeaderBlock> headers2(
3235      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3236  EXPECT_EQ(ERR_IO_PENDING,
3237            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
3238  EXPECT_TRUE(stream2->HasUrl());
3239  EXPECT_EQ(kStreamUrl, stream2->GetUrl().spec());
3240
3241  data.RunFor(1);
3242  EXPECT_EQ(3u, stream2->stream_id());
3243  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
3244
3245  // This should unstall only stream2.
3246  UnstallSessionSend(session.get(), kBodyDataSize);
3247
3248  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
3249  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3250
3251  data.RunFor(1);
3252
3253  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
3254  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3255
3256  // This should then unstall stream1.
3257  UnstallSessionSend(session.get(), kBodyDataSize);
3258
3259  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
3260  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3261
3262  data.RunFor(4);
3263
3264  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
3265  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
3266
3267  EXPECT_TRUE(delegate1.send_headers_completed());
3268  EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
3269  EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version"));
3270  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
3271
3272  EXPECT_TRUE(delegate2.send_headers_completed());
3273  EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
3274  EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version"));
3275  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
3276
3277  EXPECT_TRUE(data.at_write_eof());
3278}
3279
3280// Delegate that closes a given stream after sending its body.
3281class StreamClosingDelegate : public test::StreamDelegateWithBody {
3282 public:
3283  StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
3284                        base::StringPiece data)
3285      : StreamDelegateWithBody(stream, data) {}
3286
3287  virtual ~StreamClosingDelegate() {}
3288
3289  void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
3290    stream_to_close_ = stream_to_close;
3291  }
3292
3293  virtual void OnDataSent() OVERRIDE {
3294    test::StreamDelegateWithBody::OnDataSent();
3295    if (stream_to_close_.get()) {
3296      stream_to_close_->Close();
3297      EXPECT_EQ(NULL, stream_to_close_.get());
3298    }
3299  }
3300
3301 private:
3302  base::WeakPtr<SpdyStream> stream_to_close_;
3303};
3304
3305// Cause a stall by reducing the flow control send window to
3306// 0. Unstalling the session should properly handle deleted streams.
3307TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
3308  if (GetParam() < kProtoSPDY31)
3309    return;
3310
3311  const char kStreamUrl[] = "http://www.google.com/";
3312  GURL url(kStreamUrl);
3313
3314  session_deps_.host_resolver->set_synchronous_mode(true);
3315
3316  scoped_ptr<SpdyFrame> req1(
3317      spdy_util_.ConstructSpdyPost(
3318          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3319  scoped_ptr<SpdyFrame> req2(
3320      spdy_util_.ConstructSpdyPost(
3321          kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
3322  scoped_ptr<SpdyFrame> req3(
3323      spdy_util_.ConstructSpdyPost(
3324          kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
3325  scoped_ptr<SpdyFrame> body2(
3326      spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
3327  MockWrite writes[] = {
3328    CreateMockWrite(*req1, 0),
3329    CreateMockWrite(*req2, 1),
3330    CreateMockWrite(*req3, 2),
3331    CreateMockWrite(*body2, 3),
3332  };
3333
3334  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3335  MockRead reads[] = {
3336    CreateMockRead(*resp2, 4),
3337    MockRead(ASYNC, 0, 0, 5), // EOF
3338  };
3339
3340  DeterministicSocketData data(reads, arraysize(reads),
3341                               writes, arraysize(writes));
3342  MockConnect connect_data(SYNCHRONOUS, OK);
3343  data.set_connect_data(connect_data);
3344
3345  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3346
3347  CreateDeterministicNetworkSession();
3348  scoped_refptr<SpdySession> session =
3349      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3350  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3351            session->flow_control_state());
3352
3353  base::WeakPtr<SpdyStream> stream1 =
3354      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3355                                session, url, LOWEST, BoundNetLog());
3356  ASSERT_TRUE(stream1.get() != NULL);
3357
3358  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
3359  stream1->SetDelegate(&delegate1);
3360
3361  EXPECT_FALSE(stream1->HasUrl());
3362
3363  base::WeakPtr<SpdyStream> stream2 =
3364      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3365                                session, url, LOWEST, BoundNetLog());
3366  ASSERT_TRUE(stream2.get() != NULL);
3367
3368  StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
3369  stream2->SetDelegate(&delegate2);
3370
3371  EXPECT_FALSE(stream2->HasUrl());
3372
3373  base::WeakPtr<SpdyStream> stream3 =
3374      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3375                                session, url, LOWEST, BoundNetLog());
3376  ASSERT_TRUE(stream3.get() != NULL);
3377
3378  test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
3379  stream3->SetDelegate(&delegate3);
3380
3381  EXPECT_FALSE(stream3->HasUrl());
3382
3383  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
3384  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3385  EXPECT_FALSE(stream3->send_stalled_by_flow_control());
3386
3387  StallSessionSend(session.get());
3388
3389  scoped_ptr<SpdyHeaderBlock> headers1(
3390      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3391  EXPECT_EQ(ERR_IO_PENDING,
3392            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
3393  EXPECT_TRUE(stream1->HasUrl());
3394  EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec());
3395
3396  data.RunFor(1);
3397  EXPECT_EQ(1u, stream1->stream_id());
3398  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
3399
3400  scoped_ptr<SpdyHeaderBlock> headers2(
3401      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3402  EXPECT_EQ(ERR_IO_PENDING,
3403            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
3404  EXPECT_TRUE(stream2->HasUrl());
3405  EXPECT_EQ(kStreamUrl, stream2->GetUrl().spec());
3406
3407  data.RunFor(1);
3408  EXPECT_EQ(3u, stream2->stream_id());
3409  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
3410
3411  scoped_ptr<SpdyHeaderBlock> headers3(
3412      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3413  EXPECT_EQ(ERR_IO_PENDING,
3414            stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
3415  EXPECT_TRUE(stream3->HasUrl());
3416  EXPECT_EQ(kStreamUrl, stream3->GetUrl().spec());
3417
3418  data.RunFor(1);
3419  EXPECT_EQ(5u, stream3->stream_id());
3420  EXPECT_TRUE(stream3->send_stalled_by_flow_control());
3421
3422  SpdyStreamId stream_id1 = stream1->stream_id();
3423  SpdyStreamId stream_id2 = stream2->stream_id();
3424  SpdyStreamId stream_id3 = stream3->stream_id();
3425
3426  // Close stream1 preemptively.
3427  session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
3428  EXPECT_EQ(NULL, stream1.get());
3429
3430  EXPECT_FALSE(session->IsStreamActive(stream_id1));
3431  EXPECT_TRUE(session->IsStreamActive(stream_id2));
3432  EXPECT_TRUE(session->IsStreamActive(stream_id3));
3433
3434  // Unstall stream2, which should then close stream3.
3435  delegate2.set_stream_to_close(stream3);
3436  UnstallSessionSend(session.get(), kBodyDataSize);
3437
3438  data.RunFor(1);
3439  EXPECT_EQ(NULL, stream3.get());
3440
3441  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3442  EXPECT_FALSE(session->IsStreamActive(stream_id1));
3443  EXPECT_TRUE(session->IsStreamActive(stream_id2));
3444  EXPECT_FALSE(session->IsStreamActive(stream_id3));
3445
3446  data.RunFor(2);
3447  EXPECT_EQ(NULL, stream2.get());
3448
3449  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
3450  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
3451  EXPECT_EQ(OK, delegate3.WaitForClose());
3452
3453  EXPECT_TRUE(delegate1.send_headers_completed());
3454  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
3455
3456  EXPECT_TRUE(delegate2.send_headers_completed());
3457  EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
3458  EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version"));
3459  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
3460
3461  EXPECT_TRUE(delegate3.send_headers_completed());
3462  EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
3463
3464  EXPECT_TRUE(data.at_write_eof());
3465}
3466
3467// Cause a stall by reducing the flow control send window to
3468// 0. Unstalling the session should properly handle the session itself
3469// being closed.
3470TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
3471  if (GetParam() < kProtoSPDY31)
3472    return;
3473
3474  const char kStreamUrl[] = "http://www.google.com/";
3475  GURL url(kStreamUrl);
3476
3477  session_deps_.host_resolver->set_synchronous_mode(true);
3478
3479  scoped_ptr<SpdyFrame> req1(
3480      spdy_util_.ConstructSpdyPost(
3481          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3482  scoped_ptr<SpdyFrame> req2(
3483      spdy_util_.ConstructSpdyPost(
3484          kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
3485  scoped_ptr<SpdyFrame> body1(
3486      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
3487  MockWrite writes[] = {
3488    CreateMockWrite(*req1, 0),
3489    CreateMockWrite(*req2, 1),
3490  };
3491
3492  MockRead reads[] = {
3493    MockRead(ASYNC, 0, 0, 2), // EOF
3494  };
3495
3496  DeterministicSocketData data(reads, arraysize(reads),
3497                               writes, arraysize(writes));
3498  MockConnect connect_data(SYNCHRONOUS, OK);
3499  data.set_connect_data(connect_data);
3500
3501  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3502
3503  CreateDeterministicNetworkSession();
3504  scoped_refptr<SpdySession> session =
3505      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3506  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3507            session->flow_control_state());
3508
3509  base::WeakPtr<SpdyStream> stream1 =
3510      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3511                                session, url, LOWEST, BoundNetLog());
3512  ASSERT_TRUE(stream1.get() != NULL);
3513
3514  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
3515  stream1->SetDelegate(&delegate1);
3516
3517  EXPECT_FALSE(stream1->HasUrl());
3518
3519  base::WeakPtr<SpdyStream> stream2 =
3520      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3521                                session, url, LOWEST, BoundNetLog());
3522  ASSERT_TRUE(stream2.get() != NULL);
3523
3524  test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
3525  stream2->SetDelegate(&delegate2);
3526
3527  EXPECT_FALSE(stream2->HasUrl());
3528
3529  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
3530  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3531
3532  StallSessionSend(session.get());
3533
3534  scoped_ptr<SpdyHeaderBlock> headers1(
3535      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3536  EXPECT_EQ(ERR_IO_PENDING,
3537            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
3538  EXPECT_TRUE(stream1->HasUrl());
3539  EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec());
3540
3541  data.RunFor(1);
3542  EXPECT_EQ(1u, stream1->stream_id());
3543  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
3544
3545  scoped_ptr<SpdyHeaderBlock> headers2(
3546      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3547  EXPECT_EQ(ERR_IO_PENDING,
3548            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
3549  EXPECT_TRUE(stream2->HasUrl());
3550  EXPECT_EQ(kStreamUrl, stream2->GetUrl().spec());
3551
3552  data.RunFor(1);
3553  EXPECT_EQ(3u, stream2->stream_id());
3554  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
3555
3556  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
3557
3558  // Unstall stream1.
3559  UnstallSessionSend(session.get(), kBodyDataSize);
3560
3561  // Close the session (since we can't do it from within the delegate
3562  // method, since it's in the stream's loop).
3563  session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
3564  session = NULL;
3565
3566  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
3567
3568  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
3569  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
3570
3571  EXPECT_TRUE(delegate1.send_headers_completed());
3572  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
3573
3574  EXPECT_TRUE(delegate2.send_headers_completed());
3575  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
3576
3577  EXPECT_TRUE(data.at_write_eof());
3578}
3579
3580}  // namespace net
3581