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