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