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