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/base64.h"
8#include "base/bind.h"
9#include "base/callback.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/run_loop.h"
12#include "base/test/histogram_tester.h"
13#include "net/base/io_buffer.h"
14#include "net/base/ip_endpoint.h"
15#include "net/base/net_log_unittest.h"
16#include "net/base/request_priority.h"
17#include "net/base/test_data_directory.h"
18#include "net/base/test_data_stream.h"
19#include "net/socket/client_socket_pool_manager.h"
20#include "net/socket/next_proto.h"
21#include "net/socket/socket_test_util.h"
22#include "net/spdy/spdy_http_utils.h"
23#include "net/spdy/spdy_session_pool.h"
24#include "net/spdy/spdy_session_test_util.h"
25#include "net/spdy/spdy_stream.h"
26#include "net/spdy/spdy_stream_test_util.h"
27#include "net/spdy/spdy_test_util_common.h"
28#include "net/spdy/spdy_test_utils.h"
29#include "net/test/cert_test_util.h"
30#include "testing/platform_test.h"
31
32namespace net {
33
34namespace {
35
36static const char kTestUrl[] = "http://www.example.org/";
37static const char kTestHost[] = "www.example.org";
38static const int kTestPort = 80;
39
40const char kBodyData[] = "Body data";
41const size_t kBodyDataSize = arraysize(kBodyData);
42const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize);
43
44static base::TimeDelta g_time_delta;
45base::TimeTicks TheNearFuture() {
46  return base::TimeTicks::Now() + g_time_delta;
47}
48
49}  // namespace
50
51class SpdySessionTest : public PlatformTest,
52                        public ::testing::WithParamInterface<NextProto> {
53 public:
54  // Functions used with RunResumeAfterUnstallTest().
55
56  void StallSessionOnly(SpdySession* session, SpdyStream* stream) {
57    StallSessionSend(session);
58  }
59
60  void StallStreamOnly(SpdySession* session, SpdyStream* stream) {
61    StallStreamSend(stream);
62  }
63
64  void StallSessionStream(SpdySession* session, SpdyStream* stream) {
65    StallSessionSend(session);
66    StallStreamSend(stream);
67  }
68
69  void StallStreamSession(SpdySession* session, SpdyStream* stream) {
70    StallStreamSend(stream);
71    StallSessionSend(session);
72  }
73
74  void UnstallSessionOnly(SpdySession* session,
75                          SpdyStream* stream,
76                          int32 delta_window_size) {
77    UnstallSessionSend(session, delta_window_size);
78  }
79
80  void UnstallStreamOnly(SpdySession* session,
81                         SpdyStream* stream,
82                         int32 delta_window_size) {
83    UnstallStreamSend(stream, delta_window_size);
84  }
85
86  void UnstallSessionStream(SpdySession* session,
87                            SpdyStream* stream,
88                            int32 delta_window_size) {
89    UnstallSessionSend(session, delta_window_size);
90    UnstallStreamSend(stream, delta_window_size);
91  }
92
93  void UnstallStreamSession(SpdySession* session,
94                            SpdyStream* stream,
95                            int32 delta_window_size) {
96    UnstallStreamSend(stream, delta_window_size);
97    UnstallSessionSend(session, delta_window_size);
98  }
99
100 protected:
101  SpdySessionTest()
102      : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
103            HttpNetworkSession::NORMAL_SOCKET_POOL)),
104        old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
105            HttpNetworkSession::NORMAL_SOCKET_POOL)),
106        spdy_util_(GetParam()),
107        session_deps_(GetParam()),
108        spdy_session_pool_(NULL),
109        test_url_(kTestUrl),
110        test_host_port_pair_(kTestHost, kTestPort),
111        key_(test_host_port_pair_, ProxyServer::Direct(),
112             PRIVACY_MODE_DISABLED) {
113  }
114
115  virtual ~SpdySessionTest() {
116    // Important to restore the per-pool limit first, since the pool limit must
117    // always be greater than group limit, and the tests reduce both limits.
118    ClientSocketPoolManager::set_max_sockets_per_pool(
119        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
120    ClientSocketPoolManager::set_max_sockets_per_group(
121        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
122  }
123
124  virtual void SetUp() OVERRIDE {
125    g_time_delta = base::TimeDelta();
126  }
127
128  void CreateDeterministicNetworkSession() {
129    http_session_ =
130        SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
131    spdy_session_pool_ = http_session_->spdy_session_pool();
132  }
133
134  void CreateNetworkSession() {
135    http_session_ =
136        SpdySessionDependencies::SpdyCreateSession(&session_deps_);
137    spdy_session_pool_ = http_session_->spdy_session_pool();
138  }
139
140  void StallSessionSend(SpdySession* session) {
141    // Reduce the send window size to 0 to stall.
142    while (session->session_send_window_size_ > 0) {
143      session->DecreaseSendWindowSize(
144          std::min(kMaxSpdyFrameChunkSize, session->session_send_window_size_));
145    }
146  }
147
148  void UnstallSessionSend(SpdySession* session, int32 delta_window_size) {
149    session->IncreaseSendWindowSize(delta_window_size);
150  }
151
152  void StallStreamSend(SpdyStream* stream) {
153    // Reduce the send window size to 0 to stall.
154    while (stream->send_window_size() > 0) {
155      stream->DecreaseSendWindowSize(
156          std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
157    }
158  }
159
160  void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) {
161    stream->IncreaseSendWindowSize(delta_window_size);
162  }
163
164  void RunResumeAfterUnstallTest(
165      const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
166      const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
167          unstall_function);
168
169  // Original socket limits.  Some tests set these.  Safest to always restore
170  // them once each test has been run.
171  int old_max_group_sockets_;
172  int old_max_pool_sockets_;
173
174  SpdyTestUtil spdy_util_;
175  SpdySessionDependencies session_deps_;
176  scoped_refptr<HttpNetworkSession> http_session_;
177  SpdySessionPool* spdy_session_pool_;
178  GURL test_url_;
179  HostPortPair test_host_port_pair_;
180  SpdySessionKey key_;
181};
182
183INSTANTIATE_TEST_CASE_P(
184    NextProto,
185    SpdySessionTest,
186    testing::Values(kProtoDeprecatedSPDY2,
187                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
188
189// Try to create a SPDY session that will fail during
190// initialization. Nothing should blow up.
191TEST_P(SpdySessionTest, InitialReadError) {
192  CreateDeterministicNetworkSession();
193
194  base::WeakPtr<SpdySession> session = TryCreateFakeSpdySessionExpectingFailure(
195      spdy_session_pool_, key_, ERR_CONNECTION_CLOSED);
196  EXPECT_TRUE(session);
197  // Flush the read.
198  base::RunLoop().RunUntilIdle();
199  EXPECT_FALSE(session);
200}
201
202namespace {
203
204// A helper class that vends a callback that, when fired, destroys a
205// given SpdyStreamRequest.
206class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
207 public:
208  StreamRequestDestroyingCallback() {}
209
210  virtual ~StreamRequestDestroyingCallback() {}
211
212  void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) {
213    request_ = request.Pass();
214  }
215
216  CompletionCallback MakeCallback() {
217    return base::Bind(&StreamRequestDestroyingCallback::OnComplete,
218                      base::Unretained(this));
219  }
220
221 private:
222  void OnComplete(int result) {
223    request_.reset();
224    SetResult(result);
225  }
226
227  scoped_ptr<SpdyStreamRequest> request_;
228};
229
230}  // namespace
231
232// Request kInitialMaxConcurrentStreams streams.  Request two more
233// streams, but have the callback for one destroy the second stream
234// request. Close the session. Nothing should blow up. This is a
235// regression test for http://crbug.com/250841 .
236TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
237  session_deps_.host_resolver->set_synchronous_mode(true);
238
239  MockRead reads[] = {MockRead(ASYNC, 0, 0), };
240
241  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
242  MockConnect connect_data(SYNCHRONOUS, OK);
243  data.set_connect_data(connect_data);
244  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
245
246  CreateDeterministicNetworkSession();
247
248  base::WeakPtr<SpdySession> session =
249      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
250
251  // Create the maximum number of concurrent streams.
252  for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
253    base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
254        SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog());
255    ASSERT_TRUE(spdy_stream != NULL);
256  }
257
258  SpdyStreamRequest request1;
259  scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest);
260
261  StreamRequestDestroyingCallback callback1;
262  ASSERT_EQ(ERR_IO_PENDING,
263            request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM,
264                                  session,
265                                  test_url_,
266                                  MEDIUM,
267                                  BoundNetLog(),
268                                  callback1.MakeCallback()));
269
270  // |callback2| is never called.
271  TestCompletionCallback callback2;
272  ASSERT_EQ(ERR_IO_PENDING,
273            request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM,
274                                   session,
275                                   test_url_,
276                                   MEDIUM,
277                                   BoundNetLog(),
278                                   callback2.callback()));
279
280  callback1.SetRequestToDestroy(request2.Pass());
281
282  session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
283
284  EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
285}
286
287// A session receiving a GOAWAY frame with no active streams should close.
288TEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
289  session_deps_.host_resolver->set_synchronous_mode(true);
290
291  MockConnect connect_data(SYNCHRONOUS, OK);
292  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
293  MockRead reads[] = {
294    CreateMockRead(*goaway, 0),
295  };
296  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
297  data.set_connect_data(connect_data);
298  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
299
300  CreateDeterministicNetworkSession();
301
302  base::WeakPtr<SpdySession> session =
303      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
304
305  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
306
307  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
308
309  // Read and process the GOAWAY frame.
310  data.RunFor(1);
311  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
312  base::RunLoop().RunUntilIdle();
313  EXPECT_TRUE(session == NULL);
314}
315
316// A session receiving a GOAWAY frame immediately with no active
317// streams should then close.
318TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
319  session_deps_.host_resolver->set_synchronous_mode(true);
320
321  MockConnect connect_data(SYNCHRONOUS, OK);
322  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
323  MockRead reads[] = {
324    CreateMockRead(*goaway, 0, SYNCHRONOUS),
325  };
326  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
327  data.set_connect_data(connect_data);
328  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
329
330  CreateDeterministicNetworkSession();
331
332  data.StopAfter(1);
333
334  base::WeakPtr<SpdySession> session =
335      TryCreateInsecureSpdySessionExpectingFailure(
336          http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
337  base::RunLoop().RunUntilIdle();
338
339  EXPECT_FALSE(session);
340  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
341}
342
343// A session receiving a GOAWAY frame with active streams should close
344// when the last active stream is closed.
345TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
346  session_deps_.host_resolver->set_synchronous_mode(true);
347
348  MockConnect connect_data(SYNCHRONOUS, OK);
349  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
350  MockRead reads[] = {
351    CreateMockRead(*goaway, 2),
352    MockRead(ASYNC, 0, 3)  // EOF
353  };
354  scoped_ptr<SpdyFrame> req1(
355      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
356  scoped_ptr<SpdyFrame> req2(
357      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
358  MockWrite writes[] = {
359    CreateMockWrite(*req1, 0),
360    CreateMockWrite(*req2, 1),
361  };
362  DeterministicSocketData data(reads, arraysize(reads),
363                               writes, arraysize(writes));
364  data.set_connect_data(connect_data);
365  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
366
367  CreateDeterministicNetworkSession();
368
369  base::WeakPtr<SpdySession> session =
370      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
371
372  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
373
374  GURL url(kDefaultURL);
375  base::WeakPtr<SpdyStream> spdy_stream1 =
376      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
377                                session, url, MEDIUM, BoundNetLog());
378  test::StreamDelegateDoNothing delegate1(spdy_stream1);
379  spdy_stream1->SetDelegate(&delegate1);
380
381  base::WeakPtr<SpdyStream> spdy_stream2 =
382      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
383                                session, url, MEDIUM, BoundNetLog());
384  test::StreamDelegateDoNothing delegate2(spdy_stream2);
385  spdy_stream2->SetDelegate(&delegate2);
386
387  scoped_ptr<SpdyHeaderBlock> headers(
388      spdy_util_.ConstructGetHeaderBlock(url.spec()));
389  scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
390
391  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
392  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
393  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
394  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
395
396  data.RunFor(2);
397
398  EXPECT_EQ(1u, spdy_stream1->stream_id());
399  EXPECT_EQ(3u, spdy_stream2->stream_id());
400
401  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
402
403  // Read and process the GOAWAY frame.
404  data.RunFor(1);
405
406  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
407
408  EXPECT_FALSE(session->IsStreamActive(3));
409  EXPECT_EQ(NULL, spdy_stream2.get());
410  EXPECT_TRUE(session->IsStreamActive(1));
411
412  EXPECT_TRUE(session->IsGoingAway());
413
414  // Should close the session.
415  spdy_stream1->Close();
416  EXPECT_EQ(NULL, spdy_stream1.get());
417
418  base::MessageLoop::current()->RunUntilIdle();
419  EXPECT_TRUE(session == NULL);
420}
421
422// Have a session receive two GOAWAY frames, with the last one causing
423// the last active stream to be closed. The session should then be
424// closed after the second GOAWAY frame.
425TEST_P(SpdySessionTest, GoAwayTwice) {
426  session_deps_.host_resolver->set_synchronous_mode(true);
427
428  MockConnect connect_data(SYNCHRONOUS, OK);
429  scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
430  scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
431  MockRead reads[] = {
432    CreateMockRead(*goaway1, 2),
433    CreateMockRead(*goaway2, 3),
434    MockRead(ASYNC, 0, 4)  // EOF
435  };
436  scoped_ptr<SpdyFrame> req1(
437      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
438  scoped_ptr<SpdyFrame> req2(
439      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
440  MockWrite writes[] = {
441    CreateMockWrite(*req1, 0),
442    CreateMockWrite(*req2, 1),
443  };
444  DeterministicSocketData data(reads, arraysize(reads),
445                               writes, arraysize(writes));
446  data.set_connect_data(connect_data);
447  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
448
449  CreateDeterministicNetworkSession();
450
451  base::WeakPtr<SpdySession> session =
452      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
453
454  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
455
456  GURL url(kDefaultURL);
457  base::WeakPtr<SpdyStream> spdy_stream1 =
458      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
459                                session, url, MEDIUM, BoundNetLog());
460  test::StreamDelegateDoNothing delegate1(spdy_stream1);
461  spdy_stream1->SetDelegate(&delegate1);
462
463  base::WeakPtr<SpdyStream> spdy_stream2 =
464      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
465                                session, url, MEDIUM, BoundNetLog());
466  test::StreamDelegateDoNothing delegate2(spdy_stream2);
467  spdy_stream2->SetDelegate(&delegate2);
468
469  scoped_ptr<SpdyHeaderBlock> headers(
470      spdy_util_.ConstructGetHeaderBlock(url.spec()));
471  scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
472
473  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
474  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
475  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
476  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
477
478  data.RunFor(2);
479
480  EXPECT_EQ(1u, spdy_stream1->stream_id());
481  EXPECT_EQ(3u, spdy_stream2->stream_id());
482
483  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
484
485  // Read and process the first GOAWAY frame.
486  data.RunFor(1);
487
488  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
489
490  EXPECT_FALSE(session->IsStreamActive(3));
491  EXPECT_EQ(NULL, spdy_stream2.get());
492  EXPECT_TRUE(session->IsStreamActive(1));
493  EXPECT_TRUE(session->IsGoingAway());
494
495  // Read and process the second GOAWAY frame, which should close the
496  // session.
497  data.RunFor(1);
498  base::MessageLoop::current()->RunUntilIdle();
499  EXPECT_TRUE(session == NULL);
500}
501
502// Have a session with active streams receive a GOAWAY frame and then
503// close it. It should handle the close properly (i.e., not try to
504// make itself unavailable in its pool twice).
505TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
506  session_deps_.host_resolver->set_synchronous_mode(true);
507
508  MockConnect connect_data(SYNCHRONOUS, OK);
509  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
510  MockRead reads[] = {
511    CreateMockRead(*goaway, 2),
512    MockRead(ASYNC, 0, 3)  // EOF
513  };
514  scoped_ptr<SpdyFrame> req1(
515      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
516  scoped_ptr<SpdyFrame> req2(
517      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
518  MockWrite writes[] = {
519    CreateMockWrite(*req1, 0),
520    CreateMockWrite(*req2, 1),
521  };
522  DeterministicSocketData data(reads, arraysize(reads),
523                               writes, arraysize(writes));
524  data.set_connect_data(connect_data);
525  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
526
527  CreateDeterministicNetworkSession();
528
529  base::WeakPtr<SpdySession> session =
530      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
531
532  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
533
534  GURL url(kDefaultURL);
535  base::WeakPtr<SpdyStream> spdy_stream1 =
536      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
537                                session, url, MEDIUM, BoundNetLog());
538  test::StreamDelegateDoNothing delegate1(spdy_stream1);
539  spdy_stream1->SetDelegate(&delegate1);
540
541  base::WeakPtr<SpdyStream> spdy_stream2 =
542      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
543                                session, url, MEDIUM, BoundNetLog());
544  test::StreamDelegateDoNothing delegate2(spdy_stream2);
545  spdy_stream2->SetDelegate(&delegate2);
546
547  scoped_ptr<SpdyHeaderBlock> headers(
548      spdy_util_.ConstructGetHeaderBlock(url.spec()));
549  scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
550
551  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
552  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
553  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
554  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
555
556  data.RunFor(2);
557
558  EXPECT_EQ(1u, spdy_stream1->stream_id());
559  EXPECT_EQ(3u, spdy_stream2->stream_id());
560
561  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
562
563  // Read and process the GOAWAY frame.
564  data.RunFor(1);
565
566  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
567
568  EXPECT_FALSE(session->IsStreamActive(3));
569  EXPECT_EQ(NULL, spdy_stream2.get());
570  EXPECT_TRUE(session->IsStreamActive(1));
571  EXPECT_TRUE(session->IsGoingAway());
572
573  session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
574  EXPECT_EQ(NULL, spdy_stream1.get());
575
576  base::MessageLoop::current()->RunUntilIdle();
577  EXPECT_TRUE(session == NULL);
578}
579
580// Process a joint read buffer which causes the session to begin draining, and
581// then processes a GOAWAY. The session should gracefully drain. Regression test
582// for crbug.com/379469
583TEST_P(SpdySessionTest, GoAwayWhileDraining) {
584  session_deps_.host_resolver->set_synchronous_mode(true);
585
586  scoped_ptr<SpdyFrame> req(
587      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
588  MockWrite writes[] = {
589      CreateMockWrite(*req, 0),
590  };
591
592  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
593  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
594  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
595  size_t joint_size = goaway->size() * 2 + body->size();
596
597  // Compose interleaved |goaway| and |body| frames into a single read.
598  scoped_ptr<char[]> buffer(new char[joint_size]);
599  {
600    size_t out = 0;
601    memcpy(&buffer[out], goaway->data(), goaway->size());
602    out += goaway->size();
603    memcpy(&buffer[out], body->data(), body->size());
604    out += body->size();
605    memcpy(&buffer[out], goaway->data(), goaway->size());
606    out += goaway->size();
607    ASSERT_EQ(out, joint_size);
608  }
609  SpdyFrame joint_frames(buffer.get(), joint_size, false);
610
611  MockRead reads[] = {
612      CreateMockRead(*resp, 1), CreateMockRead(joint_frames, 2),
613      MockRead(ASYNC, 0, 3)  // EOF
614  };
615
616  MockConnect connect_data(SYNCHRONOUS, OK);
617  DeterministicSocketData data(
618      reads, arraysize(reads), writes, arraysize(writes));
619  data.set_connect_data(connect_data);
620  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
621
622  CreateDeterministicNetworkSession();
623  base::WeakPtr<SpdySession> session =
624      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
625
626  GURL url(kDefaultURL);
627  base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
628      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
629  test::StreamDelegateDoNothing delegate(spdy_stream);
630  spdy_stream->SetDelegate(&delegate);
631
632  scoped_ptr<SpdyHeaderBlock> headers(
633      spdy_util_.ConstructGetHeaderBlock(url.spec()));
634  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
635  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
636
637  data.RunFor(3);
638  base::MessageLoop::current()->RunUntilIdle();
639
640  // Stream and session closed gracefully.
641  EXPECT_TRUE(delegate.StreamIsClosed());
642  EXPECT_EQ(OK, delegate.WaitForClose());
643  EXPECT_EQ(kUploadData, delegate.TakeReceivedData());
644  EXPECT_TRUE(session == NULL);
645}
646
647// Try to create a stream after receiving a GOAWAY frame. It should
648// fail.
649TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
650  session_deps_.host_resolver->set_synchronous_mode(true);
651
652  MockConnect connect_data(SYNCHRONOUS, OK);
653  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
654  MockRead reads[] = {
655    CreateMockRead(*goaway, 1),
656    MockRead(ASYNC, 0, 2)  // EOF
657  };
658  scoped_ptr<SpdyFrame> req(
659      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
660  MockWrite writes[] = {
661    CreateMockWrite(*req, 0),
662  };
663  DeterministicSocketData data(reads, arraysize(reads),
664                               writes, arraysize(writes));
665  data.set_connect_data(connect_data);
666  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
667
668  CreateDeterministicNetworkSession();
669
670  base::WeakPtr<SpdySession> session =
671      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
672
673  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
674
675  GURL url(kDefaultURL);
676  base::WeakPtr<SpdyStream> spdy_stream =
677      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
678                                session, url, MEDIUM, BoundNetLog());
679  test::StreamDelegateDoNothing delegate(spdy_stream);
680  spdy_stream->SetDelegate(&delegate);
681
682  scoped_ptr<SpdyHeaderBlock> headers(
683      spdy_util_.ConstructGetHeaderBlock(url.spec()));
684  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
685  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
686
687  data.RunFor(1);
688
689  EXPECT_EQ(1u, spdy_stream->stream_id());
690
691  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
692
693  // Read and process the GOAWAY frame.
694  data.RunFor(1);
695
696  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
697  EXPECT_TRUE(session->IsStreamActive(1));
698
699  SpdyStreamRequest stream_request;
700  int rv = stream_request.StartRequest(
701      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog(),
702      CompletionCallback());
703  EXPECT_EQ(ERR_FAILED, rv);
704
705  // Read and process EOF.
706  data.RunFor(1);
707
708  EXPECT_TRUE(session == NULL);
709}
710
711// Receiving a SYN_STREAM frame after a GOAWAY frame should result in
712// the stream being refused.
713TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
714  session_deps_.host_resolver->set_synchronous_mode(true);
715
716  MockConnect connect_data(SYNCHRONOUS, OK);
717  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
718  scoped_ptr<SpdyFrame>
719      push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kDefaultURL));
720  MockRead reads[] = {
721    CreateMockRead(*goaway, 1),
722    CreateMockRead(*push, 2),
723    MockRead(ASYNC, 0, 4)  // EOF
724  };
725  scoped_ptr<SpdyFrame> req(
726      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
727  scoped_ptr<SpdyFrame> rst(
728      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
729  MockWrite writes[] = {
730    CreateMockWrite(*req, 0),
731    CreateMockWrite(*rst, 3)
732  };
733  DeterministicSocketData data(reads, arraysize(reads),
734                               writes, arraysize(writes));
735  data.set_connect_data(connect_data);
736  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
737
738  CreateDeterministicNetworkSession();
739
740  base::WeakPtr<SpdySession> session =
741      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
742
743  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
744
745  GURL url(kDefaultURL);
746  base::WeakPtr<SpdyStream> spdy_stream =
747      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
748                                session, url, MEDIUM, BoundNetLog());
749  test::StreamDelegateDoNothing delegate(spdy_stream);
750  spdy_stream->SetDelegate(&delegate);
751
752  scoped_ptr<SpdyHeaderBlock> headers(
753      spdy_util_.ConstructGetHeaderBlock(url.spec()));
754  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
755  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
756
757  data.RunFor(1);
758
759  EXPECT_EQ(1u, spdy_stream->stream_id());
760
761  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
762
763  // Read and process the GOAWAY frame.
764  data.RunFor(1);
765
766  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
767  EXPECT_TRUE(session->IsStreamActive(1));
768
769  // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
770  // and EOF.
771  data.RunFor(3);
772  base::MessageLoop::current()->RunUntilIdle();
773  EXPECT_TRUE(session == NULL);
774}
775
776// A session observing a network change with active streams should close
777// when the last active stream is closed.
778TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
779  session_deps_.host_resolver->set_synchronous_mode(true);
780
781  MockConnect connect_data(SYNCHRONOUS, OK);
782  MockRead reads[] = {
783    MockRead(ASYNC, 0, 1)  // EOF
784  };
785  scoped_ptr<SpdyFrame> req1(
786      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
787  MockWrite writes[] = {
788    CreateMockWrite(*req1, 0),
789  };
790  DeterministicSocketData data(reads, arraysize(reads),
791                               writes, arraysize(writes));
792  data.set_connect_data(connect_data);
793  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
794
795  CreateDeterministicNetworkSession();
796
797  base::WeakPtr<SpdySession> session =
798      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
799
800  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
801
802  base::WeakPtr<SpdyStream> spdy_stream =
803      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session,
804                                GURL(kDefaultURL), MEDIUM, BoundNetLog());
805  test::StreamDelegateDoNothing delegate(spdy_stream);
806  spdy_stream->SetDelegate(&delegate);
807
808  scoped_ptr<SpdyHeaderBlock> headers(
809      spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
810
811  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
812  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
813
814  data.RunFor(1);
815
816  EXPECT_EQ(1u, spdy_stream->stream_id());
817
818  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
819
820  spdy_session_pool_->OnIPAddressChanged();
821
822  // The SpdySessionPool behavior differs based on how the OSs reacts to
823  // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
824#if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
825  // For OSs where the TCP connections will close upon relevant network
826  // changes, SpdySessionPool doesn't need to force them to close, so in these
827  // cases verify the session has become unavailable but remains open and the
828  // pre-existing stream is still active.
829  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
830
831  EXPECT_TRUE(session->IsGoingAway());
832
833  EXPECT_TRUE(session->IsStreamActive(1));
834
835  // Should close the session.
836  spdy_stream->Close();
837#endif
838  EXPECT_EQ(NULL, spdy_stream.get());
839
840  base::MessageLoop::current()->RunUntilIdle();
841  EXPECT_TRUE(session == NULL);
842}
843
844TEST_P(SpdySessionTest, ClientPing) {
845  session_deps_.enable_ping = true;
846  session_deps_.host_resolver->set_synchronous_mode(true);
847
848  MockConnect connect_data(SYNCHRONOUS, OK);
849  scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
850  MockRead reads[] = {
851    CreateMockRead(*read_ping, 1),
852    MockRead(ASYNC, 0, 0, 2)  // EOF
853  };
854  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
855  MockWrite writes[] = {
856    CreateMockWrite(*write_ping, 0),
857  };
858  DeterministicSocketData data(
859      reads, arraysize(reads), writes, arraysize(writes));
860  data.set_connect_data(connect_data);
861  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
862
863  CreateDeterministicNetworkSession();
864
865  base::WeakPtr<SpdySession> session =
866      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
867
868  base::WeakPtr<SpdyStream> spdy_stream1 =
869      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
870                                session, test_url_, MEDIUM, BoundNetLog());
871  ASSERT_TRUE(spdy_stream1.get() != NULL);
872  test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
873  spdy_stream1->SetDelegate(&delegate);
874
875  base::TimeTicks before_ping_time = base::TimeTicks::Now();
876
877  session->set_connection_at_risk_of_loss_time(
878      base::TimeDelta::FromSeconds(-1));
879  session->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
880
881  session->SendPrefacePingIfNoneInFlight();
882
883  data.RunFor(2);
884
885  session->CheckPingStatus(before_ping_time);
886
887  EXPECT_EQ(0, session->pings_in_flight());
888  EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1));
889  EXPECT_FALSE(session->check_ping_status_pending());
890  EXPECT_GE(session->last_activity_time(), before_ping_time);
891
892  data.RunFor(1);
893
894  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
895
896  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
897  EXPECT_TRUE(session == NULL);
898}
899
900TEST_P(SpdySessionTest, ServerPing) {
901  session_deps_.host_resolver->set_synchronous_mode(true);
902
903  MockConnect connect_data(SYNCHRONOUS, OK);
904  scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
905  MockRead reads[] = {
906    CreateMockRead(*read_ping),
907    MockRead(SYNCHRONOUS, 0, 0)  // EOF
908  };
909  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
910  MockWrite writes[] = {
911    CreateMockWrite(*write_ping),
912  };
913  StaticSocketDataProvider data(
914      reads, arraysize(reads), writes, arraysize(writes));
915  data.set_connect_data(connect_data);
916  session_deps_.socket_factory->AddSocketDataProvider(&data);
917
918  CreateNetworkSession();
919
920  base::WeakPtr<SpdySession> session =
921      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
922
923  base::WeakPtr<SpdyStream> spdy_stream1 =
924      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
925                                session, test_url_, MEDIUM, BoundNetLog());
926  ASSERT_TRUE(spdy_stream1.get() != NULL);
927  test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
928  spdy_stream1->SetDelegate(&delegate);
929
930  // Flush the read completion task.
931  base::MessageLoop::current()->RunUntilIdle();
932
933  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
934
935  EXPECT_TRUE(session == NULL);
936  EXPECT_EQ(NULL, spdy_stream1.get());
937}
938
939// Cause a ping to be sent out while producing a write. The write loop
940// should handle this properly, i.e. another DoWriteLoop task should
941// not be posted. This is a regression test for
942// http://crbug.com/261043 .
943TEST_P(SpdySessionTest, PingAndWriteLoop) {
944  session_deps_.enable_ping = true;
945  session_deps_.time_func = TheNearFuture;
946
947  MockConnect connect_data(SYNCHRONOUS, OK);
948  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
949  scoped_ptr<SpdyFrame> req(
950      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
951  MockWrite writes[] = {
952    CreateMockWrite(*req, 0),
953    CreateMockWrite(*write_ping, 1),
954  };
955
956  MockRead reads[] = {
957    MockRead(ASYNC, 0, 2)  // EOF
958  };
959
960  session_deps_.host_resolver->set_synchronous_mode(true);
961
962  DeterministicSocketData data(reads, arraysize(reads),
963                               writes, arraysize(writes));
964  data.set_connect_data(connect_data);
965  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
966
967  CreateDeterministicNetworkSession();
968
969  base::WeakPtr<SpdySession> session =
970      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
971
972  GURL url(kDefaultURL);
973  base::WeakPtr<SpdyStream> spdy_stream =
974      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
975                                session, url, LOWEST, BoundNetLog());
976  test::StreamDelegateDoNothing delegate(spdy_stream);
977  spdy_stream->SetDelegate(&delegate);
978
979  scoped_ptr<SpdyHeaderBlock> headers(
980      spdy_util_.ConstructGetHeaderBlock(url.spec()));
981  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
982
983  // Shift time so that a ping will be sent out.
984  g_time_delta = base::TimeDelta::FromSeconds(11);
985
986  data.RunFor(2);
987
988  session->CloseSessionOnError(ERR_ABORTED, "Aborting");
989}
990
991TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
992  const SpdyStreamId kLastStreamId = 0x7fffffff;
993  session_deps_.host_resolver->set_synchronous_mode(true);
994
995  // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
996  // fixed to allow for two stream ID assignments, and three concurrent
997  // streams. Four streams are started, and two are activated. Verify the
998  // session goes away, and that the created (but not activated) and
999  // stalled streams are aborted. Also verify the activated streams complete,
1000  // at which point the session closes.
1001
1002  scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
1003      NULL, 0, false, kLastStreamId - 2, MEDIUM, true));
1004  scoped_ptr<SpdyFrame> req2(
1005      spdy_util_.ConstructSpdyGet(NULL, 0, false, kLastStreamId, MEDIUM, true));
1006
1007  MockWrite writes[] = {
1008      CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
1009  };
1010
1011  scoped_ptr<SpdyFrame> resp1(
1012      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId - 2));
1013  scoped_ptr<SpdyFrame> resp2(
1014      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId));
1015
1016  scoped_ptr<SpdyFrame> body1(
1017      spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
1018  scoped_ptr<SpdyFrame> body2(
1019      spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
1020
1021  MockRead reads[] = {
1022      CreateMockRead(*resp1, 2), CreateMockRead(*resp2, 3),
1023      CreateMockRead(*body1, 4), CreateMockRead(*body2, 5),
1024      MockRead(ASYNC, 0, 6)  // EOF
1025  };
1026
1027  DeterministicSocketData data(
1028      reads, arraysize(reads), writes, arraysize(writes));
1029
1030  MockConnect connect_data(SYNCHRONOUS, OK);
1031  data.set_connect_data(connect_data);
1032  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1033
1034  CreateDeterministicNetworkSession();
1035  base::WeakPtr<SpdySession> session =
1036      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1037
1038  // Fix stream_hi_water_mark_ to allow for two stream activations.
1039  session->stream_hi_water_mark_ = kLastStreamId - 2;
1040  // Fix max_concurrent_streams to allow for three stream creations.
1041  session->max_concurrent_streams_ = 3;
1042
1043  // Create three streams synchronously, and begin a fourth (which is stalled).
1044  GURL url(kDefaultURL);
1045  base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1046      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1047  test::StreamDelegateDoNothing delegate1(stream1);
1048  stream1->SetDelegate(&delegate1);
1049
1050  base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
1051      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1052  test::StreamDelegateDoNothing delegate2(stream2);
1053  stream2->SetDelegate(&delegate2);
1054
1055  base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1056      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1057  test::StreamDelegateDoNothing delegate3(stream3);
1058  stream3->SetDelegate(&delegate3);
1059
1060  SpdyStreamRequest request4;
1061  TestCompletionCallback callback4;
1062  EXPECT_EQ(ERR_IO_PENDING,
1063            request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1064                                  session,
1065                                  url,
1066                                  MEDIUM,
1067                                  BoundNetLog(),
1068                                  callback4.callback()));
1069
1070  // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1071  EXPECT_EQ(0u, session->num_active_streams());
1072  EXPECT_EQ(3u, session->num_created_streams());
1073  EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1074
1075  // Activate stream 1. One ID remains available.
1076  stream1->SendRequestHeaders(
1077      scoped_ptr<SpdyHeaderBlock>(
1078          spdy_util_.ConstructGetHeaderBlock(url.spec())),
1079      NO_MORE_DATA_TO_SEND);
1080  data.RunFor(1);
1081
1082  EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1083  EXPECT_EQ(1u, session->num_active_streams());
1084  EXPECT_EQ(2u, session->num_created_streams());
1085  EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1086
1087  // Activate stream 2. ID space is exhausted.
1088  stream2->SendRequestHeaders(
1089      scoped_ptr<SpdyHeaderBlock>(
1090          spdy_util_.ConstructGetHeaderBlock(url.spec())),
1091      NO_MORE_DATA_TO_SEND);
1092  data.RunFor(1);
1093
1094  // Active streams remain active.
1095  EXPECT_EQ(kLastStreamId, stream2->stream_id());
1096  EXPECT_EQ(2u, session->num_active_streams());
1097
1098  // Session is going away. Created and stalled streams were aborted.
1099  EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session->availability_state_);
1100  EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose());
1101  EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult());
1102  EXPECT_EQ(0u, session->num_created_streams());
1103  EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1104
1105  // Read responses on remaining active streams.
1106  data.RunFor(4);
1107  EXPECT_EQ(OK, delegate1.WaitForClose());
1108  EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1109  EXPECT_EQ(OK, delegate2.WaitForClose());
1110  EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1111
1112  // Session was destroyed.
1113  base::MessageLoop::current()->RunUntilIdle();
1114  EXPECT_FALSE(session.get());
1115}
1116
1117// Verifies that an unstalled pending stream creation racing with a new stream
1118// creation doesn't violate the maximum stream concurrency. Regression test for
1119// crbug.com/373858.
1120TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) {
1121  session_deps_.host_resolver->set_synchronous_mode(true);
1122
1123  MockRead reads[] = {
1124      MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1125  };
1126
1127  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1128
1129  MockConnect connect_data(SYNCHRONOUS, OK);
1130  data.set_connect_data(connect_data);
1131  session_deps_.socket_factory->AddSocketDataProvider(&data);
1132
1133  CreateNetworkSession();
1134  base::WeakPtr<SpdySession> session =
1135      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1136
1137  // Fix max_concurrent_streams to allow for one open stream.
1138  session->max_concurrent_streams_ = 1;
1139
1140  // Create two streams: one synchronously, and one which stalls.
1141  GURL url(kDefaultURL);
1142  base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1143      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1144
1145  SpdyStreamRequest request2;
1146  TestCompletionCallback callback2;
1147  EXPECT_EQ(ERR_IO_PENDING,
1148            request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1149                                  session,
1150                                  url,
1151                                  MEDIUM,
1152                                  BoundNetLog(),
1153                                  callback2.callback()));
1154
1155  EXPECT_EQ(1u, session->num_created_streams());
1156  EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1157
1158  // Cancel the first stream. A callback to unstall the second stream was
1159  // posted. Don't run it yet.
1160  stream1->Cancel();
1161
1162  EXPECT_EQ(0u, session->num_created_streams());
1163  EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1164
1165  // Create a third stream prior to the second stream's callback.
1166  base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1167      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1168
1169  EXPECT_EQ(1u, session->num_created_streams());
1170  EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1171
1172  // NOW run the message loop. The unstalled stream will re-stall itself.
1173  base::MessageLoop::current()->RunUntilIdle();
1174  EXPECT_EQ(1u, session->num_created_streams());
1175  EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1176
1177  // Cancel the third stream and run the message loop. Verify that the second
1178  // stream creation now completes.
1179  stream3->Cancel();
1180  base::MessageLoop::current()->RunUntilIdle();
1181
1182  EXPECT_EQ(1u, session->num_created_streams());
1183  EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1184  EXPECT_EQ(OK, callback2.WaitForResult());
1185}
1186
1187TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
1188  session_deps_.host_resolver->set_synchronous_mode(true);
1189  session_deps_.time_func = TheNearFuture;
1190
1191  scoped_ptr<SpdyFrame> req(
1192      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1193  scoped_ptr<SpdyFrame> rst(
1194      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
1195
1196  scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
1197      NULL, 0, 2, 1, "http://www.google.com/a.dat"));
1198  scoped_ptr<SpdyFrame> push_a_body(
1199      spdy_util_.ConstructSpdyBodyFrame(2, false));
1200  scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
1201      NULL, 0, 4, 1, "http://www.google.com/b.dat"));
1202  MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)};
1203  MockRead reads[] = {
1204      CreateMockRead(*push_a, 1), CreateMockRead(*push_a_body, 2),
1205      CreateMockRead(*push_b, 3), MockRead(ASYNC, 0, 5),  // EOF
1206  };
1207  DeterministicSocketData data(
1208      reads, arraysize(reads), writes, arraysize(writes));
1209
1210  MockConnect connect_data(SYNCHRONOUS, OK);
1211  data.set_connect_data(connect_data);
1212  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1213
1214  CreateDeterministicNetworkSession();
1215  base::WeakPtr<SpdySession> session =
1216      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1217
1218  // Process the principal request, and the first push stream request & body.
1219  GURL url(kDefaultURL);
1220  base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1221      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1222  test::StreamDelegateDoNothing delegate(spdy_stream);
1223  spdy_stream->SetDelegate(&delegate);
1224
1225  scoped_ptr<SpdyHeaderBlock> headers(
1226      spdy_util_.ConstructGetHeaderBlock(url.spec()));
1227  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1228
1229  data.RunFor(3);
1230
1231  // Verify that there is one unclaimed push stream.
1232  EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1233  SpdySession::PushedStreamMap::iterator iter =
1234      session->unclaimed_pushed_streams_.find(
1235          GURL("http://www.google.com/a.dat"));
1236  EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1237
1238  if (session->flow_control_state_ ==
1239      SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1240    // Unclaimed push body consumed bytes from the session window.
1241    EXPECT_EQ(kSpdySessionInitialWindowSize - kUploadDataSize,
1242              session->session_recv_window_size_);
1243    EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
1244  }
1245
1246  // Shift time to expire the push stream. Read the second SYN_STREAM,
1247  // and verify a RST_STREAM was written.
1248  g_time_delta = base::TimeDelta::FromSeconds(301);
1249  data.RunFor(2);
1250
1251  // Verify that the second pushed stream evicted the first pushed stream.
1252  EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1253  iter = session->unclaimed_pushed_streams_.find(
1254      GURL("http://www.google.com/b.dat"));
1255  EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
1256
1257  if (session->flow_control_state_ ==
1258      SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
1259    // Verify that the session window reclaimed the evicted stream body.
1260    EXPECT_EQ(kSpdySessionInitialWindowSize,
1261              session->session_recv_window_size_);
1262    EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
1263  }
1264
1265  // Read and process EOF.
1266  data.RunFor(1);
1267  base::MessageLoop::current()->RunUntilIdle();
1268  EXPECT_TRUE(session == NULL);
1269}
1270
1271TEST_P(SpdySessionTest, FailedPing) {
1272  session_deps_.host_resolver->set_synchronous_mode(true);
1273
1274  MockConnect connect_data(SYNCHRONOUS, OK);
1275  MockRead reads[] = {
1276      MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1277  };
1278  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
1279  scoped_ptr<SpdyFrame> goaway(
1280      spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping."));
1281  MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)};
1282  StaticSocketDataProvider data(
1283      reads, arraysize(reads), writes, arraysize(writes));
1284  data.set_connect_data(connect_data);
1285  session_deps_.socket_factory->AddSocketDataProvider(&data);
1286
1287  CreateNetworkSession();
1288
1289  base::WeakPtr<SpdySession> session =
1290      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1291
1292  base::WeakPtr<SpdyStream> spdy_stream1 =
1293      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1294                                session, test_url_, MEDIUM, BoundNetLog());
1295  ASSERT_TRUE(spdy_stream1.get() != NULL);
1296  test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
1297  spdy_stream1->SetDelegate(&delegate);
1298
1299  session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
1300  session->set_hung_interval(base::TimeDelta::FromSeconds(0));
1301
1302  // Send a PING frame.
1303  session->WritePingFrame(1, false);
1304  EXPECT_LT(0, session->pings_in_flight());
1305  EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1));
1306  EXPECT_TRUE(session->check_ping_status_pending());
1307
1308  // Assert session is not closed.
1309  EXPECT_TRUE(session->IsAvailable());
1310  EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams());
1311  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1312
1313  // We set last time we have received any data in 1 sec less than now.
1314  // CheckPingStatus will trigger timeout because hung interval is zero.
1315  base::TimeTicks now = base::TimeTicks::Now();
1316  session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
1317  session->CheckPingStatus(now);
1318  base::MessageLoop::current()->RunUntilIdle();
1319
1320  EXPECT_TRUE(session == NULL);
1321  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1322  EXPECT_EQ(NULL, spdy_stream1.get());
1323}
1324
1325// Request kInitialMaxConcurrentStreams + 1 streams.  Receive a
1326// settings frame increasing the max concurrent streams by 1.  Make
1327// sure nothing blows up. This is a regression test for
1328// http://crbug.com/57331 .
1329TEST_P(SpdySessionTest, OnSettings) {
1330  session_deps_.host_resolver->set_synchronous_mode(true);
1331
1332  const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1333
1334  SettingsMap new_settings;
1335  const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1336  new_settings[kSpdySettingsIds] =
1337      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1338  scoped_ptr<SpdyFrame> settings_frame(
1339      spdy_util_.ConstructSpdySettings(new_settings));
1340  MockRead reads[] = {
1341    CreateMockRead(*settings_frame, 0),
1342    MockRead(ASYNC, 0, 1),
1343  };
1344
1345  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1346  MockWrite writes[] = {
1347    CreateMockWrite(*settings_ack, 2),
1348  };
1349
1350  DeterministicSocketData data(reads, arraysize(reads),
1351                               writes, arraysize(writes));
1352  MockConnect connect_data(SYNCHRONOUS, OK);
1353  data.set_connect_data(connect_data);
1354  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1355
1356  CreateDeterministicNetworkSession();
1357
1358  base::WeakPtr<SpdySession> session =
1359      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1360
1361  // Create the maximum number of concurrent streams.
1362  for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1363    base::WeakPtr<SpdyStream> spdy_stream =
1364        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1365                                  session, test_url_, MEDIUM, BoundNetLog());
1366    ASSERT_TRUE(spdy_stream != NULL);
1367  }
1368
1369  StreamReleaserCallback stream_releaser;
1370  SpdyStreamRequest request;
1371  ASSERT_EQ(ERR_IO_PENDING,
1372            request.StartRequest(
1373                SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1374                BoundNetLog(),
1375                stream_releaser.MakeCallback(&request)));
1376
1377  data.RunFor(1);
1378
1379  EXPECT_EQ(OK, stream_releaser.WaitForResult());
1380
1381  data.RunFor(1);
1382  if (spdy_util_.spdy_version() >= SPDY4) {
1383    // Allow the SETTINGS+ACK to write, so the session finishes draining.
1384    data.RunFor(1);
1385  }
1386  base::MessageLoop::current()->RunUntilIdle();
1387  EXPECT_TRUE(session == NULL);
1388}
1389
1390// Start with a persisted value for max concurrent streams. Receive a
1391// settings frame increasing the max concurrent streams by 1 and which
1392// also clears the persisted data. Verify that persisted data is
1393// correct.
1394TEST_P(SpdySessionTest, ClearSettings) {
1395  if (spdy_util_.spdy_version() >= SPDY4) {
1396    // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1397    // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4.
1398    return;
1399  }
1400  session_deps_.host_resolver->set_synchronous_mode(true);
1401
1402  SettingsMap new_settings;
1403  const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1404  new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1405      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1406  scoped_ptr<SpdyFrame> settings_frame(
1407      spdy_util_.ConstructSpdySettings(new_settings));
1408  uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1409  test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1410  MockRead reads[] = {
1411    CreateMockRead(*settings_frame, 0),
1412    MockRead(ASYNC, 0, 1),
1413  };
1414
1415  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
1416  MockConnect connect_data(SYNCHRONOUS, OK);
1417  data.set_connect_data(connect_data);
1418  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1419
1420  CreateDeterministicNetworkSession();
1421
1422  // Initialize the SpdySetting with the default.
1423  spdy_session_pool_->http_server_properties()->SetSpdySetting(
1424      test_host_port_pair_,
1425      SETTINGS_MAX_CONCURRENT_STREAMS,
1426      SETTINGS_FLAG_PLEASE_PERSIST,
1427      kInitialMaxConcurrentStreams);
1428
1429  EXPECT_FALSE(
1430      spdy_session_pool_->http_server_properties()->GetSpdySettings(
1431          test_host_port_pair_).empty());
1432
1433  base::WeakPtr<SpdySession> session =
1434      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1435
1436  // Create the maximum number of concurrent streams.
1437  for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1438    base::WeakPtr<SpdyStream> spdy_stream =
1439        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1440                                  session, test_url_, MEDIUM, BoundNetLog());
1441    ASSERT_TRUE(spdy_stream != NULL);
1442  }
1443
1444  StreamReleaserCallback stream_releaser;
1445
1446  SpdyStreamRequest request;
1447  ASSERT_EQ(ERR_IO_PENDING,
1448            request.StartRequest(
1449                SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1450                BoundNetLog(),
1451                stream_releaser.MakeCallback(&request)));
1452
1453  data.RunFor(1);
1454
1455  EXPECT_EQ(OK, stream_releaser.WaitForResult());
1456
1457  // Make sure that persisted data is cleared.
1458  EXPECT_TRUE(
1459      spdy_session_pool_->http_server_properties()->GetSpdySettings(
1460          test_host_port_pair_).empty());
1461
1462  // Make sure session's max_concurrent_streams is correct.
1463  EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1464            session->max_concurrent_streams());
1465
1466  data.RunFor(1);
1467  EXPECT_TRUE(session == NULL);
1468}
1469
1470// Start with max concurrent streams set to 1.  Request two streams.
1471// When the first completes, have the callback close its stream, which
1472// should trigger the second stream creation.  Then cancel that one
1473// immediately.  Don't crash.  This is a regression test for
1474// http://crbug.com/63532 .
1475TEST_P(SpdySessionTest, CancelPendingCreateStream) {
1476  session_deps_.host_resolver->set_synchronous_mode(true);
1477
1478  MockRead reads[] = {
1479    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1480  };
1481
1482  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1483  MockConnect connect_data(SYNCHRONOUS, OK);
1484
1485  data.set_connect_data(connect_data);
1486  session_deps_.socket_factory->AddSocketDataProvider(&data);
1487
1488  CreateNetworkSession();
1489
1490  // Initialize the SpdySetting with 1 max concurrent streams.
1491  spdy_session_pool_->http_server_properties()->SetSpdySetting(
1492      test_host_port_pair_,
1493      SETTINGS_MAX_CONCURRENT_STREAMS,
1494      SETTINGS_FLAG_PLEASE_PERSIST,
1495      1);
1496
1497  base::WeakPtr<SpdySession> session =
1498      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1499
1500  // Leave room for only one more stream to be created.
1501  for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1502    base::WeakPtr<SpdyStream> spdy_stream =
1503        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1504                                  session, test_url_, MEDIUM, BoundNetLog());
1505    ASSERT_TRUE(spdy_stream != NULL);
1506  }
1507
1508  // Create 2 more streams.  First will succeed.  Second will be pending.
1509  base::WeakPtr<SpdyStream> spdy_stream1 =
1510      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1511                                session, test_url_, MEDIUM, BoundNetLog());
1512  ASSERT_TRUE(spdy_stream1.get() != NULL);
1513
1514  // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
1515  // a valgrind error if the callback is invoked when it's not supposed to be.
1516  scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
1517
1518  SpdyStreamRequest request;
1519  ASSERT_EQ(ERR_IO_PENDING,
1520            request.StartRequest(
1521                SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
1522                BoundNetLog(),
1523                callback->callback()));
1524
1525  // Release the first one, this will allow the second to be created.
1526  spdy_stream1->Cancel();
1527  EXPECT_EQ(NULL, spdy_stream1.get());
1528
1529  request.CancelRequest();
1530  callback.reset();
1531
1532  // Should not crash when running the pending callback.
1533  base::MessageLoop::current()->RunUntilIdle();
1534}
1535
1536TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
1537  session_deps_.host_resolver->set_synchronous_mode(true);
1538
1539  MockRead reads[] = {
1540    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1541  };
1542
1543  SettingsMap settings;
1544  const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
1545  const SpdySettingsIds kSpdySettingsIds2 = SETTINGS_INITIAL_WINDOW_SIZE;
1546  const uint32 kInitialRecvWindowSize = 10 * 1024 * 1024;
1547  settings[kSpdySettingsIds1] =
1548      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
1549  if (spdy_util_.spdy_version() >= SPDY3) {
1550    settings[kSpdySettingsIds2] =
1551        SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialRecvWindowSize);
1552  }
1553  MockConnect connect_data(SYNCHRONOUS, OK);
1554  scoped_ptr<SpdyFrame> settings_frame(
1555      spdy_util_.ConstructSpdySettings(settings));
1556  scoped_ptr<SpdyFrame> initial_window_update(
1557      spdy_util_.ConstructSpdyWindowUpdate(
1558          kSessionFlowControlStreamId,
1559          kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
1560  std::vector<MockWrite> writes;
1561  if (GetParam() == kProtoSPDY4) {
1562    writes.push_back(
1563        MockWrite(ASYNC,
1564                  kHttp2ConnectionHeaderPrefix,
1565                  kHttp2ConnectionHeaderPrefixSize));
1566  }
1567  writes.push_back(CreateMockWrite(*settings_frame));
1568  if (GetParam() >= kProtoSPDY31) {
1569    writes.push_back(CreateMockWrite(*initial_window_update));
1570  };
1571
1572  SettingsMap server_settings;
1573  const uint32 initial_max_concurrent_streams = 1;
1574  server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1575      SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1576                            initial_max_concurrent_streams);
1577  scoped_ptr<SpdyFrame> server_settings_frame(
1578      spdy_util_.ConstructSpdySettings(server_settings));
1579  if (GetParam() <= kProtoSPDY31) {
1580    writes.push_back(CreateMockWrite(*server_settings_frame));
1581  }
1582
1583  session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize;
1584
1585  StaticSocketDataProvider data(reads, arraysize(reads),
1586                                vector_as_array(&writes), writes.size());
1587  data.set_connect_data(connect_data);
1588  session_deps_.socket_factory->AddSocketDataProvider(&data);
1589
1590  CreateNetworkSession();
1591
1592  spdy_session_pool_->http_server_properties()->SetSpdySetting(
1593      test_host_port_pair_,
1594      SETTINGS_MAX_CONCURRENT_STREAMS,
1595      SETTINGS_FLAG_PLEASE_PERSIST,
1596      initial_max_concurrent_streams);
1597
1598  SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1599  pool_peer.SetEnableSendingInitialData(true);
1600
1601  base::WeakPtr<SpdySession> session =
1602      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1603
1604  base::MessageLoop::current()->RunUntilIdle();
1605  EXPECT_TRUE(data.at_write_eof());
1606}
1607
1608TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
1609  CreateNetworkSession();
1610
1611  base::WeakPtr<HttpServerProperties> test_http_server_properties =
1612      spdy_session_pool_->http_server_properties();
1613  SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
1614  test_http_server_properties->SetSpdySetting(
1615      test_host_port_pair_,
1616      SETTINGS_MAX_CONCURRENT_STREAMS,
1617      SETTINGS_FLAG_PLEASE_PERSIST,
1618      2);
1619  EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
1620      test_host_port_pair_).size());
1621  spdy_session_pool_->OnIPAddressChanged();
1622  EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
1623      test_host_port_pair_).size());
1624}
1625
1626TEST_P(SpdySessionTest, Initialize) {
1627  CapturingBoundNetLog log;
1628  session_deps_.net_log = log.bound().net_log();
1629  session_deps_.host_resolver->set_synchronous_mode(true);
1630
1631  MockConnect connect_data(SYNCHRONOUS, OK);
1632  MockRead reads[] = {
1633    MockRead(ASYNC, 0, 0)  // EOF
1634  };
1635
1636  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1637  data.set_connect_data(connect_data);
1638  session_deps_.socket_factory->AddSocketDataProvider(&data);
1639
1640  CreateNetworkSession();
1641
1642  base::WeakPtr<SpdySession> session =
1643      CreateInsecureSpdySession(http_session_, key_, log.bound());
1644  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1645
1646  // Flush the read completion task.
1647  base::MessageLoop::current()->RunUntilIdle();
1648
1649  net::CapturingNetLog::CapturedEntryList entries;
1650  log.GetEntries(&entries);
1651  EXPECT_LT(0u, entries.size());
1652
1653  // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly.
1654  int pos = net::ExpectLogContainsSomewhere(
1655      entries, 0,
1656      net::NetLog::TYPE_SPDY_SESSION_INITIALIZED,
1657      net::NetLog::PHASE_NONE);
1658  EXPECT_LT(0, pos);
1659
1660  CapturingNetLog::CapturedEntry entry = entries[pos];
1661  NetLog::Source socket_source;
1662  EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1663                                                  &socket_source));
1664  EXPECT_TRUE(socket_source.IsValid());
1665  EXPECT_NE(log.bound().source().id, socket_source.id);
1666}
1667
1668TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
1669  session_deps_.host_resolver->set_synchronous_mode(true);
1670
1671  MockConnect connect_data(SYNCHRONOUS, OK);
1672  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
1673  MockRead reads[] = {
1674    CreateMockRead(*goaway),
1675    MockRead(SYNCHRONOUS, 0, 0)  // EOF
1676  };
1677
1678  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1679  data.set_connect_data(connect_data);
1680  session_deps_.socket_factory->AddSocketDataProvider(&data);
1681
1682  CreateNetworkSession();
1683
1684  CapturingBoundNetLog log;
1685  base::WeakPtr<SpdySession> session =
1686      CreateInsecureSpdySession(http_session_, key_, log.bound());
1687  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1688
1689  // Flush the read completion task.
1690  base::MessageLoop::current()->RunUntilIdle();
1691
1692  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1693  EXPECT_TRUE(session == NULL);
1694
1695  // Check that the NetLog was filled reasonably.
1696  net::CapturingNetLog::CapturedEntryList entries;
1697  log.GetEntries(&entries);
1698  EXPECT_LT(0u, entries.size());
1699
1700  // Check that we logged SPDY_SESSION_CLOSE correctly.
1701  int pos = net::ExpectLogContainsSomewhere(
1702      entries, 0,
1703      net::NetLog::TYPE_SPDY_SESSION_CLOSE,
1704      net::NetLog::PHASE_NONE);
1705
1706  if (pos < static_cast<int>(entries.size())) {
1707    CapturingNetLog::CapturedEntry entry = entries[pos];
1708    int error_code = 0;
1709    ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1710    EXPECT_EQ(OK, error_code);
1711  } else {
1712    ADD_FAILURE();
1713  }
1714}
1715
1716TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1717  session_deps_.host_resolver->set_synchronous_mode(true);
1718
1719  MockConnect connect_data(SYNCHRONOUS, OK);
1720  MockRead reads[] = {
1721      MockRead(SYNCHRONOUS, 0, 0)  // EOF
1722  };
1723
1724  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1725  data.set_connect_data(connect_data);
1726  session_deps_.socket_factory->AddSocketDataProvider(&data);
1727
1728  CreateNetworkSession();
1729
1730  CapturingBoundNetLog log;
1731  base::WeakPtr<SpdySession> session =
1732      CreateInsecureSpdySession(http_session_, key_, log.bound());
1733  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1734
1735  // Flush the read completion task.
1736  base::MessageLoop::current()->RunUntilIdle();
1737
1738  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1739  EXPECT_TRUE(session == NULL);
1740
1741  // Check that the NetLog was filled reasonably.
1742  net::CapturingNetLog::CapturedEntryList entries;
1743  log.GetEntries(&entries);
1744  EXPECT_LT(0u, entries.size());
1745
1746  // Check that we logged SPDY_SESSION_CLOSE correctly.
1747  int pos =
1748      net::ExpectLogContainsSomewhere(entries,
1749                                      0,
1750                                      net::NetLog::TYPE_SPDY_SESSION_CLOSE,
1751                                      net::NetLog::PHASE_NONE);
1752
1753  if (pos < static_cast<int>(entries.size())) {
1754    CapturingNetLog::CapturedEntry entry = entries[pos];
1755    int error_code = 0;
1756    ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1757    EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1758  } else {
1759    ADD_FAILURE();
1760  }
1761}
1762
1763TEST_P(SpdySessionTest, SynCompressionHistograms) {
1764  session_deps_.enable_compression = true;
1765
1766  scoped_ptr<SpdyFrame> req(
1767      spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, MEDIUM, true));
1768  MockWrite writes[] = {
1769    CreateMockWrite(*req, 0),
1770  };
1771  MockRead reads[] = {
1772    MockRead(ASYNC, 0, 1)  // EOF
1773  };
1774  DeterministicSocketData data(reads, arraysize(reads),
1775                               writes, arraysize(writes));
1776  MockConnect connect_data(SYNCHRONOUS, OK);
1777  data.set_connect_data(connect_data);
1778  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1779
1780  CreateDeterministicNetworkSession();
1781  base::WeakPtr<SpdySession> session =
1782      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1783
1784  GURL url(kDefaultURL);
1785  base::WeakPtr<SpdyStream> spdy_stream =
1786      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1787                                session, url, MEDIUM, BoundNetLog());
1788  test::StreamDelegateDoNothing delegate(spdy_stream);
1789  spdy_stream->SetDelegate(&delegate);
1790
1791  scoped_ptr<SpdyHeaderBlock> headers(
1792      spdy_util_.ConstructGetHeaderBlock(url.spec()));
1793  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1794  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1795
1796  // Write request headers & capture resulting histogram update.
1797  base::HistogramTester histogram_tester;
1798
1799  data.RunFor(1);
1800  // Regression test of compression performance under the request fixture.
1801  switch (spdy_util_.spdy_version()) {
1802    case SPDY2:
1803      histogram_tester.ExpectBucketCount(
1804          "Net.SpdySynStreamCompressionPercentage", 0, 1);
1805      break;
1806    case SPDY3:
1807      histogram_tester.ExpectBucketCount(
1808          "Net.SpdySynStreamCompressionPercentage", 30, 1);
1809      break;
1810    case SPDY4:
1811      histogram_tester.ExpectBucketCount(
1812          "Net.SpdySynStreamCompressionPercentage", 82, 1);
1813      break;
1814    case SPDY5:
1815      histogram_tester.ExpectBucketCount(
1816          "Net.SpdySynStreamCompressionPercentage", 82, 1);
1817      break;
1818    default:
1819      NOTREACHED();
1820  }
1821
1822  // Read and process EOF.
1823  data.RunFor(1);
1824  base::MessageLoop::current()->RunUntilIdle();
1825  EXPECT_TRUE(session == NULL);
1826}
1827
1828// Queue up a low-priority SYN_STREAM followed by a high-priority
1829// one. The high priority one should still send first and receive
1830// first.
1831TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
1832  // Construct the request.
1833  MockConnect connect_data(SYNCHRONOUS, OK);
1834  scoped_ptr<SpdyFrame> req_highest(
1835      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true));
1836  scoped_ptr<SpdyFrame> req_lowest(
1837      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1838  MockWrite writes[] = {
1839    CreateMockWrite(*req_highest, 0),
1840    CreateMockWrite(*req_lowest, 1),
1841  };
1842
1843  scoped_ptr<SpdyFrame> resp_highest(
1844      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1845  scoped_ptr<SpdyFrame> body_highest(
1846      spdy_util_.ConstructSpdyBodyFrame(1, true));
1847  scoped_ptr<SpdyFrame> resp_lowest(
1848      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1849  scoped_ptr<SpdyFrame> body_lowest(
1850      spdy_util_.ConstructSpdyBodyFrame(3, true));
1851  MockRead reads[] = {
1852    CreateMockRead(*resp_highest, 2),
1853    CreateMockRead(*body_highest, 3),
1854    CreateMockRead(*resp_lowest, 4),
1855    CreateMockRead(*body_lowest, 5),
1856    MockRead(ASYNC, 0, 6)  // EOF
1857  };
1858
1859  session_deps_.host_resolver->set_synchronous_mode(true);
1860
1861  DeterministicSocketData data(reads, arraysize(reads),
1862                               writes, arraysize(writes));
1863  data.set_connect_data(connect_data);
1864  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1865
1866  CreateDeterministicNetworkSession();
1867
1868  base::WeakPtr<SpdySession> session =
1869      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1870
1871  GURL url(kDefaultURL);
1872
1873  base::WeakPtr<SpdyStream> spdy_stream_lowest =
1874      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1875                                session, url, LOWEST, BoundNetLog());
1876  ASSERT_TRUE(spdy_stream_lowest);
1877  EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1878  test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1879  spdy_stream_lowest->SetDelegate(&delegate_lowest);
1880
1881  base::WeakPtr<SpdyStream> spdy_stream_highest =
1882      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1883                                session, url, HIGHEST, BoundNetLog());
1884  ASSERT_TRUE(spdy_stream_highest);
1885  EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1886  test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1887  spdy_stream_highest->SetDelegate(&delegate_highest);
1888
1889  // Queue the lower priority one first.
1890
1891  scoped_ptr<SpdyHeaderBlock> headers_lowest(
1892      spdy_util_.ConstructGetHeaderBlock(url.spec()));
1893  spdy_stream_lowest->SendRequestHeaders(
1894      headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1895  EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
1896
1897  scoped_ptr<SpdyHeaderBlock> headers_highest(
1898      spdy_util_.ConstructGetHeaderBlock(url.spec()));
1899  spdy_stream_highest->SendRequestHeaders(
1900      headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1901  EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
1902
1903  data.RunFor(7);
1904
1905  EXPECT_FALSE(spdy_stream_lowest);
1906  EXPECT_FALSE(spdy_stream_highest);
1907  EXPECT_EQ(3u, delegate_lowest.stream_id());
1908  EXPECT_EQ(1u, delegate_highest.stream_id());
1909}
1910
1911TEST_P(SpdySessionTest, CancelStream) {
1912  MockConnect connect_data(SYNCHRONOUS, OK);
1913  // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1914  // Request 2, at LOWEST priority, will be a full request and will be id 1.
1915  scoped_ptr<SpdyFrame> req2(
1916      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1917  MockWrite writes[] = {
1918    CreateMockWrite(*req2, 0),
1919  };
1920
1921  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1922  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
1923  MockRead reads[] = {
1924    CreateMockRead(*resp2, 1),
1925    CreateMockRead(*body2, 2),
1926    MockRead(ASYNC, 0, 3)  // EOF
1927  };
1928
1929  session_deps_.host_resolver->set_synchronous_mode(true);
1930
1931  DeterministicSocketData data(reads, arraysize(reads),
1932                               writes, arraysize(writes));
1933  data.set_connect_data(connect_data);
1934  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1935
1936  CreateDeterministicNetworkSession();
1937
1938  base::WeakPtr<SpdySession> session =
1939      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1940
1941  GURL url1(kDefaultURL);
1942  base::WeakPtr<SpdyStream> spdy_stream1 =
1943      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1944                                session, url1, HIGHEST, BoundNetLog());
1945  ASSERT_TRUE(spdy_stream1.get() != NULL);
1946  EXPECT_EQ(0u, spdy_stream1->stream_id());
1947  test::StreamDelegateDoNothing delegate1(spdy_stream1);
1948  spdy_stream1->SetDelegate(&delegate1);
1949
1950  GURL url2(kDefaultURL);
1951  base::WeakPtr<SpdyStream> spdy_stream2 =
1952      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1953                                session, url2, LOWEST, BoundNetLog());
1954  ASSERT_TRUE(spdy_stream2.get() != NULL);
1955  EXPECT_EQ(0u, spdy_stream2->stream_id());
1956  test::StreamDelegateDoNothing delegate2(spdy_stream2);
1957  spdy_stream2->SetDelegate(&delegate2);
1958
1959  scoped_ptr<SpdyHeaderBlock> headers(
1960      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1961  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1962  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1963
1964  scoped_ptr<SpdyHeaderBlock> headers2(
1965      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1966  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1967  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
1968
1969  EXPECT_EQ(0u, spdy_stream1->stream_id());
1970
1971  spdy_stream1->Cancel();
1972  EXPECT_EQ(NULL, spdy_stream1.get());
1973
1974  EXPECT_EQ(0u, delegate1.stream_id());
1975
1976  data.RunFor(1);
1977
1978  EXPECT_EQ(0u, delegate1.stream_id());
1979  EXPECT_EQ(1u, delegate2.stream_id());
1980
1981  spdy_stream2->Cancel();
1982  EXPECT_EQ(NULL, spdy_stream2.get());
1983}
1984
1985// Create two streams that are set to re-close themselves on close,
1986// and then close the session. Nothing should blow up. Also a
1987// regression test for http://crbug.com/139518 .
1988TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
1989  session_deps_.host_resolver->set_synchronous_mode(true);
1990
1991  MockConnect connect_data(SYNCHRONOUS, OK);
1992
1993  // No actual data will be sent.
1994  MockWrite writes[] = {
1995    MockWrite(ASYNC, 0, 1)  // EOF
1996  };
1997
1998  MockRead reads[] = {
1999    MockRead(ASYNC, 0, 0)  // EOF
2000  };
2001  DeterministicSocketData data(reads, arraysize(reads),
2002                               writes, arraysize(writes));
2003  data.set_connect_data(connect_data);
2004  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2005
2006  CreateDeterministicNetworkSession();
2007
2008  base::WeakPtr<SpdySession> session =
2009      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2010
2011  GURL url1(kDefaultURL);
2012  base::WeakPtr<SpdyStream> spdy_stream1 =
2013      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2014                                session, url1, HIGHEST, BoundNetLog());
2015  ASSERT_TRUE(spdy_stream1.get() != NULL);
2016  EXPECT_EQ(0u, spdy_stream1->stream_id());
2017
2018  GURL url2(kDefaultURL);
2019  base::WeakPtr<SpdyStream> spdy_stream2 =
2020      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2021                                session, url2, LOWEST, BoundNetLog());
2022  ASSERT_TRUE(spdy_stream2.get() != NULL);
2023  EXPECT_EQ(0u, spdy_stream2->stream_id());
2024
2025  test::ClosingDelegate delegate1(spdy_stream1);
2026  spdy_stream1->SetDelegate(&delegate1);
2027
2028  test::ClosingDelegate delegate2(spdy_stream2);
2029  spdy_stream2->SetDelegate(&delegate2);
2030
2031  scoped_ptr<SpdyHeaderBlock> headers(
2032      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2033  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2034  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2035
2036  scoped_ptr<SpdyHeaderBlock> headers2(
2037      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2038  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2039  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2040
2041  // Ensure that the streams have not yet been activated and assigned an id.
2042  EXPECT_EQ(0u, spdy_stream1->stream_id());
2043  EXPECT_EQ(0u, spdy_stream2->stream_id());
2044
2045  // Ensure we don't crash while closing the session.
2046  session->CloseSessionOnError(ERR_ABORTED, std::string());
2047
2048  EXPECT_EQ(NULL, spdy_stream1.get());
2049  EXPECT_EQ(NULL, spdy_stream2.get());
2050
2051  EXPECT_TRUE(delegate1.StreamIsClosed());
2052  EXPECT_TRUE(delegate2.StreamIsClosed());
2053
2054  base::MessageLoop::current()->RunUntilIdle();
2055  EXPECT_TRUE(session == NULL);
2056}
2057
2058// Create two streams that are set to close each other on close, and
2059// then close the session. Nothing should blow up.
2060TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
2061  session_deps_.host_resolver->set_synchronous_mode(true);
2062
2063  MockConnect connect_data(SYNCHRONOUS, OK);
2064
2065  // No actual data will be sent.
2066  MockWrite writes[] = {
2067    MockWrite(ASYNC, 0, 1)  // EOF
2068  };
2069
2070  MockRead reads[] = {
2071    MockRead(ASYNC, 0, 0)  // EOF
2072  };
2073  DeterministicSocketData data(reads, arraysize(reads),
2074                               writes, arraysize(writes));
2075  data.set_connect_data(connect_data);
2076  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2077
2078  CreateDeterministicNetworkSession();
2079
2080  base::WeakPtr<SpdySession> session =
2081      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2082
2083  GURL url1(kDefaultURL);
2084  base::WeakPtr<SpdyStream> spdy_stream1 =
2085      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2086                                session, url1, HIGHEST, BoundNetLog());
2087  ASSERT_TRUE(spdy_stream1.get() != NULL);
2088  EXPECT_EQ(0u, spdy_stream1->stream_id());
2089
2090  GURL url2(kDefaultURL);
2091  base::WeakPtr<SpdyStream> spdy_stream2 =
2092      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2093                                session, url2, LOWEST, BoundNetLog());
2094  ASSERT_TRUE(spdy_stream2.get() != NULL);
2095  EXPECT_EQ(0u, spdy_stream2->stream_id());
2096
2097  // Make |spdy_stream1| close |spdy_stream2|.
2098  test::ClosingDelegate delegate1(spdy_stream2);
2099  spdy_stream1->SetDelegate(&delegate1);
2100
2101  // Make |spdy_stream2| close |spdy_stream1|.
2102  test::ClosingDelegate delegate2(spdy_stream1);
2103  spdy_stream2->SetDelegate(&delegate2);
2104
2105  scoped_ptr<SpdyHeaderBlock> headers(
2106      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2107  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2108  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2109
2110  scoped_ptr<SpdyHeaderBlock> headers2(
2111      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2112  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2113  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2114
2115  // Ensure that the streams have not yet been activated and assigned an id.
2116  EXPECT_EQ(0u, spdy_stream1->stream_id());
2117  EXPECT_EQ(0u, spdy_stream2->stream_id());
2118
2119  // Ensure we don't crash while closing the session.
2120  session->CloseSessionOnError(ERR_ABORTED, std::string());
2121
2122  EXPECT_EQ(NULL, spdy_stream1.get());
2123  EXPECT_EQ(NULL, spdy_stream2.get());
2124
2125  EXPECT_TRUE(delegate1.StreamIsClosed());
2126  EXPECT_TRUE(delegate2.StreamIsClosed());
2127
2128  base::MessageLoop::current()->RunUntilIdle();
2129  EXPECT_TRUE(session == NULL);
2130}
2131
2132// Create two streams that are set to re-close themselves on close,
2133// activate them, and then close the session. Nothing should blow up.
2134TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
2135  session_deps_.host_resolver->set_synchronous_mode(true);
2136
2137  MockConnect connect_data(SYNCHRONOUS, OK);
2138
2139  scoped_ptr<SpdyFrame> req1(
2140      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2141  scoped_ptr<SpdyFrame> req2(
2142      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2143  MockWrite writes[] = {
2144    CreateMockWrite(*req1, 0),
2145    CreateMockWrite(*req2, 1),
2146  };
2147
2148  MockRead reads[] = {
2149    MockRead(ASYNC, 0, 2)  // EOF
2150  };
2151
2152  DeterministicSocketData data(reads, arraysize(reads),
2153                               writes, arraysize(writes));
2154  data.set_connect_data(connect_data);
2155  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2156
2157  CreateDeterministicNetworkSession();
2158
2159  base::WeakPtr<SpdySession> session =
2160      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2161
2162  GURL url1(kDefaultURL);
2163  base::WeakPtr<SpdyStream> spdy_stream1 =
2164      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2165                                session, url1, MEDIUM, BoundNetLog());
2166  ASSERT_TRUE(spdy_stream1.get() != NULL);
2167  EXPECT_EQ(0u, spdy_stream1->stream_id());
2168
2169  GURL url2(kDefaultURL);
2170  base::WeakPtr<SpdyStream> spdy_stream2 =
2171      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2172                                session, url2, MEDIUM, BoundNetLog());
2173  ASSERT_TRUE(spdy_stream2.get() != NULL);
2174  EXPECT_EQ(0u, spdy_stream2->stream_id());
2175
2176  test::ClosingDelegate delegate1(spdy_stream1);
2177  spdy_stream1->SetDelegate(&delegate1);
2178
2179  test::ClosingDelegate delegate2(spdy_stream2);
2180  spdy_stream2->SetDelegate(&delegate2);
2181
2182  scoped_ptr<SpdyHeaderBlock> headers(
2183      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2184  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2185  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2186
2187  scoped_ptr<SpdyHeaderBlock> headers2(
2188      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2189  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2190  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2191
2192  // Ensure that the streams have not yet been activated and assigned an id.
2193  EXPECT_EQ(0u, spdy_stream1->stream_id());
2194  EXPECT_EQ(0u, spdy_stream2->stream_id());
2195
2196  data.RunFor(2);
2197
2198  EXPECT_EQ(1u, spdy_stream1->stream_id());
2199  EXPECT_EQ(3u, spdy_stream2->stream_id());
2200
2201  // Ensure we don't crash while closing the session.
2202  session->CloseSessionOnError(ERR_ABORTED, std::string());
2203
2204  EXPECT_EQ(NULL, spdy_stream1.get());
2205  EXPECT_EQ(NULL, spdy_stream2.get());
2206
2207  EXPECT_TRUE(delegate1.StreamIsClosed());
2208  EXPECT_TRUE(delegate2.StreamIsClosed());
2209
2210  base::MessageLoop::current()->RunUntilIdle();
2211  EXPECT_TRUE(session == NULL);
2212}
2213
2214// Create two streams that are set to close each other on close,
2215// activate them, and then close the session. Nothing should blow up.
2216TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2217  session_deps_.host_resolver->set_synchronous_mode(true);
2218
2219  MockConnect connect_data(SYNCHRONOUS, OK);
2220
2221  scoped_ptr<SpdyFrame> req1(
2222      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2223  scoped_ptr<SpdyFrame> req2(
2224      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2225  MockWrite writes[] = {
2226    CreateMockWrite(*req1, 0),
2227    CreateMockWrite(*req2, 1),
2228  };
2229
2230  MockRead reads[] = {
2231    MockRead(ASYNC, 0, 2)  // EOF
2232  };
2233
2234  DeterministicSocketData data(reads, arraysize(reads),
2235                               writes, arraysize(writes));
2236  data.set_connect_data(connect_data);
2237  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2238
2239  CreateDeterministicNetworkSession();
2240
2241  base::WeakPtr<SpdySession> session =
2242      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2243
2244  GURL url1(kDefaultURL);
2245  base::WeakPtr<SpdyStream> spdy_stream1 =
2246      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2247                                session, url1, MEDIUM, BoundNetLog());
2248  ASSERT_TRUE(spdy_stream1.get() != NULL);
2249  EXPECT_EQ(0u, spdy_stream1->stream_id());
2250
2251  GURL url2(kDefaultURL);
2252  base::WeakPtr<SpdyStream> spdy_stream2 =
2253      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2254                                session, url2, MEDIUM, BoundNetLog());
2255  ASSERT_TRUE(spdy_stream2.get() != NULL);
2256  EXPECT_EQ(0u, spdy_stream2->stream_id());
2257
2258  // Make |spdy_stream1| close |spdy_stream2|.
2259  test::ClosingDelegate delegate1(spdy_stream2);
2260  spdy_stream1->SetDelegate(&delegate1);
2261
2262  // Make |spdy_stream2| close |spdy_stream1|.
2263  test::ClosingDelegate delegate2(spdy_stream1);
2264  spdy_stream2->SetDelegate(&delegate2);
2265
2266  scoped_ptr<SpdyHeaderBlock> headers(
2267      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2268  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2269  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2270
2271  scoped_ptr<SpdyHeaderBlock> headers2(
2272      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2273  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2274  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
2275
2276  // Ensure that the streams have not yet been activated and assigned an id.
2277  EXPECT_EQ(0u, spdy_stream1->stream_id());
2278  EXPECT_EQ(0u, spdy_stream2->stream_id());
2279
2280  data.RunFor(2);
2281
2282  EXPECT_EQ(1u, spdy_stream1->stream_id());
2283  EXPECT_EQ(3u, spdy_stream2->stream_id());
2284
2285  // Ensure we don't crash while closing the session.
2286  session->CloseSessionOnError(ERR_ABORTED, std::string());
2287
2288  EXPECT_EQ(NULL, spdy_stream1.get());
2289  EXPECT_EQ(NULL, spdy_stream2.get());
2290
2291  EXPECT_TRUE(delegate1.StreamIsClosed());
2292  EXPECT_TRUE(delegate2.StreamIsClosed());
2293
2294  base::MessageLoop::current()->RunUntilIdle();
2295  EXPECT_TRUE(session == NULL);
2296}
2297
2298// Delegate that closes a given session when the stream is closed.
2299class SessionClosingDelegate : public test::StreamDelegateDoNothing {
2300 public:
2301  SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2302                         const base::WeakPtr<SpdySession>& session_to_close)
2303      : StreamDelegateDoNothing(stream),
2304        session_to_close_(session_to_close) {}
2305
2306  virtual ~SessionClosingDelegate() {}
2307
2308  virtual void OnClose(int status) OVERRIDE {
2309    session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2310  }
2311
2312 private:
2313  base::WeakPtr<SpdySession> session_to_close_;
2314};
2315
2316// Close an activated stream that closes its session. Nothing should
2317// blow up. This is a regression test for http://crbug.com/263691 .
2318TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2319  session_deps_.host_resolver->set_synchronous_mode(true);
2320
2321  MockConnect connect_data(SYNCHRONOUS, OK);
2322
2323  scoped_ptr<SpdyFrame> req(
2324      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2325  scoped_ptr<SpdyFrame> rst(
2326      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2327  scoped_ptr<SpdyFrame> goaway(
2328      spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2329  // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2330  // despite being queued second.
2331  MockWrite writes[] = {
2332      CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 1),
2333      CreateMockWrite(*rst, 2),
2334  };
2335
2336  MockRead reads[] = {
2337      MockRead(ASYNC, 0, 3)  // EOF
2338  };
2339  DeterministicSocketData data(reads, arraysize(reads),
2340                               writes, arraysize(writes));
2341  data.set_connect_data(connect_data);
2342  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2343
2344  CreateDeterministicNetworkSession();
2345
2346  base::WeakPtr<SpdySession> session =
2347      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2348
2349  GURL url(kDefaultURL);
2350  base::WeakPtr<SpdyStream> spdy_stream =
2351      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2352                                session, url, MEDIUM, BoundNetLog());
2353  ASSERT_TRUE(spdy_stream.get() != NULL);
2354  EXPECT_EQ(0u, spdy_stream->stream_id());
2355
2356  SessionClosingDelegate delegate(spdy_stream, session);
2357  spdy_stream->SetDelegate(&delegate);
2358
2359  scoped_ptr<SpdyHeaderBlock> headers(
2360      spdy_util_.ConstructGetHeaderBlock(url.spec()));
2361  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2362  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2363
2364  EXPECT_EQ(0u, spdy_stream->stream_id());
2365
2366  data.RunFor(1);
2367
2368  EXPECT_EQ(1u, spdy_stream->stream_id());
2369
2370  // Ensure we don't crash while closing the stream (which closes the
2371  // session).
2372  spdy_stream->Cancel();
2373
2374  EXPECT_EQ(NULL, spdy_stream.get());
2375  EXPECT_TRUE(delegate.StreamIsClosed());
2376
2377  data.RunFor(2);  // Write the RST_STREAM & GOAWAY.
2378  base::MessageLoop::current()->RunUntilIdle();
2379  EXPECT_TRUE(session == NULL);
2380}
2381
2382TEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2383  session_deps_.host_resolver->set_synchronous_mode(true);
2384
2385  MockConnect connect_data(SYNCHRONOUS, OK);
2386
2387  // No actual data will be sent.
2388  MockWrite writes[] = {
2389    MockWrite(ASYNC, 0, 1)  // EOF
2390  };
2391
2392  MockRead reads[] = {
2393    MockRead(ASYNC, 0, 0)  // EOF
2394  };
2395  DeterministicSocketData data(reads, arraysize(reads),
2396                               writes, arraysize(writes));
2397  data.set_connect_data(connect_data);
2398  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2399
2400  // Load a cert that is valid for:
2401  //   www.example.org
2402  //   mail.example.org
2403  //   www.example.com
2404  base::FilePath certs_dir = GetTestCertsDirectory();
2405  scoped_refptr<X509Certificate> test_cert(
2406      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2407  ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2408
2409  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2410  ssl.cert = test_cert;
2411  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2412
2413  CreateDeterministicNetworkSession();
2414
2415  base::WeakPtr<SpdySession> session =
2416      CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2417
2418  EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2419  EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2420  EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
2421  EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2422}
2423
2424TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2425  session_deps_.host_resolver->set_synchronous_mode(true);
2426
2427  MockConnect connect_data(SYNCHRONOUS, OK);
2428
2429  // No actual data will be sent.
2430  MockWrite writes[] = {
2431    MockWrite(ASYNC, 0, 1)  // EOF
2432  };
2433
2434  MockRead reads[] = {
2435    MockRead(ASYNC, 0, 0)  // EOF
2436  };
2437  DeterministicSocketData data(reads, arraysize(reads),
2438                               writes, arraysize(writes));
2439  data.set_connect_data(connect_data);
2440  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2441
2442  // Load a cert that is valid for:
2443  //   www.example.org
2444  //   mail.example.org
2445  //   www.example.com
2446  base::FilePath certs_dir = GetTestCertsDirectory();
2447  scoped_refptr<X509Certificate> test_cert(
2448      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2449  ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
2450
2451  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2452  ssl.channel_id_sent = true;
2453  ssl.cert = test_cert;
2454  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2455
2456  CreateDeterministicNetworkSession();
2457
2458  base::WeakPtr<SpdySession> session =
2459      CreateSecureSpdySession(http_session_, key_, BoundNetLog());
2460
2461  EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2462  EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2463  EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2464  EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
2465}
2466
2467TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2468  // TODO(rtenneti): Define a helper class/methods and move the common code in
2469  // this file.
2470  MockConnect connect_data(SYNCHRONOUS, OK);
2471
2472  SettingsMap new_settings;
2473  const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2474  const uint32 max_concurrent_streams = 1;
2475  new_settings[kSpdySettingsIds1] =
2476      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
2477
2478  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
2479  scoped_ptr<SpdyFrame> req1(
2480      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2481  scoped_ptr<SpdyFrame> req2(
2482      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
2483  scoped_ptr<SpdyFrame> req3(
2484      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
2485  MockWrite writes[] = {
2486    CreateMockWrite(*settings_ack, 1),
2487    CreateMockWrite(*req1, 2),
2488    CreateMockWrite(*req2, 5),
2489    CreateMockWrite(*req3, 8),
2490  };
2491
2492  // Set up the socket so we read a SETTINGS frame that sets max concurrent
2493  // streams to 1.
2494  scoped_ptr<SpdyFrame> settings_frame(
2495      spdy_util_.ConstructSpdySettings(new_settings));
2496
2497  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2498  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2499
2500  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2501  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2502
2503  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
2504  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
2505
2506  MockRead reads[] = {
2507    CreateMockRead(*settings_frame),
2508    CreateMockRead(*resp1, 3),
2509    CreateMockRead(*body1, 4),
2510    CreateMockRead(*resp2, 6),
2511    CreateMockRead(*body2, 7),
2512    CreateMockRead(*resp3, 9),
2513    CreateMockRead(*body3, 10),
2514    MockRead(ASYNC, 0, 11)  // EOF
2515  };
2516
2517  DeterministicSocketData data(reads, arraysize(reads),
2518                               writes, arraysize(writes));
2519  data.set_connect_data(connect_data);
2520  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2521
2522  CreateDeterministicNetworkSession();
2523
2524  base::WeakPtr<SpdySession> session =
2525      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2526
2527  // Read the settings frame.
2528  data.RunFor(1);
2529
2530  GURL url1(kDefaultURL);
2531  base::WeakPtr<SpdyStream> spdy_stream1 =
2532      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2533                                session, url1, LOWEST, BoundNetLog());
2534  ASSERT_TRUE(spdy_stream1.get() != NULL);
2535  EXPECT_EQ(0u, spdy_stream1->stream_id());
2536  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2537  spdy_stream1->SetDelegate(&delegate1);
2538
2539  TestCompletionCallback callback2;
2540  GURL url2(kDefaultURL);
2541  SpdyStreamRequest request2;
2542  ASSERT_EQ(ERR_IO_PENDING,
2543            request2.StartRequest(
2544                SPDY_REQUEST_RESPONSE_STREAM,
2545                session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2546
2547  TestCompletionCallback callback3;
2548  GURL url3(kDefaultURL);
2549  SpdyStreamRequest request3;
2550  ASSERT_EQ(ERR_IO_PENDING,
2551            request3.StartRequest(
2552                SPDY_REQUEST_RESPONSE_STREAM,
2553                session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2554
2555  EXPECT_EQ(0u, session->num_active_streams());
2556  EXPECT_EQ(1u, session->num_created_streams());
2557  EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2558
2559  scoped_ptr<SpdyHeaderBlock> headers(
2560      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2561  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2562  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2563
2564  // Run until 1st stream is activated and then closed.
2565  EXPECT_EQ(0u, delegate1.stream_id());
2566  data.RunFor(4);
2567  EXPECT_EQ(NULL, spdy_stream1.get());
2568  EXPECT_EQ(1u, delegate1.stream_id());
2569
2570  EXPECT_EQ(0u, session->num_active_streams());
2571  EXPECT_EQ(0u, session->num_created_streams());
2572  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2573
2574  // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2575  // create the 2nd stream.
2576  base::MessageLoop::current()->RunUntilIdle();
2577
2578  EXPECT_EQ(0u, session->num_active_streams());
2579  EXPECT_EQ(1u, session->num_created_streams());
2580  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2581
2582  base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2583  test::StreamDelegateDoNothing delegate2(stream2);
2584  stream2->SetDelegate(&delegate2);
2585  scoped_ptr<SpdyHeaderBlock> headers2(
2586      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2587  stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2588  EXPECT_TRUE(stream2->HasUrlFromHeaders());
2589
2590  // Run until 2nd stream is activated and then closed.
2591  EXPECT_EQ(0u, delegate2.stream_id());
2592  data.RunFor(3);
2593  EXPECT_EQ(NULL, stream2.get());
2594  EXPECT_EQ(3u, delegate2.stream_id());
2595
2596  EXPECT_EQ(0u, session->num_active_streams());
2597  EXPECT_EQ(0u, session->num_created_streams());
2598  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2599
2600  // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2601  // create the 3rd stream.
2602  base::MessageLoop::current()->RunUntilIdle();
2603
2604  EXPECT_EQ(0u, session->num_active_streams());
2605  EXPECT_EQ(1u, session->num_created_streams());
2606  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2607
2608  base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2609  test::StreamDelegateDoNothing delegate3(stream3);
2610  stream3->SetDelegate(&delegate3);
2611  scoped_ptr<SpdyHeaderBlock> headers3(
2612      spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2613  stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2614  EXPECT_TRUE(stream3->HasUrlFromHeaders());
2615
2616  // Run until 2nd stream is activated and then closed.
2617  EXPECT_EQ(0u, delegate3.stream_id());
2618  data.RunFor(3);
2619  EXPECT_EQ(NULL, stream3.get());
2620  EXPECT_EQ(5u, delegate3.stream_id());
2621
2622  EXPECT_EQ(0u, session->num_active_streams());
2623  EXPECT_EQ(0u, session->num_created_streams());
2624  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2625
2626  data.RunFor(1);
2627}
2628
2629TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2630  session_deps_.host_resolver->set_synchronous_mode(true);
2631
2632  MockRead reads[] = {
2633    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2634  };
2635
2636  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2637  MockConnect connect_data(SYNCHRONOUS, OK);
2638
2639  data.set_connect_data(connect_data);
2640  session_deps_.socket_factory->AddSocketDataProvider(&data);
2641
2642  CreateNetworkSession();
2643
2644  base::WeakPtr<SpdySession> session =
2645      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2646
2647  // Leave room for only one more stream to be created.
2648  for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2649    base::WeakPtr<SpdyStream> spdy_stream =
2650        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2651                                  session, test_url_, MEDIUM, BoundNetLog());
2652    ASSERT_TRUE(spdy_stream != NULL);
2653  }
2654
2655  GURL url1(kDefaultURL);
2656  base::WeakPtr<SpdyStream> spdy_stream1 =
2657      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2658                                session, url1, LOWEST, BoundNetLog());
2659  ASSERT_TRUE(spdy_stream1.get() != NULL);
2660  EXPECT_EQ(0u, spdy_stream1->stream_id());
2661
2662  TestCompletionCallback callback2;
2663  GURL url2(kDefaultURL);
2664  SpdyStreamRequest request2;
2665  ASSERT_EQ(ERR_IO_PENDING,
2666            request2.StartRequest(
2667                SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2668                callback2.callback()));
2669
2670  TestCompletionCallback callback3;
2671  GURL url3(kDefaultURL);
2672  SpdyStreamRequest request3;
2673  ASSERT_EQ(ERR_IO_PENDING,
2674            request3.StartRequest(
2675                SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2676                callback3.callback()));
2677
2678  EXPECT_EQ(0u, session->num_active_streams());
2679  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2680  EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2681
2682  // Cancel the first stream; this will allow the second stream to be created.
2683  EXPECT_TRUE(spdy_stream1.get() != NULL);
2684  spdy_stream1->Cancel();
2685  EXPECT_EQ(NULL, spdy_stream1.get());
2686
2687  EXPECT_EQ(OK, callback2.WaitForResult());
2688  EXPECT_EQ(0u, session->num_active_streams());
2689  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2690  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2691
2692  // Cancel the second stream; this will allow the third stream to be created.
2693  base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2694  spdy_stream2->Cancel();
2695  EXPECT_EQ(NULL, spdy_stream2.get());
2696
2697  EXPECT_EQ(OK, callback3.WaitForResult());
2698  EXPECT_EQ(0u, session->num_active_streams());
2699  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2700  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2701
2702  // Cancel the third stream.
2703  base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2704  spdy_stream3->Cancel();
2705  EXPECT_EQ(NULL, spdy_stream3.get());
2706  EXPECT_EQ(0u, session->num_active_streams());
2707  EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
2708  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2709}
2710
2711// Test that SpdySession::DoReadLoop reads data from the socket
2712// without yielding.  This test makes 32k - 1 bytes of data available
2713// on the socket for reading. It then verifies that it has read all
2714// the available data without yielding.
2715TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2716  MockConnect connect_data(SYNCHRONOUS, OK);
2717  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2718
2719  scoped_ptr<SpdyFrame> req1(
2720      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2721  MockWrite writes[] = {
2722    CreateMockWrite(*req1, 0),
2723  };
2724
2725  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2726  // (-spdy_data_frame_size).
2727  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2728  const int kPayloadSize =
2729      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2730  TestDataStream test_stream;
2731  scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2732  char* payload_data = payload->data();
2733  test_stream.GetBytes(payload_data, kPayloadSize);
2734
2735  scoped_ptr<SpdyFrame> partial_data_frame(
2736      framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2737  scoped_ptr<SpdyFrame> finish_data_frame(
2738      framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2739
2740  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2741
2742  // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2743  // bytes.
2744  MockRead reads[] = {
2745    CreateMockRead(*resp1, 1),
2746    CreateMockRead(*partial_data_frame, 2),
2747    CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2748    CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2749    CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2750    MockRead(ASYNC, 0, 6)  // EOF
2751  };
2752
2753  // Create SpdySession and SpdyStream and send the request.
2754  DeterministicSocketData data(reads, arraysize(reads),
2755                               writes, arraysize(writes));
2756  data.set_connect_data(connect_data);
2757  session_deps_.host_resolver->set_synchronous_mode(true);
2758  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2759
2760  CreateDeterministicNetworkSession();
2761
2762  base::WeakPtr<SpdySession> session =
2763      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2764
2765  GURL url1(kDefaultURL);
2766  base::WeakPtr<SpdyStream> spdy_stream1 =
2767      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2768                                session, url1, MEDIUM, BoundNetLog());
2769  ASSERT_TRUE(spdy_stream1.get() != NULL);
2770  EXPECT_EQ(0u, spdy_stream1->stream_id());
2771  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2772  spdy_stream1->SetDelegate(&delegate1);
2773
2774  scoped_ptr<SpdyHeaderBlock> headers1(
2775      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2776  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2777  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2778
2779  // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2780  // post a task.
2781  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2782
2783  // Run until 1st read.
2784  EXPECT_EQ(0u, delegate1.stream_id());
2785  data.RunFor(2);
2786  EXPECT_EQ(1u, delegate1.stream_id());
2787  EXPECT_EQ(0u, observer.executed_count());
2788
2789  // Read all the data and verify SpdySession::DoReadLoop has not
2790  // posted a task.
2791  data.RunFor(4);
2792  EXPECT_EQ(NULL, spdy_stream1.get());
2793
2794  // Verify task observer's executed_count is zero, which indicates DoRead read
2795  // all the available data.
2796  EXPECT_EQ(0u, observer.executed_count());
2797  EXPECT_TRUE(data.at_write_eof());
2798  EXPECT_TRUE(data.at_read_eof());
2799}
2800
2801// Test that SpdySession::DoReadLoop yields while reading the
2802// data. This test makes 32k + 1 bytes of data available on the socket
2803// for reading. It then verifies that DoRead has yielded even though
2804// there is data available for it to read (i.e, socket()->Read didn't
2805// return ERR_IO_PENDING during socket reads).
2806TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
2807  MockConnect connect_data(SYNCHRONOUS, OK);
2808  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2809
2810  scoped_ptr<SpdyFrame> req1(
2811      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2812  MockWrite writes[] = {
2813    CreateMockWrite(*req1, 0),
2814  };
2815
2816  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2817  // (-spdy_data_frame_size).
2818  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2819  const int kPayloadSize =
2820      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2821  TestDataStream test_stream;
2822  scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2823  char* payload_data = payload->data();
2824  test_stream.GetBytes(payload_data, kPayloadSize);
2825
2826  scoped_ptr<SpdyFrame> partial_data_frame(
2827      framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2828  scoped_ptr<SpdyFrame> finish_data_frame(
2829      framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
2830
2831  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2832
2833  // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
2834  MockRead reads[] = {
2835    CreateMockRead(*resp1, 1),
2836    CreateMockRead(*partial_data_frame, 2),
2837    CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2838    CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2839    CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
2840    CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
2841    MockRead(ASYNC, 0, 7)  // EOF
2842  };
2843
2844  // Create SpdySession and SpdyStream and send the request.
2845  DeterministicSocketData data(reads, arraysize(reads),
2846                               writes, arraysize(writes));
2847  data.set_connect_data(connect_data);
2848  session_deps_.host_resolver->set_synchronous_mode(true);
2849  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2850
2851  CreateDeterministicNetworkSession();
2852
2853  base::WeakPtr<SpdySession> session =
2854      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2855
2856  GURL url1(kDefaultURL);
2857  base::WeakPtr<SpdyStream> spdy_stream1 =
2858      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2859                                session, url1, MEDIUM, BoundNetLog());
2860  ASSERT_TRUE(spdy_stream1.get() != NULL);
2861  EXPECT_EQ(0u, spdy_stream1->stream_id());
2862  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2863  spdy_stream1->SetDelegate(&delegate1);
2864
2865  scoped_ptr<SpdyHeaderBlock> headers1(
2866      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2867  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2868  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2869
2870  // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2871  // task.
2872  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2873
2874  // Run until 1st read.
2875  EXPECT_EQ(0u, delegate1.stream_id());
2876  data.RunFor(2);
2877  EXPECT_EQ(1u, delegate1.stream_id());
2878  EXPECT_EQ(0u, observer.executed_count());
2879
2880  // Read all the data and verify SpdySession::DoReadLoop has posted a
2881  // task.
2882  data.RunFor(6);
2883  EXPECT_EQ(NULL, spdy_stream1.get());
2884
2885  // Verify task observer's executed_count is 1, which indicates DoRead has
2886  // posted only one task and thus yielded though there is data available for it
2887  // to read.
2888  EXPECT_EQ(1u, observer.executed_count());
2889  EXPECT_TRUE(data.at_write_eof());
2890  EXPECT_TRUE(data.at_read_eof());
2891}
2892
2893// Test that SpdySession::DoReadLoop() tests interactions of yielding
2894// + async, by doing the following MockReads.
2895//
2896// MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
2897// ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
2898//
2899// The above reads 26K synchronously. Since that is less that 32K, we
2900// will attempt to read again. However, that DoRead() will return
2901// ERR_IO_PENDING (because of async read), so DoReadLoop() will
2902// yield. When we come back, DoRead() will read the results from the
2903// async read, and rest of the data synchronously.
2904TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
2905  MockConnect connect_data(SYNCHRONOUS, OK);
2906  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2907
2908  scoped_ptr<SpdyFrame> req1(
2909      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2910  MockWrite writes[] = {
2911    CreateMockWrite(*req1, 0),
2912  };
2913
2914  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2915  // (-spdy_data_frame_size).
2916  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2917  TestDataStream test_stream;
2918  const int kEightKPayloadSize =
2919      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2920  scoped_refptr<net::IOBuffer> eightk_payload(
2921      new net::IOBuffer(kEightKPayloadSize));
2922  char* eightk_payload_data = eightk_payload->data();
2923  test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
2924
2925  // Build buffer of 2k size.
2926  TestDataStream test_stream2;
2927  const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
2928  scoped_refptr<net::IOBuffer> twok_payload(
2929      new net::IOBuffer(kTwoKPayloadSize));
2930  char* twok_payload_data = twok_payload->data();
2931  test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
2932
2933  scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
2934      1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
2935  scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
2936      1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
2937  scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
2938      1, "h", 1, DATA_FLAG_FIN));
2939
2940  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2941
2942  MockRead reads[] = {
2943    CreateMockRead(*resp1, 1),
2944    CreateMockRead(*eightk_data_frame, 2),
2945    CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
2946    CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2947    CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
2948    CreateMockRead(*eightk_data_frame, 6, ASYNC),
2949    CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
2950    CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2951    CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
2952    CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
2953    CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
2954    MockRead(ASYNC, 0, 12)  // EOF
2955  };
2956
2957  // Create SpdySession and SpdyStream and send the request.
2958  DeterministicSocketData data(reads, arraysize(reads),
2959                               writes, arraysize(writes));
2960  data.set_connect_data(connect_data);
2961  session_deps_.host_resolver->set_synchronous_mode(true);
2962  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2963
2964  CreateDeterministicNetworkSession();
2965
2966  base::WeakPtr<SpdySession> session =
2967      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2968
2969  GURL url1(kDefaultURL);
2970  base::WeakPtr<SpdyStream> spdy_stream1 =
2971      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2972                                session, url1, MEDIUM, BoundNetLog());
2973  ASSERT_TRUE(spdy_stream1.get() != NULL);
2974  EXPECT_EQ(0u, spdy_stream1->stream_id());
2975  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2976  spdy_stream1->SetDelegate(&delegate1);
2977
2978  scoped_ptr<SpdyHeaderBlock> headers1(
2979      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2980  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2981  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2982
2983  // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2984  // posting of tasks.
2985  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2986
2987  // Run until 1st read.
2988  EXPECT_EQ(0u, delegate1.stream_id());
2989  data.RunFor(2);
2990  EXPECT_EQ(1u, delegate1.stream_id());
2991  EXPECT_EQ(0u, observer.executed_count());
2992
2993  // Read all the data and verify SpdySession::DoReadLoop has posted a
2994  // task.
2995  data.RunFor(12);
2996  EXPECT_EQ(NULL, spdy_stream1.get());
2997
2998  // Verify task observer's executed_count is 1, which indicates DoRead has
2999  // posted only one task and thus yielded though there is data available for
3000  // it to read.
3001  EXPECT_EQ(1u, observer.executed_count());
3002  EXPECT_TRUE(data.at_write_eof());
3003  EXPECT_TRUE(data.at_read_eof());
3004}
3005
3006// Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
3007// nothing blows up.
3008TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
3009  MockConnect connect_data(SYNCHRONOUS, OK);
3010  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3011
3012  scoped_ptr<SpdyFrame> req1(
3013      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3014  MockWrite writes[] = {
3015    CreateMockWrite(*req1, 0),
3016  };
3017
3018  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3019  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
3020  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
3021
3022  MockRead reads[] = {
3023    CreateMockRead(*resp1, 1),
3024    CreateMockRead(*body1, 2),
3025    CreateMockRead(*goaway, 3),
3026  };
3027
3028  // Create SpdySession and SpdyStream and send the request.
3029  DeterministicSocketData data(reads, arraysize(reads),
3030                               writes, arraysize(writes));
3031  data.set_connect_data(connect_data);
3032  session_deps_.host_resolver->set_synchronous_mode(true);
3033  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3034
3035  CreateDeterministicNetworkSession();
3036
3037  base::WeakPtr<SpdySession> session =
3038      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3039
3040  GURL url1(kDefaultURL);
3041  base::WeakPtr<SpdyStream> spdy_stream1 =
3042      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3043                                session, url1, MEDIUM, BoundNetLog());
3044  test::StreamDelegateDoNothing delegate1(spdy_stream1);
3045  spdy_stream1->SetDelegate(&delegate1);
3046  ASSERT_TRUE(spdy_stream1.get() != NULL);
3047  EXPECT_EQ(0u, spdy_stream1->stream_id());
3048
3049  scoped_ptr<SpdyHeaderBlock> headers1(
3050      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3051  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
3052  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3053
3054  // Run until 1st read.
3055  EXPECT_EQ(0u, spdy_stream1->stream_id());
3056  data.RunFor(1);
3057  EXPECT_EQ(1u, spdy_stream1->stream_id());
3058
3059  // Run until GoAway.
3060  data.RunFor(3);
3061  EXPECT_EQ(NULL, spdy_stream1.get());
3062  EXPECT_TRUE(data.at_write_eof());
3063  EXPECT_TRUE(data.at_read_eof());
3064  EXPECT_TRUE(session == NULL);
3065}
3066
3067// Within this framework, a SpdySession should be initialized with
3068// flow control disabled for protocol version 2, with flow control
3069// enabled only for streams for protocol version 3, and with flow
3070// control enabled for streams and sessions for higher versions.
3071TEST_P(SpdySessionTest, ProtocolNegotiation) {
3072  session_deps_.host_resolver->set_synchronous_mode(true);
3073
3074  MockConnect connect_data(SYNCHRONOUS, OK);
3075  MockRead reads[] = {
3076    MockRead(SYNCHRONOUS, 0, 0)  // EOF
3077  };
3078  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3079  data.set_connect_data(connect_data);
3080  session_deps_.socket_factory->AddSocketDataProvider(&data);
3081
3082  CreateNetworkSession();
3083  base::WeakPtr<SpdySession> session =
3084      CreateFakeSpdySession(spdy_session_pool_, key_);
3085
3086  EXPECT_EQ(spdy_util_.spdy_version(),
3087            session->buffered_spdy_framer_->protocol_version());
3088  if (GetParam() == kProtoDeprecatedSPDY2) {
3089    EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state());
3090    EXPECT_EQ(0, session->session_send_window_size_);
3091    EXPECT_EQ(0, session->session_recv_window_size_);
3092  } else if (GetParam() == kProtoSPDY3) {
3093    EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
3094    EXPECT_EQ(0, session->session_send_window_size_);
3095    EXPECT_EQ(0, session->session_recv_window_size_);
3096  } else {
3097    EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3098              session->flow_control_state());
3099    EXPECT_EQ(kSpdySessionInitialWindowSize,
3100              session->session_send_window_size_);
3101    EXPECT_EQ(kSpdySessionInitialWindowSize,
3102              session->session_recv_window_size_);
3103  }
3104  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3105}
3106
3107// Tests the case of a non-SPDY request closing an idle SPDY session when no
3108// pointers to the idle session are currently held.
3109TEST_P(SpdySessionTest, CloseOneIdleConnection) {
3110  ClientSocketPoolManager::set_max_sockets_per_group(
3111      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3112  ClientSocketPoolManager::set_max_sockets_per_pool(
3113      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3114
3115  MockConnect connect_data(SYNCHRONOUS, OK);
3116  MockRead reads[] = {
3117    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
3118  };
3119  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3120  data.set_connect_data(connect_data);
3121  session_deps_.socket_factory->AddSocketDataProvider(&data);
3122  session_deps_.socket_factory->AddSocketDataProvider(&data);
3123
3124  CreateNetworkSession();
3125
3126  TransportClientSocketPool* pool =
3127      http_session_->GetTransportSocketPool(
3128          HttpNetworkSession::NORMAL_SOCKET_POOL);
3129
3130  // Create an idle SPDY session.
3131  SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3132                      PRIVACY_MODE_DISABLED);
3133  base::WeakPtr<SpdySession> session1 =
3134      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3135  EXPECT_FALSE(pool->IsStalled());
3136
3137  // Trying to create a new connection should cause the pool to be stalled, and
3138  // post a task asynchronously to try and close the session.
3139  TestCompletionCallback callback2;
3140  HostPortPair host_port2("2.com", 80);
3141  scoped_refptr<TransportSocketParams> params2(
3142      new TransportSocketParams(
3143          host_port2, false, false, OnHostResolutionCallback(),
3144          TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3145  scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3146  EXPECT_EQ(ERR_IO_PENDING,
3147            connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3148                              callback2.callback(), pool, BoundNetLog()));
3149  EXPECT_TRUE(pool->IsStalled());
3150
3151  // The socket pool should close the connection asynchronously and establish a
3152  // new connection.
3153  EXPECT_EQ(OK, callback2.WaitForResult());
3154  EXPECT_FALSE(pool->IsStalled());
3155  EXPECT_TRUE(session1 == NULL);
3156}
3157
3158// Tests the case of a non-SPDY request closing an idle SPDY session when no
3159// pointers to the idle session are currently held, in the case the SPDY session
3160// has an alias.
3161TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
3162  ClientSocketPoolManager::set_max_sockets_per_group(
3163      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3164  ClientSocketPoolManager::set_max_sockets_per_pool(
3165      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3166
3167  MockConnect connect_data(SYNCHRONOUS, OK);
3168  MockRead reads[] = {
3169    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
3170  };
3171  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3172  data.set_connect_data(connect_data);
3173  session_deps_.socket_factory->AddSocketDataProvider(&data);
3174  session_deps_.socket_factory->AddSocketDataProvider(&data);
3175
3176  session_deps_.host_resolver->set_synchronous_mode(true);
3177  session_deps_.host_resolver->rules()->AddIPLiteralRule(
3178      "1.com", "192.168.0.2", std::string());
3179  session_deps_.host_resolver->rules()->AddIPLiteralRule(
3180      "2.com", "192.168.0.2", std::string());
3181  // Not strictly needed.
3182  session_deps_.host_resolver->rules()->AddIPLiteralRule(
3183      "3.com", "192.168.0.3", std::string());
3184
3185  CreateNetworkSession();
3186
3187  TransportClientSocketPool* pool =
3188      http_session_->GetTransportSocketPool(
3189          HttpNetworkSession::NORMAL_SOCKET_POOL);
3190
3191  // Create an idle SPDY session.
3192  SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3193                      PRIVACY_MODE_DISABLED);
3194  base::WeakPtr<SpdySession> session1 =
3195      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3196  EXPECT_FALSE(pool->IsStalled());
3197
3198  // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3199  SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3200                      PRIVACY_MODE_DISABLED);
3201  HostResolver::RequestInfo info(key2.host_port_pair());
3202  AddressList addresses;
3203  // Pre-populate the DNS cache, since a synchronous resolution is required in
3204  // order to create the alias.
3205  session_deps_.host_resolver->Resolve(info,
3206                                       DEFAULT_PRIORITY,
3207                                       &addresses,
3208                                       CompletionCallback(),
3209                                       NULL,
3210                                       BoundNetLog());
3211  // Get a session for |key2|, which should return the session created earlier.
3212  base::WeakPtr<SpdySession> session2 =
3213      spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3214  ASSERT_EQ(session1.get(), session2.get());
3215  EXPECT_FALSE(pool->IsStalled());
3216
3217  // Trying to create a new connection should cause the pool to be stalled, and
3218  // post a task asynchronously to try and close the session.
3219  TestCompletionCallback callback3;
3220  HostPortPair host_port3("3.com", 80);
3221  scoped_refptr<TransportSocketParams> params3(
3222      new TransportSocketParams(
3223          host_port3, false, false, OnHostResolutionCallback(),
3224          TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3225  scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3226  EXPECT_EQ(ERR_IO_PENDING,
3227            connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3228                              callback3.callback(), pool, BoundNetLog()));
3229  EXPECT_TRUE(pool->IsStalled());
3230
3231  // The socket pool should close the connection asynchronously and establish a
3232  // new connection.
3233  EXPECT_EQ(OK, callback3.WaitForResult());
3234  EXPECT_FALSE(pool->IsStalled());
3235  EXPECT_TRUE(session1 == NULL);
3236  EXPECT_TRUE(session2 == NULL);
3237}
3238
3239// Tests that when a SPDY session becomes idle, it closes itself if there is
3240// a lower layer pool stalled on the per-pool socket limit.
3241TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3242  ClientSocketPoolManager::set_max_sockets_per_group(
3243      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3244  ClientSocketPoolManager::set_max_sockets_per_pool(
3245      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3246
3247  MockConnect connect_data(SYNCHRONOUS, OK);
3248  MockRead reads[] = {
3249    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
3250  };
3251  scoped_ptr<SpdyFrame> req1(
3252      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3253  scoped_ptr<SpdyFrame> cancel1(
3254      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3255  MockWrite writes[] = {
3256    CreateMockWrite(*req1, 1),
3257    CreateMockWrite(*cancel1, 1),
3258  };
3259  StaticSocketDataProvider data(reads, arraysize(reads),
3260                                writes, arraysize(writes));
3261  data.set_connect_data(connect_data);
3262  session_deps_.socket_factory->AddSocketDataProvider(&data);
3263
3264  MockRead http_reads[] = {
3265    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
3266  };
3267  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
3268                                     NULL, 0);
3269  http_data.set_connect_data(connect_data);
3270  session_deps_.socket_factory->AddSocketDataProvider(&http_data);
3271
3272
3273  CreateNetworkSession();
3274
3275  TransportClientSocketPool* pool =
3276      http_session_->GetTransportSocketPool(
3277          HttpNetworkSession::NORMAL_SOCKET_POOL);
3278
3279  // Create a SPDY session.
3280  GURL url1(kDefaultURL);
3281  SpdySessionKey key1(HostPortPair(url1.host(), 80),
3282                      ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3283  base::WeakPtr<SpdySession> session1 =
3284      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3285  EXPECT_FALSE(pool->IsStalled());
3286
3287  // Create a stream using the session, and send a request.
3288
3289  TestCompletionCallback callback1;
3290  base::WeakPtr<SpdyStream> spdy_stream1 =
3291      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3292                                session1, url1, DEFAULT_PRIORITY,
3293                                BoundNetLog());
3294  ASSERT_TRUE(spdy_stream1.get());
3295  test::StreamDelegateDoNothing delegate1(spdy_stream1);
3296  spdy_stream1->SetDelegate(&delegate1);
3297
3298  scoped_ptr<SpdyHeaderBlock> headers1(
3299      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3300  EXPECT_EQ(ERR_IO_PENDING,
3301            spdy_stream1->SendRequestHeaders(
3302                headers1.Pass(), NO_MORE_DATA_TO_SEND));
3303  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3304
3305  base::MessageLoop::current()->RunUntilIdle();
3306
3307  // Trying to create a new connection should cause the pool to be stalled, and
3308  // post a task asynchronously to try and close the session.
3309  TestCompletionCallback callback2;
3310  HostPortPair host_port2("2.com", 80);
3311  scoped_refptr<TransportSocketParams> params2(
3312      new TransportSocketParams(
3313          host_port2, false, false, OnHostResolutionCallback(),
3314          TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
3315  scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3316  EXPECT_EQ(ERR_IO_PENDING,
3317            connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3318                              callback2.callback(), pool, BoundNetLog()));
3319  EXPECT_TRUE(pool->IsStalled());
3320
3321  // Running the message loop should cause the socket pool to ask the SPDY
3322  // session to close an idle socket, but since the socket is in use, nothing
3323  // happens.
3324  base::RunLoop().RunUntilIdle();
3325  EXPECT_TRUE(pool->IsStalled());
3326  EXPECT_FALSE(callback2.have_result());
3327
3328  // Cancelling the request should result in the session's socket being
3329  // closed, since the pool is stalled.
3330  ASSERT_TRUE(spdy_stream1.get());
3331  spdy_stream1->Cancel();
3332  base::RunLoop().RunUntilIdle();
3333  ASSERT_FALSE(pool->IsStalled());
3334  EXPECT_EQ(OK, callback2.WaitForResult());
3335}
3336
3337// Verify that SpdySessionKey and therefore SpdySession is different when
3338// privacy mode is enabled or disabled.
3339TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3340  CreateDeterministicNetworkSession();
3341
3342  HostPortPair host_port_pair("www.google.com", 443);
3343  SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3344                                     PRIVACY_MODE_ENABLED);
3345  SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3346                                     PRIVACY_MODE_DISABLED);
3347
3348  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3349  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3350
3351  // Add SpdySession with PrivacyMode Enabled to the pool.
3352  base::WeakPtr<SpdySession> session_privacy_enabled =
3353      CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3354
3355  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3356  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3357
3358  // Add SpdySession with PrivacyMode Disabled to the pool.
3359  base::WeakPtr<SpdySession> session_privacy_disabled =
3360      CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3361
3362  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3363  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3364
3365  session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
3366  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3367  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3368
3369  session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
3370  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
3371  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3372}
3373
3374// Delegate that creates another stream when its stream is closed.
3375class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3376 public:
3377  StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3378                         const base::WeakPtr<SpdySession>& session)
3379      : StreamDelegateDoNothing(stream),
3380        session_(session) {}
3381
3382  virtual ~StreamCreatingDelegate() {}
3383
3384  virtual void OnClose(int status) OVERRIDE {
3385    GURL url(kDefaultURL);
3386    ignore_result(
3387        CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3388                                  session_, url, MEDIUM, BoundNetLog()));
3389  }
3390
3391 private:
3392  const base::WeakPtr<SpdySession> session_;
3393};
3394
3395// Create another stream in response to a stream being reset. Nothing
3396// should blow up. This is a regression test for
3397// http://crbug.com/263690 .
3398TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3399  session_deps_.host_resolver->set_synchronous_mode(true);
3400
3401  MockConnect connect_data(SYNCHRONOUS, OK);
3402
3403  scoped_ptr<SpdyFrame> req(
3404      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3405  MockWrite writes[] = {
3406    CreateMockWrite(*req, 0),
3407  };
3408
3409  scoped_ptr<SpdyFrame> rst(
3410      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3411  MockRead reads[] = {
3412    CreateMockRead(*rst, 1),
3413    MockRead(ASYNC, 0, 2)  // EOF
3414  };
3415  DeterministicSocketData data(reads, arraysize(reads),
3416                               writes, arraysize(writes));
3417  data.set_connect_data(connect_data);
3418  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3419
3420  CreateDeterministicNetworkSession();
3421
3422  base::WeakPtr<SpdySession> session =
3423      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3424
3425  GURL url(kDefaultURL);
3426  base::WeakPtr<SpdyStream> spdy_stream =
3427      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3428                                session, url, MEDIUM, BoundNetLog());
3429  ASSERT_TRUE(spdy_stream.get() != NULL);
3430  EXPECT_EQ(0u, spdy_stream->stream_id());
3431
3432  StreamCreatingDelegate delegate(spdy_stream, session);
3433  spdy_stream->SetDelegate(&delegate);
3434
3435  scoped_ptr<SpdyHeaderBlock> headers(
3436      spdy_util_.ConstructGetHeaderBlock(url.spec()));
3437  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3438  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3439
3440  EXPECT_EQ(0u, spdy_stream->stream_id());
3441
3442  data.RunFor(1);
3443
3444  EXPECT_EQ(1u, spdy_stream->stream_id());
3445
3446  // Cause the stream to be reset, which should cause another stream
3447  // to be created.
3448  data.RunFor(1);
3449
3450  EXPECT_EQ(NULL, spdy_stream.get());
3451  EXPECT_TRUE(delegate.StreamIsClosed());
3452  EXPECT_EQ(0u, session->num_active_streams());
3453  EXPECT_EQ(1u, session->num_created_streams());
3454}
3455
3456// The tests below are only for SPDY/3 and above.
3457
3458TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3459  if (GetParam() < kProtoSPDY3)
3460    return;
3461
3462  // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3463  // gets sent.
3464  SettingsMap new_settings;
3465  int32 window_size = 1;
3466  new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3467      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3468
3469  // Set up the socket so we read a SETTINGS frame that sets
3470  // INITIAL_WINDOW_SIZE.
3471  MockConnect connect_data(SYNCHRONOUS, OK);
3472  scoped_ptr<SpdyFrame> settings_frame(
3473      spdy_util_.ConstructSpdySettings(new_settings));
3474  MockRead reads[] = {
3475    CreateMockRead(*settings_frame, 0),
3476    MockRead(ASYNC, 0, 1)  // EOF
3477  };
3478
3479  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3480  MockWrite writes[] = {
3481    CreateMockWrite(*settings_ack, 2),
3482  };
3483
3484  session_deps_.host_resolver->set_synchronous_mode(true);
3485
3486  DeterministicSocketData data(reads, arraysize(reads),
3487                               writes, arraysize(writes));
3488  data.set_connect_data(connect_data);
3489  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3490
3491  CreateDeterministicNetworkSession();
3492
3493  base::WeakPtr<SpdySession> session =
3494      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3495  base::WeakPtr<SpdyStream> spdy_stream1 =
3496      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3497                                session, test_url_, MEDIUM, BoundNetLog());
3498  ASSERT_TRUE(spdy_stream1.get() != NULL);
3499  TestCompletionCallback callback1;
3500  EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3501
3502  data.RunFor(1);  // Process the SETTINGS frame, but not the EOF
3503  base::MessageLoop::current()->RunUntilIdle();
3504  EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3505  EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3506
3507  // Release the first one, this will allow the second to be created.
3508  spdy_stream1->Cancel();
3509  EXPECT_EQ(NULL, spdy_stream1.get());
3510
3511  base::WeakPtr<SpdyStream> spdy_stream2 =
3512      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3513                                session, test_url_, MEDIUM, BoundNetLog());
3514  ASSERT_TRUE(spdy_stream2.get() != NULL);
3515  EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3516  spdy_stream2->Cancel();
3517  EXPECT_EQ(NULL, spdy_stream2.get());
3518}
3519
3520// The tests below are only for SPDY/3.1 and above.
3521
3522// SpdySession::{Increase,Decrease}RecvWindowSize should properly
3523// adjust the session receive window size for SPDY 3.1 and higher. In
3524// addition, SpdySession::IncreaseRecvWindowSize should trigger
3525// sending a WINDOW_UPDATE frame for a large enough delta.
3526TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3527  if (GetParam() < kProtoSPDY31)
3528    return;
3529
3530  session_deps_.host_resolver->set_synchronous_mode(true);
3531
3532  const int32 delta_window_size = 100;
3533
3534  MockConnect connect_data(SYNCHRONOUS, OK);
3535  MockRead reads[] = {
3536    MockRead(ASYNC, 0, 1)  // EOF
3537  };
3538  scoped_ptr<SpdyFrame> window_update(
3539      spdy_util_.ConstructSpdyWindowUpdate(
3540          kSessionFlowControlStreamId,
3541          kSpdySessionInitialWindowSize + delta_window_size));
3542  MockWrite writes[] = {
3543    CreateMockWrite(*window_update, 0),
3544  };
3545  DeterministicSocketData data(reads, arraysize(reads),
3546                               writes, arraysize(writes));
3547  data.set_connect_data(connect_data);
3548  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3549
3550  CreateDeterministicNetworkSession();
3551  base::WeakPtr<SpdySession> session =
3552      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3553  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3554            session->flow_control_state());
3555
3556  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3557  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3558
3559  session->IncreaseRecvWindowSize(delta_window_size);
3560  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3561            session->session_recv_window_size_);
3562  EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3563
3564  // Should trigger sending a WINDOW_UPDATE frame.
3565  session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize);
3566  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size +
3567            kSpdySessionInitialWindowSize,
3568            session->session_recv_window_size_);
3569  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3570
3571  data.RunFor(1);
3572
3573  // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3574  session->in_io_loop_ = true;
3575  session->DecreaseRecvWindowSize(
3576      kSpdySessionInitialWindowSize + delta_window_size +
3577      kSpdySessionInitialWindowSize);
3578  session->in_io_loop_ = false;
3579  EXPECT_EQ(0, session->session_recv_window_size_);
3580  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3581}
3582
3583// SpdySession::{Increase,Decrease}SendWindowSize should properly
3584// adjust the session send window size when the "enable_spdy_31" flag
3585// is set.
3586TEST_P(SpdySessionTest, AdjustSendWindowSize) {
3587  if (GetParam() < kProtoSPDY31)
3588    return;
3589
3590  session_deps_.host_resolver->set_synchronous_mode(true);
3591
3592  MockConnect connect_data(SYNCHRONOUS, OK);
3593  MockRead reads[] = {
3594    MockRead(SYNCHRONOUS, 0, 0)  // EOF
3595  };
3596  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3597  data.set_connect_data(connect_data);
3598  session_deps_.socket_factory->AddSocketDataProvider(&data);
3599
3600  CreateNetworkSession();
3601  base::WeakPtr<SpdySession> session =
3602      CreateFakeSpdySession(spdy_session_pool_, key_);
3603  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3604            session->flow_control_state());
3605
3606  const int32 delta_window_size = 100;
3607
3608  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3609
3610  session->IncreaseSendWindowSize(delta_window_size);
3611  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3612            session->session_send_window_size_);
3613
3614  session->DecreaseSendWindowSize(delta_window_size);
3615  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3616}
3617
3618// Incoming data for an inactive stream should not cause the session
3619// receive window size to decrease, but it should cause the unacked
3620// bytes to increase.
3621TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3622  if (GetParam() < kProtoSPDY31)
3623    return;
3624
3625  session_deps_.host_resolver->set_synchronous_mode(true);
3626
3627  MockConnect connect_data(SYNCHRONOUS, OK);
3628  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3629  MockRead reads[] = {
3630    CreateMockRead(*resp, 0),
3631    MockRead(ASYNC, 0, 1)  // EOF
3632  };
3633  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3634  data.set_connect_data(connect_data);
3635  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3636
3637  CreateDeterministicNetworkSession();
3638  base::WeakPtr<SpdySession> session =
3639      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3640  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3641            session->flow_control_state());
3642
3643  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3644  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3645
3646  data.RunFor(1);
3647
3648  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3649  EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3650
3651  data.RunFor(1);
3652}
3653
3654// A delegate that drops any received data.
3655class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3656 public:
3657  DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3658                           base::StringPiece data)
3659      : StreamDelegateSendImmediate(stream, data) {}
3660
3661  virtual ~DropReceivedDataDelegate() {}
3662
3663  // Drop any received data.
3664  virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) OVERRIDE {}
3665};
3666
3667// Send data back and forth but use a delegate that drops its received
3668// data. The receive window should still increase to its original
3669// value, i.e. we shouldn't "leak" receive window bytes.
3670TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
3671  if (GetParam() < kProtoSPDY31)
3672    return;
3673
3674  const char kStreamUrl[] = "http://www.google.com/";
3675
3676  const int32 msg_data_size = 100;
3677  const std::string msg_data(msg_data_size, 'a');
3678
3679  MockConnect connect_data(SYNCHRONOUS, OK);
3680
3681  scoped_ptr<SpdyFrame> req(
3682      spdy_util_.ConstructSpdyPost(
3683          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3684  scoped_ptr<SpdyFrame> msg(
3685      spdy_util_.ConstructSpdyBodyFrame(
3686          1, msg_data.data(), msg_data_size, false));
3687  MockWrite writes[] = {
3688    CreateMockWrite(*req, 0),
3689    CreateMockWrite(*msg, 2),
3690  };
3691
3692  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3693  scoped_ptr<SpdyFrame> echo(
3694      spdy_util_.ConstructSpdyBodyFrame(
3695          1, msg_data.data(), msg_data_size, false));
3696  scoped_ptr<SpdyFrame> window_update(
3697      spdy_util_.ConstructSpdyWindowUpdate(
3698          kSessionFlowControlStreamId, msg_data_size));
3699  MockRead reads[] = {
3700    CreateMockRead(*resp, 1),
3701    CreateMockRead(*echo, 3),
3702    MockRead(ASYNC, 0, 4)  // EOF
3703  };
3704
3705  // Create SpdySession and SpdyStream and send the request.
3706  DeterministicSocketData data(reads, arraysize(reads),
3707                               writes, arraysize(writes));
3708  data.set_connect_data(connect_data);
3709  session_deps_.host_resolver->set_synchronous_mode(true);
3710  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3711
3712  CreateDeterministicNetworkSession();
3713
3714  base::WeakPtr<SpdySession> session =
3715      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3716
3717  GURL url(kStreamUrl);
3718  base::WeakPtr<SpdyStream> stream =
3719      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3720                                session, url, MEDIUM, BoundNetLog());
3721  ASSERT_TRUE(stream.get() != NULL);
3722  EXPECT_EQ(0u, stream->stream_id());
3723
3724  DropReceivedDataDelegate delegate(stream, msg_data);
3725  stream->SetDelegate(&delegate);
3726
3727  scoped_ptr<SpdyHeaderBlock> headers(
3728      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3729  EXPECT_EQ(ERR_IO_PENDING,
3730            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3731  EXPECT_TRUE(stream->HasUrlFromHeaders());
3732
3733  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3734  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3735
3736  data.RunFor(4);
3737
3738  EXPECT_TRUE(data.at_write_eof());
3739  EXPECT_TRUE(data.at_read_eof());
3740
3741  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3742  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3743
3744  stream->Close();
3745  EXPECT_EQ(NULL, stream.get());
3746
3747  EXPECT_EQ(OK, delegate.WaitForClose());
3748
3749  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3750  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3751}
3752
3753// Send data back and forth but close the stream before its data frame
3754// can be written to the socket. The send window should then increase
3755// to its original value, i.e. we shouldn't "leak" send window bytes.
3756TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
3757  if (GetParam() < kProtoSPDY31)
3758    return;
3759
3760  const char kStreamUrl[] = "http://www.google.com/";
3761
3762  const int32 msg_data_size = 100;
3763  const std::string msg_data(msg_data_size, 'a');
3764
3765  MockConnect connect_data(SYNCHRONOUS, OK);
3766
3767  scoped_ptr<SpdyFrame> req(
3768      spdy_util_.ConstructSpdyPost(
3769          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3770  MockWrite writes[] = {
3771    CreateMockWrite(*req, 0),
3772  };
3773
3774  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3775  MockRead reads[] = {
3776    CreateMockRead(*resp, 1),
3777    MockRead(ASYNC, 0, 2)  // EOF
3778  };
3779
3780  // Create SpdySession and SpdyStream and send the request.
3781  DeterministicSocketData data(reads, arraysize(reads),
3782                               writes, arraysize(writes));
3783  data.set_connect_data(connect_data);
3784  session_deps_.host_resolver->set_synchronous_mode(true);
3785  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3786
3787  CreateDeterministicNetworkSession();
3788
3789  base::WeakPtr<SpdySession> session =
3790      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3791
3792  GURL url(kStreamUrl);
3793  base::WeakPtr<SpdyStream> stream =
3794      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3795                                session, url, MEDIUM, BoundNetLog());
3796  ASSERT_TRUE(stream.get() != NULL);
3797  EXPECT_EQ(0u, stream->stream_id());
3798
3799  test::StreamDelegateSendImmediate delegate(stream, msg_data);
3800  stream->SetDelegate(&delegate);
3801
3802  scoped_ptr<SpdyHeaderBlock> headers(
3803      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3804  EXPECT_EQ(ERR_IO_PENDING,
3805            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3806  EXPECT_TRUE(stream->HasUrlFromHeaders());
3807
3808  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3809
3810  data.RunFor(1);
3811
3812  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3813
3814  data.RunFor(1);
3815
3816  EXPECT_TRUE(data.at_write_eof());
3817  EXPECT_TRUE(data.at_read_eof());
3818
3819  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3820            session->session_send_window_size_);
3821
3822  // Closing the stream should increase the session's send window.
3823  stream->Close();
3824  EXPECT_EQ(NULL, stream.get());
3825
3826  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3827
3828  EXPECT_EQ(OK, delegate.WaitForClose());
3829}
3830
3831// Send data back and forth; the send and receive windows should
3832// change appropriately.
3833TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
3834  if (GetParam() < kProtoSPDY31)
3835    return;
3836
3837  const char kStreamUrl[] = "http://www.google.com/";
3838
3839  const int32 msg_data_size = 100;
3840  const std::string msg_data(msg_data_size, 'a');
3841
3842  MockConnect connect_data(SYNCHRONOUS, OK);
3843
3844  scoped_ptr<SpdyFrame> req(
3845      spdy_util_.ConstructSpdyPost(
3846          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3847  scoped_ptr<SpdyFrame> msg(
3848      spdy_util_.ConstructSpdyBodyFrame(
3849          1, msg_data.data(), msg_data_size, false));
3850  MockWrite writes[] = {
3851    CreateMockWrite(*req, 0),
3852    CreateMockWrite(*msg, 2),
3853  };
3854
3855  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3856  scoped_ptr<SpdyFrame> echo(
3857      spdy_util_.ConstructSpdyBodyFrame(
3858          1, msg_data.data(), msg_data_size, false));
3859  scoped_ptr<SpdyFrame> window_update(
3860      spdy_util_.ConstructSpdyWindowUpdate(
3861          kSessionFlowControlStreamId, msg_data_size));
3862  MockRead reads[] = {
3863    CreateMockRead(*resp, 1),
3864    CreateMockRead(*echo, 3),
3865    CreateMockRead(*window_update, 4),
3866    MockRead(ASYNC, 0, 5)  // EOF
3867  };
3868
3869  // Create SpdySession and SpdyStream and send the request.
3870  DeterministicSocketData data(reads, arraysize(reads),
3871                               writes, arraysize(writes));
3872  data.set_connect_data(connect_data);
3873  session_deps_.host_resolver->set_synchronous_mode(true);
3874  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3875
3876  CreateDeterministicNetworkSession();
3877
3878  base::WeakPtr<SpdySession> session =
3879      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3880
3881  GURL url(kStreamUrl);
3882  base::WeakPtr<SpdyStream> stream =
3883      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3884                                session, url, MEDIUM, BoundNetLog());
3885  ASSERT_TRUE(stream.get() != NULL);
3886  EXPECT_EQ(0u, stream->stream_id());
3887
3888  test::StreamDelegateSendImmediate delegate(stream, msg_data);
3889  stream->SetDelegate(&delegate);
3890
3891  scoped_ptr<SpdyHeaderBlock> headers(
3892      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
3893  EXPECT_EQ(ERR_IO_PENDING,
3894            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3895  EXPECT_TRUE(stream->HasUrlFromHeaders());
3896
3897  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3898  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3899  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3900
3901  data.RunFor(1);
3902
3903  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3904  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3905  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3906
3907  data.RunFor(1);
3908
3909  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3910            session->session_send_window_size_);
3911  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3912  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3913
3914  data.RunFor(1);
3915
3916  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3917            session->session_send_window_size_);
3918  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3919  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3920
3921  data.RunFor(1);
3922
3923  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3924            session->session_send_window_size_);
3925  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3926            session->session_recv_window_size_);
3927  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3928
3929  data.RunFor(1);
3930
3931  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3932  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3933            session->session_recv_window_size_);
3934  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3935
3936  EXPECT_TRUE(data.at_write_eof());
3937  EXPECT_TRUE(data.at_read_eof());
3938
3939  EXPECT_EQ(msg_data, delegate.TakeReceivedData());
3940
3941  // Draining the delegate's read queue should increase the session's
3942  // receive window.
3943  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3944  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3945  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3946
3947  stream->Close();
3948  EXPECT_EQ(NULL, stream.get());
3949
3950  EXPECT_EQ(OK, delegate.WaitForClose());
3951
3952  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3953  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3954  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3955}
3956
3957// Given a stall function and an unstall function, runs a test to make
3958// sure that a stream resumes after unstall.
3959void SpdySessionTest::RunResumeAfterUnstallTest(
3960    const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
3961    const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
3962        unstall_function) {
3963  const char kStreamUrl[] = "http://www.google.com/";
3964  GURL url(kStreamUrl);
3965
3966  session_deps_.host_resolver->set_synchronous_mode(true);
3967
3968  scoped_ptr<SpdyFrame> req(
3969      spdy_util_.ConstructSpdyPost(
3970          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
3971  scoped_ptr<SpdyFrame> body(
3972      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
3973  MockWrite writes[] = {
3974    CreateMockWrite(*req, 0),
3975    CreateMockWrite(*body, 1),
3976  };
3977
3978  scoped_ptr<SpdyFrame> resp(
3979      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3980  scoped_ptr<SpdyFrame> echo(
3981      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
3982  MockRead reads[] = {
3983    CreateMockRead(*resp, 2),
3984    MockRead(ASYNC, 0, 0, 3), // EOF
3985  };
3986
3987  DeterministicSocketData data(reads, arraysize(reads),
3988                               writes, arraysize(writes));
3989  MockConnect connect_data(SYNCHRONOUS, OK);
3990  data.set_connect_data(connect_data);
3991
3992  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3993
3994  CreateDeterministicNetworkSession();
3995  base::WeakPtr<SpdySession> session =
3996      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3997  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3998            session->flow_control_state());
3999
4000  base::WeakPtr<SpdyStream> stream =
4001      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4002                                session, url, LOWEST, BoundNetLog());
4003  ASSERT_TRUE(stream.get() != NULL);
4004
4005  test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
4006  stream->SetDelegate(&delegate);
4007
4008  EXPECT_FALSE(stream->HasUrlFromHeaders());
4009  EXPECT_FALSE(stream->send_stalled_by_flow_control());
4010
4011  scoped_ptr<SpdyHeaderBlock> headers(
4012      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4013  EXPECT_EQ(ERR_IO_PENDING,
4014            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
4015  EXPECT_TRUE(stream->HasUrlFromHeaders());
4016  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
4017
4018  stall_function.Run(session.get(), stream.get());
4019
4020  data.RunFor(1);
4021
4022  EXPECT_TRUE(stream->send_stalled_by_flow_control());
4023
4024  unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
4025
4026  EXPECT_FALSE(stream->send_stalled_by_flow_control());
4027
4028  data.RunFor(3);
4029
4030  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
4031
4032  EXPECT_TRUE(delegate.send_headers_completed());
4033  EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
4034  EXPECT_EQ(std::string(), delegate.TakeReceivedData());
4035  EXPECT_TRUE(data.at_write_eof());
4036}
4037
4038// Run the resume-after-unstall test with all possible stall and
4039// unstall sequences.
4040
4041TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
4042  if (GetParam() < kProtoSPDY31)
4043    return;
4044
4045  RunResumeAfterUnstallTest(
4046      base::Bind(&SpdySessionTest::StallSessionOnly,
4047                 base::Unretained(this)),
4048      base::Bind(&SpdySessionTest::UnstallSessionOnly,
4049                 base::Unretained(this)));
4050}
4051
4052// Equivalent to
4053// SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
4054TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
4055  if (GetParam() < kProtoSPDY31)
4056    return;
4057
4058  RunResumeAfterUnstallTest(
4059      base::Bind(&SpdySessionTest::StallStreamOnly,
4060                 base::Unretained(this)),
4061      base::Bind(&SpdySessionTest::UnstallStreamOnly,
4062                 base::Unretained(this)));
4063}
4064
4065TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
4066  if (GetParam() < kProtoSPDY31)
4067    return;
4068
4069  RunResumeAfterUnstallTest(
4070      base::Bind(&SpdySessionTest::StallSessionStream,
4071                 base::Unretained(this)),
4072      base::Bind(&SpdySessionTest::UnstallSessionStream,
4073                 base::Unretained(this)));
4074}
4075
4076TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
4077  if (GetParam() < kProtoSPDY31)
4078    return;
4079
4080  RunResumeAfterUnstallTest(
4081      base::Bind(&SpdySessionTest::StallStreamSession,
4082                 base::Unretained(this)),
4083      base::Bind(&SpdySessionTest::UnstallSessionStream,
4084                 base::Unretained(this)));
4085}
4086
4087TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
4088  if (GetParam() < kProtoSPDY31)
4089    return;
4090
4091  RunResumeAfterUnstallTest(
4092      base::Bind(&SpdySessionTest::StallStreamSession,
4093                 base::Unretained(this)),
4094      base::Bind(&SpdySessionTest::UnstallStreamSession,
4095                 base::Unretained(this)));
4096}
4097
4098TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
4099  if (GetParam() < kProtoSPDY31)
4100    return;
4101
4102  RunResumeAfterUnstallTest(
4103      base::Bind(&SpdySessionTest::StallSessionStream,
4104                 base::Unretained(this)),
4105      base::Bind(&SpdySessionTest::UnstallStreamSession,
4106                 base::Unretained(this)));
4107}
4108
4109// Cause a stall by reducing the flow control send window to 0. The
4110// streams should resume in priority order when that window is then
4111// increased.
4112TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
4113  if (GetParam() < kProtoSPDY31)
4114    return;
4115
4116  const char kStreamUrl[] = "http://www.google.com/";
4117  GURL url(kStreamUrl);
4118
4119  session_deps_.host_resolver->set_synchronous_mode(true);
4120
4121  scoped_ptr<SpdyFrame> req1(
4122      spdy_util_.ConstructSpdyPost(
4123          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4124  scoped_ptr<SpdyFrame> req2(
4125      spdy_util_.ConstructSpdyPost(
4126          kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
4127  scoped_ptr<SpdyFrame> body1(
4128      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
4129  scoped_ptr<SpdyFrame> body2(
4130      spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4131  MockWrite writes[] = {
4132    CreateMockWrite(*req1, 0),
4133    CreateMockWrite(*req2, 1),
4134    CreateMockWrite(*body2, 2),
4135    CreateMockWrite(*body1, 3),
4136  };
4137
4138  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4139  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4140  MockRead reads[] = {
4141    CreateMockRead(*resp1, 4),
4142    CreateMockRead(*resp2, 5),
4143    MockRead(ASYNC, 0, 0, 6), // EOF
4144  };
4145
4146  DeterministicSocketData data(reads, arraysize(reads),
4147                               writes, arraysize(writes));
4148  MockConnect connect_data(SYNCHRONOUS, OK);
4149  data.set_connect_data(connect_data);
4150
4151  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4152
4153  CreateDeterministicNetworkSession();
4154  base::WeakPtr<SpdySession> session =
4155      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4156  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4157            session->flow_control_state());
4158
4159  base::WeakPtr<SpdyStream> stream1 =
4160      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4161                                session, url, LOWEST, BoundNetLog());
4162  ASSERT_TRUE(stream1.get() != NULL);
4163
4164  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4165  stream1->SetDelegate(&delegate1);
4166
4167  EXPECT_FALSE(stream1->HasUrlFromHeaders());
4168
4169  base::WeakPtr<SpdyStream> stream2 =
4170      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4171                                session, url, MEDIUM, BoundNetLog());
4172  ASSERT_TRUE(stream2.get() != NULL);
4173
4174  test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4175  stream2->SetDelegate(&delegate2);
4176
4177  EXPECT_FALSE(stream2->HasUrlFromHeaders());
4178
4179  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4180  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4181
4182  StallSessionSend(session.get());
4183
4184  scoped_ptr<SpdyHeaderBlock> headers1(
4185      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4186  EXPECT_EQ(ERR_IO_PENDING,
4187            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4188  EXPECT_TRUE(stream1->HasUrlFromHeaders());
4189  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4190
4191  data.RunFor(1);
4192  EXPECT_EQ(1u, stream1->stream_id());
4193  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4194
4195  scoped_ptr<SpdyHeaderBlock> headers2(
4196      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4197  EXPECT_EQ(ERR_IO_PENDING,
4198            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4199  EXPECT_TRUE(stream2->HasUrlFromHeaders());
4200  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4201
4202  data.RunFor(1);
4203  EXPECT_EQ(3u, stream2->stream_id());
4204  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4205
4206  // This should unstall only stream2.
4207  UnstallSessionSend(session.get(), kBodyDataSize);
4208
4209  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4210  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4211
4212  data.RunFor(1);
4213
4214  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4215  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4216
4217  // This should then unstall stream1.
4218  UnstallSessionSend(session.get(), kBodyDataSize);
4219
4220  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4221  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4222
4223  data.RunFor(4);
4224
4225  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4226  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4227
4228  EXPECT_TRUE(delegate1.send_headers_completed());
4229  EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4230  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4231
4232  EXPECT_TRUE(delegate2.send_headers_completed());
4233  EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4234  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4235
4236  EXPECT_TRUE(data.at_write_eof());
4237}
4238
4239// Delegate that closes a given stream after sending its body.
4240class StreamClosingDelegate : public test::StreamDelegateWithBody {
4241 public:
4242  StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4243                        base::StringPiece data)
4244      : StreamDelegateWithBody(stream, data) {}
4245
4246  virtual ~StreamClosingDelegate() {}
4247
4248  void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4249    stream_to_close_ = stream_to_close;
4250  }
4251
4252  virtual void OnDataSent() OVERRIDE {
4253    test::StreamDelegateWithBody::OnDataSent();
4254    if (stream_to_close_.get()) {
4255      stream_to_close_->Close();
4256      EXPECT_EQ(NULL, stream_to_close_.get());
4257    }
4258  }
4259
4260 private:
4261  base::WeakPtr<SpdyStream> stream_to_close_;
4262};
4263
4264// Cause a stall by reducing the flow control send window to
4265// 0. Unstalling the session should properly handle deleted streams.
4266TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
4267  if (GetParam() < kProtoSPDY31)
4268    return;
4269
4270  const char kStreamUrl[] = "http://www.google.com/";
4271  GURL url(kStreamUrl);
4272
4273  session_deps_.host_resolver->set_synchronous_mode(true);
4274
4275  scoped_ptr<SpdyFrame> req1(
4276      spdy_util_.ConstructSpdyPost(
4277          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4278  scoped_ptr<SpdyFrame> req2(
4279      spdy_util_.ConstructSpdyPost(
4280          kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4281  scoped_ptr<SpdyFrame> req3(
4282      spdy_util_.ConstructSpdyPost(
4283          kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
4284  scoped_ptr<SpdyFrame> body2(
4285      spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
4286  MockWrite writes[] = {
4287    CreateMockWrite(*req1, 0),
4288    CreateMockWrite(*req2, 1),
4289    CreateMockWrite(*req3, 2),
4290    CreateMockWrite(*body2, 3),
4291  };
4292
4293  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4294  MockRead reads[] = {
4295    CreateMockRead(*resp2, 4),
4296    MockRead(ASYNC, 0, 0, 5), // EOF
4297  };
4298
4299  DeterministicSocketData data(reads, arraysize(reads),
4300                               writes, arraysize(writes));
4301  MockConnect connect_data(SYNCHRONOUS, OK);
4302  data.set_connect_data(connect_data);
4303
4304  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4305
4306  CreateDeterministicNetworkSession();
4307  base::WeakPtr<SpdySession> session =
4308      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4309  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4310            session->flow_control_state());
4311
4312  base::WeakPtr<SpdyStream> stream1 =
4313      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4314                                session, url, LOWEST, BoundNetLog());
4315  ASSERT_TRUE(stream1.get() != NULL);
4316
4317  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4318  stream1->SetDelegate(&delegate1);
4319
4320  EXPECT_FALSE(stream1->HasUrlFromHeaders());
4321
4322  base::WeakPtr<SpdyStream> stream2 =
4323      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4324                                session, url, LOWEST, BoundNetLog());
4325  ASSERT_TRUE(stream2.get() != NULL);
4326
4327  StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
4328  stream2->SetDelegate(&delegate2);
4329
4330  EXPECT_FALSE(stream2->HasUrlFromHeaders());
4331
4332  base::WeakPtr<SpdyStream> stream3 =
4333      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4334                                session, url, LOWEST, BoundNetLog());
4335  ASSERT_TRUE(stream3.get() != NULL);
4336
4337  test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4338  stream3->SetDelegate(&delegate3);
4339
4340  EXPECT_FALSE(stream3->HasUrlFromHeaders());
4341
4342  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4343  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4344  EXPECT_FALSE(stream3->send_stalled_by_flow_control());
4345
4346  StallSessionSend(session.get());
4347
4348  scoped_ptr<SpdyHeaderBlock> headers1(
4349      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4350  EXPECT_EQ(ERR_IO_PENDING,
4351            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4352  EXPECT_TRUE(stream1->HasUrlFromHeaders());
4353  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4354
4355  data.RunFor(1);
4356  EXPECT_EQ(1u, stream1->stream_id());
4357  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4358
4359  scoped_ptr<SpdyHeaderBlock> headers2(
4360      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4361  EXPECT_EQ(ERR_IO_PENDING,
4362            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4363  EXPECT_TRUE(stream2->HasUrlFromHeaders());
4364  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4365
4366  data.RunFor(1);
4367  EXPECT_EQ(3u, stream2->stream_id());
4368  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4369
4370  scoped_ptr<SpdyHeaderBlock> headers3(
4371      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4372  EXPECT_EQ(ERR_IO_PENDING,
4373            stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4374  EXPECT_TRUE(stream3->HasUrlFromHeaders());
4375  EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4376
4377  data.RunFor(1);
4378  EXPECT_EQ(5u, stream3->stream_id());
4379  EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4380
4381  SpdyStreamId stream_id1 = stream1->stream_id();
4382  SpdyStreamId stream_id2 = stream2->stream_id();
4383  SpdyStreamId stream_id3 = stream3->stream_id();
4384
4385  // Close stream1 preemptively.
4386  session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4387  EXPECT_EQ(NULL, stream1.get());
4388
4389  EXPECT_FALSE(session->IsStreamActive(stream_id1));
4390  EXPECT_TRUE(session->IsStreamActive(stream_id2));
4391  EXPECT_TRUE(session->IsStreamActive(stream_id3));
4392
4393  // Unstall stream2, which should then close stream3.
4394  delegate2.set_stream_to_close(stream3);
4395  UnstallSessionSend(session.get(), kBodyDataSize);
4396
4397  data.RunFor(1);
4398  EXPECT_EQ(NULL, stream3.get());
4399
4400  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4401  EXPECT_FALSE(session->IsStreamActive(stream_id1));
4402  EXPECT_TRUE(session->IsStreamActive(stream_id2));
4403  EXPECT_FALSE(session->IsStreamActive(stream_id3));
4404
4405  data.RunFor(2);
4406  EXPECT_EQ(NULL, stream2.get());
4407
4408  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4409  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4410  EXPECT_EQ(OK, delegate3.WaitForClose());
4411
4412  EXPECT_TRUE(delegate1.send_headers_completed());
4413  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4414
4415  EXPECT_TRUE(delegate2.send_headers_completed());
4416  EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4417  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4418
4419  EXPECT_TRUE(delegate3.send_headers_completed());
4420  EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4421
4422  EXPECT_TRUE(data.at_write_eof());
4423}
4424
4425// Cause a stall by reducing the flow control send window to
4426// 0. Unstalling the session should properly handle the session itself
4427// being closed.
4428TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4429  if (GetParam() < kProtoSPDY31)
4430    return;
4431
4432  const char kStreamUrl[] = "http://www.google.com/";
4433  GURL url(kStreamUrl);
4434
4435  session_deps_.host_resolver->set_synchronous_mode(true);
4436
4437  scoped_ptr<SpdyFrame> req1(
4438      spdy_util_.ConstructSpdyPost(
4439          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4440  scoped_ptr<SpdyFrame> req2(
4441      spdy_util_.ConstructSpdyPost(
4442          kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4443  scoped_ptr<SpdyFrame> body1(
4444      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4445  MockWrite writes[] = {
4446    CreateMockWrite(*req1, 0),
4447    CreateMockWrite(*req2, 1),
4448  };
4449
4450  MockRead reads[] = {
4451    MockRead(ASYNC, 0, 0, 2), // EOF
4452  };
4453
4454  DeterministicSocketData data(reads, arraysize(reads),
4455                               writes, arraysize(writes));
4456  MockConnect connect_data(SYNCHRONOUS, OK);
4457  data.set_connect_data(connect_data);
4458
4459  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4460
4461  CreateDeterministicNetworkSession();
4462  base::WeakPtr<SpdySession> session =
4463      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4464  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4465            session->flow_control_state());
4466
4467  base::WeakPtr<SpdyStream> stream1 =
4468      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4469                                session, url, LOWEST, BoundNetLog());
4470  ASSERT_TRUE(stream1.get() != NULL);
4471
4472  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4473  stream1->SetDelegate(&delegate1);
4474
4475  EXPECT_FALSE(stream1->HasUrlFromHeaders());
4476
4477  base::WeakPtr<SpdyStream> stream2 =
4478      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4479                                session, url, LOWEST, BoundNetLog());
4480  ASSERT_TRUE(stream2.get() != NULL);
4481
4482  test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4483  stream2->SetDelegate(&delegate2);
4484
4485  EXPECT_FALSE(stream2->HasUrlFromHeaders());
4486
4487  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4488  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4489
4490  StallSessionSend(session.get());
4491
4492  scoped_ptr<SpdyHeaderBlock> headers1(
4493      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4494  EXPECT_EQ(ERR_IO_PENDING,
4495            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4496  EXPECT_TRUE(stream1->HasUrlFromHeaders());
4497  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4498
4499  data.RunFor(1);
4500  EXPECT_EQ(1u, stream1->stream_id());
4501  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4502
4503  scoped_ptr<SpdyHeaderBlock> headers2(
4504      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4505  EXPECT_EQ(ERR_IO_PENDING,
4506            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4507  EXPECT_TRUE(stream2->HasUrlFromHeaders());
4508  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4509
4510  data.RunFor(1);
4511  EXPECT_EQ(3u, stream2->stream_id());
4512  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
4513
4514  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
4515
4516  // Unstall stream1.
4517  UnstallSessionSend(session.get(), kBodyDataSize);
4518
4519  // Close the session (since we can't do it from within the delegate
4520  // method, since it's in the stream's loop).
4521  session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4522  base::RunLoop().RunUntilIdle();
4523  EXPECT_TRUE(session == NULL);
4524
4525  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4526
4527  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4528  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4529
4530  EXPECT_TRUE(delegate1.send_headers_completed());
4531  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4532
4533  EXPECT_TRUE(delegate2.send_headers_completed());
4534  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4535
4536  EXPECT_TRUE(data.at_write_eof());
4537}
4538
4539TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4540  if (GetParam() < kProtoSPDY31)
4541    return;
4542
4543  MockConnect connect_data(SYNCHRONOUS, OK);
4544
4545  scoped_ptr<SpdyFrame> req(
4546      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4547  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4548      0,
4549      GOAWAY_FLOW_CONTROL_ERROR,
4550      "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4551      "the receive window size of 1"));
4552  MockWrite writes[] = {
4553      CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
4554  };
4555
4556  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4557  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4558  MockRead reads[] = {
4559      CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
4560  };
4561
4562  DeterministicSocketData data(
4563      reads, arraysize(reads), writes, arraysize(writes));
4564  data.set_connect_data(connect_data);
4565  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4566
4567  CreateDeterministicNetworkSession();
4568
4569  base::WeakPtr<SpdySession> session =
4570      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4571
4572  GURL url(kDefaultURL);
4573  base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4574      SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
4575  ASSERT_TRUE(spdy_stream.get() != NULL);
4576  test::StreamDelegateDoNothing delegate(spdy_stream);
4577  spdy_stream->SetDelegate(&delegate);
4578
4579  scoped_ptr<SpdyHeaderBlock> headers(
4580      spdy_util_.ConstructGetHeaderBlock(url.spec()));
4581  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4582
4583  data.RunFor(1);  // Write request.
4584
4585  // Put session on the edge of overflowing it's recv window.
4586  session->session_recv_window_size_ = 1;
4587
4588  // Read response headers & body. Body overflows the session window, and a
4589  // goaway is written.
4590  data.RunFor(3);
4591  base::MessageLoop::current()->RunUntilIdle();
4592
4593  EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4594  EXPECT_TRUE(session == NULL);
4595}
4596
4597TEST_P(SpdySessionTest, SplitHeaders) {
4598  GURL kStreamUrl("http://www.google.com/foo.dat");
4599  SpdyHeaderBlock headers;
4600  spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4601  headers["alpha"] = "beta";
4602
4603  SpdyHeaderBlock request_headers;
4604  SpdyHeaderBlock response_headers;
4605
4606  SplitPushedHeadersToRequestAndResponse(
4607      headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4608
4609  SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4610  std::string alpha_val =
4611      (it == response_headers.end()) ? std::string() : it->second;
4612  EXPECT_EQ("beta", alpha_val);
4613
4614  GURL request_url =
4615      GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4616  EXPECT_EQ(kStreamUrl, request_url);
4617}
4618
4619// Regression. Sorta. Push streams and client streams were sharing a single
4620// limit for a long time.
4621TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
4622  SettingsMap new_settings;
4623  new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4624      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
4625  scoped_ptr<SpdyFrame> settings_frame(
4626      spdy_util_.ConstructSpdySettings(new_settings));
4627  scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
4628      NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4629  MockRead reads[] = {
4630      CreateMockRead(*settings_frame), CreateMockRead(*pushed, 3),
4631      MockRead(ASYNC, 0, 4),
4632  };
4633
4634  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
4635  scoped_ptr<SpdyFrame> req(
4636      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4637  MockWrite writes[] = {
4638      CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
4639  };
4640
4641  DeterministicSocketData data(
4642      reads, arraysize(reads), writes, arraysize(writes));
4643  MockConnect connect_data(SYNCHRONOUS, OK);
4644  data.set_connect_data(connect_data);
4645  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4646
4647  CreateDeterministicNetworkSession();
4648
4649  base::WeakPtr<SpdySession> session =
4650      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4651
4652  // Read the settings frame.
4653  data.RunFor(1);
4654
4655  GURL url1(kDefaultURL);
4656  base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4657      SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4658  ASSERT_TRUE(spdy_stream1.get() != NULL);
4659  EXPECT_EQ(0u, spdy_stream1->stream_id());
4660  test::StreamDelegateDoNothing delegate1(spdy_stream1);
4661  spdy_stream1->SetDelegate(&delegate1);
4662
4663  EXPECT_EQ(0u, session->num_active_streams());
4664  EXPECT_EQ(1u, session->num_created_streams());
4665  EXPECT_EQ(0u, session->num_pushed_streams());
4666  EXPECT_EQ(0u, session->num_active_pushed_streams());
4667
4668  scoped_ptr<SpdyHeaderBlock> headers(
4669      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4670  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4671  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4672
4673  // Run until 1st stream is activated.
4674  EXPECT_EQ(0u, delegate1.stream_id());
4675  data.RunFor(2);
4676  EXPECT_EQ(1u, delegate1.stream_id());
4677  EXPECT_EQ(1u, session->num_active_streams());
4678  EXPECT_EQ(0u, session->num_created_streams());
4679  EXPECT_EQ(0u, session->num_pushed_streams());
4680  EXPECT_EQ(0u, session->num_active_pushed_streams());
4681
4682  // Run until pushed stream is created.
4683  data.RunFor(1);
4684  EXPECT_EQ(2u, session->num_active_streams());
4685  EXPECT_EQ(0u, session->num_created_streams());
4686  EXPECT_EQ(1u, session->num_pushed_streams());
4687  EXPECT_EQ(1u, session->num_active_pushed_streams());
4688
4689  // Second stream should not be stalled, although we have 2 active streams, but
4690  // one of them is push stream and should not be taken into account when we
4691  // create streams on the client.
4692  base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
4693      SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4694  EXPECT_TRUE(spdy_stream2.get() != NULL);
4695  EXPECT_EQ(2u, session->num_active_streams());
4696  EXPECT_EQ(1u, session->num_created_streams());
4697  EXPECT_EQ(1u, session->num_pushed_streams());
4698  EXPECT_EQ(1u, session->num_active_pushed_streams());
4699
4700  // Read EOF.
4701  data.RunFor(1);
4702}
4703
4704TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
4705  scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4706      NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4707  scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
4708      NULL, 0, 4, 1, "http://www.google.com/b.dat"));
4709  MockRead reads[] = {
4710      CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4711      MockRead(ASYNC, 0, 4),
4712  };
4713
4714  scoped_ptr<SpdyFrame> req(
4715      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4716  scoped_ptr<SpdyFrame> rst(
4717      spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4718  MockWrite writes[] = {
4719      CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4720  };
4721
4722  DeterministicSocketData data(
4723      reads, arraysize(reads), writes, arraysize(writes));
4724  MockConnect connect_data(SYNCHRONOUS, OK);
4725  data.set_connect_data(connect_data);
4726  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4727
4728  CreateDeterministicNetworkSession();
4729
4730  base::WeakPtr<SpdySession> session =
4731      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4732  session->set_max_concurrent_pushed_streams(1);
4733
4734  GURL url1(kDefaultURL);
4735  base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4736      SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4737  ASSERT_TRUE(spdy_stream1.get() != NULL);
4738  EXPECT_EQ(0u, spdy_stream1->stream_id());
4739  test::StreamDelegateDoNothing delegate1(spdy_stream1);
4740  spdy_stream1->SetDelegate(&delegate1);
4741
4742  EXPECT_EQ(0u, session->num_active_streams());
4743  EXPECT_EQ(1u, session->num_created_streams());
4744  EXPECT_EQ(0u, session->num_pushed_streams());
4745  EXPECT_EQ(0u, session->num_active_pushed_streams());
4746
4747  scoped_ptr<SpdyHeaderBlock> headers(
4748      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4749  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4750  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4751
4752  // Run until 1st stream is activated.
4753  EXPECT_EQ(0u, delegate1.stream_id());
4754  data.RunFor(1);
4755  EXPECT_EQ(1u, delegate1.stream_id());
4756  EXPECT_EQ(1u, session->num_active_streams());
4757  EXPECT_EQ(0u, session->num_created_streams());
4758  EXPECT_EQ(0u, session->num_pushed_streams());
4759  EXPECT_EQ(0u, session->num_active_pushed_streams());
4760
4761  // Run until pushed stream is created.
4762  data.RunFor(1);
4763  EXPECT_EQ(2u, session->num_active_streams());
4764  EXPECT_EQ(0u, session->num_created_streams());
4765  EXPECT_EQ(1u, session->num_pushed_streams());
4766  EXPECT_EQ(1u, session->num_active_pushed_streams());
4767
4768  // Reset incoming pushed stream.
4769  data.RunFor(2);
4770  EXPECT_EQ(2u, session->num_active_streams());
4771  EXPECT_EQ(0u, session->num_created_streams());
4772  EXPECT_EQ(1u, session->num_pushed_streams());
4773  EXPECT_EQ(1u, session->num_active_pushed_streams());
4774
4775  // Read EOF.
4776  data.RunFor(1);
4777}
4778
4779TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
4780  // Streams in reserved remote state exist only in SPDY4.
4781  if (spdy_util_.spdy_version() < SPDY4)
4782    return;
4783
4784  scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
4785      NULL, 0, 2, 1, "http://www.google.com/a.dat"));
4786  scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4787  spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
4788                                 push_headers.get());
4789  scoped_ptr<SpdyFrame> push_b(
4790      spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 4, 1));
4791  scoped_ptr<SpdyFrame> headers_b(
4792      spdy_util_.ConstructSpdyPushHeaders(4, NULL, 0));
4793  MockRead reads[] = {
4794      CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
4795      CreateMockRead(*headers_b, 3), MockRead(ASYNC, 0, 5),
4796  };
4797
4798  scoped_ptr<SpdyFrame> req(
4799      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4800  scoped_ptr<SpdyFrame> rst(
4801      spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
4802  MockWrite writes[] = {
4803      CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
4804  };
4805
4806  DeterministicSocketData data(
4807      reads, arraysize(reads), writes, arraysize(writes));
4808  MockConnect connect_data(SYNCHRONOUS, OK);
4809  data.set_connect_data(connect_data);
4810  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4811
4812  CreateDeterministicNetworkSession();
4813
4814  base::WeakPtr<SpdySession> session =
4815      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4816  session->set_max_concurrent_pushed_streams(1);
4817
4818  GURL url1(kDefaultURL);
4819  base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4820      SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4821  ASSERT_TRUE(spdy_stream1.get() != NULL);
4822  EXPECT_EQ(0u, spdy_stream1->stream_id());
4823  test::StreamDelegateDoNothing delegate1(spdy_stream1);
4824  spdy_stream1->SetDelegate(&delegate1);
4825
4826  EXPECT_EQ(0u, session->num_active_streams());
4827  EXPECT_EQ(1u, session->num_created_streams());
4828  EXPECT_EQ(0u, session->num_pushed_streams());
4829  EXPECT_EQ(0u, session->num_active_pushed_streams());
4830
4831  scoped_ptr<SpdyHeaderBlock> headers(
4832      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4833  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4834  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4835
4836  // Run until 1st stream is activated.
4837  EXPECT_EQ(0u, delegate1.stream_id());
4838  data.RunFor(1);
4839  EXPECT_EQ(1u, delegate1.stream_id());
4840  EXPECT_EQ(1u, session->num_active_streams());
4841  EXPECT_EQ(0u, session->num_created_streams());
4842  EXPECT_EQ(0u, session->num_pushed_streams());
4843  EXPECT_EQ(0u, session->num_active_pushed_streams());
4844
4845  // Run until pushed stream is created.
4846  data.RunFor(1);
4847  EXPECT_EQ(2u, session->num_active_streams());
4848  EXPECT_EQ(0u, session->num_created_streams());
4849  EXPECT_EQ(1u, session->num_pushed_streams());
4850  EXPECT_EQ(1u, session->num_active_pushed_streams());
4851
4852  // Accept promised stream. It should not count towards pushed stream limit.
4853  data.RunFor(1);
4854  EXPECT_EQ(3u, session->num_active_streams());
4855  EXPECT_EQ(0u, session->num_created_streams());
4856  EXPECT_EQ(2u, session->num_pushed_streams());
4857  EXPECT_EQ(1u, session->num_active_pushed_streams());
4858
4859  // Reset last pushed stream upon headers reception as it is going to be 2nd,
4860  // while we accept only one.
4861  data.RunFor(2);
4862  EXPECT_EQ(2u, session->num_active_streams());
4863  EXPECT_EQ(0u, session->num_created_streams());
4864  EXPECT_EQ(1u, session->num_pushed_streams());
4865  EXPECT_EQ(1u, session->num_active_pushed_streams());
4866
4867  // Read EOF.
4868  data.RunFor(1);
4869}
4870
4871TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
4872  // Streams in reserved remote state exist only in SPDY4.
4873  if (spdy_util_.spdy_version() < SPDY4)
4874    return;
4875
4876  const char kPushedUrl[] = "http://www.google.com/a.dat";
4877  scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
4878  spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
4879  scoped_ptr<SpdyFrame> push_promise(
4880      spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 2, 1));
4881  scoped_ptr<SpdyFrame> headers_frame(
4882      spdy_util_.ConstructSpdyPushHeaders(2, NULL, 0));
4883  MockRead reads[] = {
4884      CreateMockRead(*push_promise, 1), CreateMockRead(*headers_frame, 2),
4885      MockRead(ASYNC, 0, 4),
4886  };
4887
4888  scoped_ptr<SpdyFrame> req(
4889      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4890  scoped_ptr<SpdyFrame> rst(
4891      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
4892  MockWrite writes[] = {
4893      CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
4894  };
4895
4896  DeterministicSocketData data(
4897      reads, arraysize(reads), writes, arraysize(writes));
4898  MockConnect connect_data(SYNCHRONOUS, OK);
4899  data.set_connect_data(connect_data);
4900  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4901
4902  CreateDeterministicNetworkSession();
4903
4904  base::WeakPtr<SpdySession> session =
4905      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4906
4907  GURL url1(kDefaultURL);
4908  base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
4909      SPDY_REQUEST_RESPONSE_STREAM, session, url1, LOWEST, BoundNetLog());
4910  ASSERT_TRUE(spdy_stream1.get() != NULL);
4911  EXPECT_EQ(0u, spdy_stream1->stream_id());
4912  test::StreamDelegateDoNothing delegate1(spdy_stream1);
4913  spdy_stream1->SetDelegate(&delegate1);
4914
4915  EXPECT_EQ(0u, session->num_active_streams());
4916  EXPECT_EQ(1u, session->num_created_streams());
4917  EXPECT_EQ(0u, session->num_pushed_streams());
4918  EXPECT_EQ(0u, session->num_active_pushed_streams());
4919
4920  scoped_ptr<SpdyHeaderBlock> headers(
4921      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
4922  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4923  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
4924
4925  // Run until 1st stream is activated.
4926  EXPECT_EQ(0u, delegate1.stream_id());
4927  data.RunFor(1);
4928  EXPECT_EQ(1u, delegate1.stream_id());
4929  EXPECT_EQ(1u, session->num_active_streams());
4930  EXPECT_EQ(0u, session->num_created_streams());
4931  EXPECT_EQ(0u, session->num_pushed_streams());
4932  EXPECT_EQ(0u, session->num_active_pushed_streams());
4933
4934  // Run until pushed stream is created.
4935  data.RunFor(1);
4936  EXPECT_EQ(2u, session->num_active_streams());
4937  EXPECT_EQ(0u, session->num_created_streams());
4938  EXPECT_EQ(1u, session->num_pushed_streams());
4939  EXPECT_EQ(0u, session->num_active_pushed_streams());
4940
4941  base::WeakPtr<SpdyStream> pushed_stream;
4942  int rv =
4943      session->GetPushStream(GURL(kPushedUrl), &pushed_stream, BoundNetLog());
4944  ASSERT_EQ(OK, rv);
4945  ASSERT_TRUE(pushed_stream.get() != NULL);
4946  test::StreamDelegateCloseOnHeaders delegate2(pushed_stream);
4947  pushed_stream->SetDelegate(&delegate2);
4948
4949  // Receive headers for pushed stream. Delegate will cancel the stream, ensure
4950  // that all our counters are in consistent state.
4951  data.RunFor(1);
4952  EXPECT_EQ(1u, session->num_active_streams());
4953  EXPECT_EQ(0u, session->num_created_streams());
4954  EXPECT_EQ(0u, session->num_pushed_streams());
4955  EXPECT_EQ(0u, session->num_active_pushed_streams());
4956
4957  // Read EOF.
4958  data.RunFor(2);
4959}
4960
4961TEST_P(SpdySessionTest, RejectInvalidUnknownFrames) {
4962  session_deps_.host_resolver->set_synchronous_mode(true);
4963
4964  MockRead reads[] = {
4965      MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
4966  };
4967
4968  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
4969
4970  MockConnect connect_data(SYNCHRONOUS, OK);
4971  data.set_connect_data(connect_data);
4972  session_deps_.socket_factory->AddSocketDataProvider(&data);
4973
4974  CreateNetworkSession();
4975  base::WeakPtr<SpdySession> session =
4976      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4977
4978  session->stream_hi_water_mark_ = 5;
4979  // Low client (odd) ids are fine.
4980  EXPECT_TRUE(session->OnUnknownFrame(3, 0));
4981  // Client id exceeding watermark.
4982  EXPECT_FALSE(session->OnUnknownFrame(9, 0));
4983
4984  session->last_accepted_push_stream_id_ = 6;
4985  // Low server (even) ids are fine.
4986  EXPECT_TRUE(session->OnUnknownFrame(2, 0));
4987  // Server id exceeding last accepted id.
4988  EXPECT_FALSE(session->OnUnknownFrame(8, 0));
4989}
4990
4991TEST(MapFramerErrorToProtocolError, MapsValues) {
4992  CHECK_EQ(
4993      SPDY_ERROR_INVALID_CONTROL_FRAME,
4994      MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4995  CHECK_EQ(
4996      SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4997      MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4998  CHECK_EQ(
4999      SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
5000      MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
5001  CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
5002           MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
5003}
5004
5005TEST(MapFramerErrorToNetError, MapsValue) {
5006  CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
5007           MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
5008  CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5009           MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
5010  CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
5011           MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
5012  CHECK_EQ(
5013      ERR_SPDY_FRAME_SIZE_ERROR,
5014      MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
5015}
5016
5017TEST(MapRstStreamStatusToProtocolError, MapsValues) {
5018  CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
5019           MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
5020  CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
5021           MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
5022  CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
5023           MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
5024}
5025
5026TEST(MapNetErrorToGoAwayStatus, MapsValue) {
5027  CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
5028           MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
5029  CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
5030           MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
5031  CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
5032           MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
5033  CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
5034           MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
5035  CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
5036           MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
5037  CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
5038}
5039
5040TEST(CanPoolTest, CanPool) {
5041  // Load a cert that is valid for:
5042  //   www.example.org
5043  //   mail.example.org
5044  //   www.example.com
5045
5046  TransportSecurityState tss;
5047  SSLInfo ssl_info;
5048  ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5049                                     "spdy_pooling.pem");
5050
5051  EXPECT_TRUE(SpdySession::CanPool(
5052      &tss, ssl_info, "www.example.org", "www.example.org"));
5053  EXPECT_TRUE(SpdySession::CanPool(
5054      &tss, ssl_info, "www.example.org", "mail.example.org"));
5055  EXPECT_TRUE(SpdySession::CanPool(
5056      &tss, ssl_info, "www.example.org", "mail.example.com"));
5057  EXPECT_FALSE(SpdySession::CanPool(
5058      &tss, ssl_info, "www.example.org", "mail.google.com"));
5059}
5060
5061TEST(CanPoolTest, CanNotPoolWithCertErrors) {
5062  // Load a cert that is valid for:
5063  //   www.example.org
5064  //   mail.example.org
5065  //   www.example.com
5066
5067  TransportSecurityState tss;
5068  SSLInfo ssl_info;
5069  ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5070                                     "spdy_pooling.pem");
5071  ssl_info.cert_status = CERT_STATUS_REVOKED;
5072
5073  EXPECT_FALSE(SpdySession::CanPool(
5074      &tss, ssl_info, "www.example.org", "mail.example.org"));
5075}
5076
5077TEST(CanPoolTest, CanNotPoolWithClientCerts) {
5078  // Load a cert that is valid for:
5079  //   www.example.org
5080  //   mail.example.org
5081  //   www.example.com
5082
5083  TransportSecurityState tss;
5084  SSLInfo ssl_info;
5085  ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5086                                     "spdy_pooling.pem");
5087  ssl_info.client_cert_sent = true;
5088
5089  EXPECT_FALSE(SpdySession::CanPool(
5090      &tss, ssl_info, "www.example.org", "mail.example.org"));
5091}
5092
5093TEST(CanPoolTest, CanNotPoolAcrossETLDsWithChannelID) {
5094  // Load a cert that is valid for:
5095  //   www.example.org
5096  //   mail.example.org
5097  //   www.example.com
5098
5099  TransportSecurityState tss;
5100  SSLInfo ssl_info;
5101  ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5102                                     "spdy_pooling.pem");
5103  ssl_info.channel_id_sent = true;
5104
5105  EXPECT_TRUE(SpdySession::CanPool(
5106      &tss, ssl_info, "www.example.org", "mail.example.org"));
5107  EXPECT_FALSE(SpdySession::CanPool(
5108      &tss, ssl_info, "www.example.org", "www.example.com"));
5109}
5110
5111TEST(CanPoolTest, CanNotPoolWithBadPins) {
5112  uint8 primary_pin = 1;
5113  uint8 backup_pin = 2;
5114  uint8 bad_pin = 3;
5115  TransportSecurityState tss;
5116  test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5117
5118  SSLInfo ssl_info;
5119  ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5120                                     "spdy_pooling.pem");
5121  ssl_info.is_issued_by_known_root = true;
5122  ssl_info.public_key_hashes.push_back(test::GetTestHashValue(bad_pin));
5123
5124  EXPECT_FALSE(SpdySession::CanPool(
5125      &tss, ssl_info, "www.example.org", "mail.example.org"));
5126}
5127
5128TEST(CanPoolTest, CanPoolWithAcceptablePins) {
5129  uint8 primary_pin = 1;
5130  uint8 backup_pin = 2;
5131  TransportSecurityState tss;
5132  test::AddPin(&tss, "mail.example.org", primary_pin, backup_pin);
5133
5134  SSLInfo ssl_info;
5135  ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(),
5136                                     "spdy_pooling.pem");
5137  ssl_info.is_issued_by_known_root = true;
5138  ssl_info.public_key_hashes.push_back(test::GetTestHashValue(primary_pin));
5139
5140  EXPECT_TRUE(SpdySession::CanPool(
5141      &tss, ssl_info, "www.example.org", "mail.example.org"));
5142}
5143
5144}  // namespace net
5145