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