spdy_session_unittest.cc revision c2db58bd994c04d98e4ee2cd7565b71548655fe3
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/callback.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
10a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "base/run_loop.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/io_buffer.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log_unittest.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/request_priority.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/test_data_directory.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/test_data_stream.h"
17a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "net/socket/client_socket_pool_manager.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/socket/next_proto.h"
197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "net/socket/socket_test_util.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_http_utils.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session_pool.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_session_test_util.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_stream.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_stream_test_util.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_test_util_common.h"
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/spdy/spdy_test_utils.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/test/cert_test_util.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/platform_test.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char kTestUrl[] = "http://www.example.org/";
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char kTestHost[] = "www.example.org";
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kTestPort = 80;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kBodyData[] = "Body data";
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kBodyDataSize = arraysize(kBodyData);
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::StringPiece kBodyDataStringPiece(kBodyData, kBodyDataSize);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic base::TimeDelta g_time_delta;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::TimeTicks TheNearFuture() {
44ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return base::TimeTicks::Now() + g_time_delta;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)class SpdySessionTest : public PlatformTest,
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        public ::testing::WithParamInterface<NextProto> {
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Functions used with RunResumeAfterUnstallTest().
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StallSessionOnly(SpdySession* session, SpdyStream* stream) {
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StallSessionSend(session);
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StallStreamOnly(SpdySession* session, SpdyStream* stream) {
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StallStreamSend(stream);
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StallSessionStream(SpdySession* session, SpdyStream* stream) {
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StallSessionSend(session);
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StallStreamSend(stream);
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StallStreamSession(SpdySession* session, SpdyStream* stream) {
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StallStreamSend(stream);
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StallSessionSend(session);
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void UnstallSessionOnly(SpdySession* session,
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          SpdyStream* stream,
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          int32 delta_window_size) {
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UnstallSessionSend(session, delta_window_size);
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void UnstallStreamOnly(SpdySession* session,
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         SpdyStream* stream,
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         int32 delta_window_size) {
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UnstallStreamSend(stream, delta_window_size);
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void UnstallSessionStream(SpdySession* session,
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            SpdyStream* stream,
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            int32 delta_window_size) {
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UnstallSessionSend(session, delta_window_size);
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UnstallStreamSend(stream, delta_window_size);
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void UnstallStreamSession(SpdySession* session,
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            SpdyStream* stream,
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            int32 delta_window_size) {
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UnstallStreamSend(stream, delta_window_size);
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UnstallSessionSend(session, delta_window_size);
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SpdySessionTest()
100a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
101a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)            HttpNetworkSession::NORMAL_SOCKET_POOL)),
102a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
103a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)            HttpNetworkSession::NORMAL_SOCKET_POOL)),
1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        spdy_util_(GetParam()),
1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        session_deps_(GetParam()),
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        spdy_session_pool_(NULL),
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        test_url_(kTestUrl),
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        test_host_port_pair_(kTestHost, kTestPort),
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        key_(test_host_port_pair_, ProxyServer::Direct(),
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)             kPrivacyModeDisabled) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  virtual ~SpdySessionTest() {
114a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Important to restore the per-pool limit first, since the pool limit must
115a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // always be greater than group limit, and the tests reduce both limits.
116a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ClientSocketPoolManager::set_max_sockets_per_pool(
117a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
118a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ClientSocketPoolManager::set_max_sockets_per_group(
119a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
120a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
121a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
122a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
123ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    g_time_delta = base::TimeDelta();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void CreateDeterministicNetworkSession() {
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    http_session_ =
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    spdy_session_pool_ = http_session_->spdy_session_pool();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void CreateNetworkSession() {
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    http_session_ =
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SpdySessionDependencies::SpdyCreateSession(&session_deps_);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    spdy_session_pool_ = http_session_->spdy_session_pool();
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void StallSessionSend(SpdySession* session) {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Reduce the send window size to 0 to stall.
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    while (session->session_send_window_size_ > 0) {
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->DecreaseSendWindowSize(
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          std::min(kMaxSpdyFrameChunkSize, session->session_send_window_size_));
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void UnstallSessionSend(SpdySession* session, int32 delta_window_size) {
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session->IncreaseSendWindowSize(delta_window_size);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StallStreamSend(SpdyStream* stream) {
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Reduce the send window size to 0 to stall.
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    while (stream->send_window_size() > 0) {
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      stream->DecreaseSendWindowSize(
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void UnstallStreamSend(SpdyStream* stream, int32 delta_window_size) {
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    stream->IncreaseSendWindowSize(delta_window_size);
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  void RunResumeAfterUnstallTest(
1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          unstall_function);
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
167a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Original socket limits.  Some tests set these.  Safest to always restore
168a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // them once each test has been run.
169a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  int old_max_group_sockets_;
170a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  int old_max_pool_sockets_;
171a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
172b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  SpdyTestUtil spdy_util_;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdySessionDependencies session_deps_;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<HttpNetworkSession> http_session_;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdySessionPool* spdy_session_pool_;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL test_url_;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HostPortPair test_host_port_pair_;
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SpdySessionKey key_;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(
1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    NextProto,
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SpdySessionTest,
184558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
185558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                    kProtoHTTP2Draft04));
1867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
187ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Try to create a SPDY session that will fail during
188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// initialization. Nothing should blow up.
189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, InitialReadError) {
190ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
191ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
192ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  TryCreateFakeSpdySessionExpectingFailure(
193ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_session_pool_, key_, ERR_FAILED);
194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
195ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
196ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// A session receiving a GOAWAY frame with no active streams should
197ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// immediately close.
198ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
199ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
200ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
201ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
202ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
203ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
204ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 0),
205ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
206ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
207ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
208ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
209ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
210ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
211ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
212ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
213ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
214ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
215ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
216ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
217ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
218ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
219ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
220ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
221ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
222ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the GOAWAY frame.
223ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
224ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
225ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
226ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
227ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
228ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
229ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
230ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// A session receiving a GOAWAY frame immediately with no active
231ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// streams should then close.
232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
233ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
234ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
235ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
236ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
237ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
238ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 0, SYNCHRONOUS),
239ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
240ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
241ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
242ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
243ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
244ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
245ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
246ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
247ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
248ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
249ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.StopAfter(1);
250ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
251ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  TryCreateInsecureSpdySessionExpectingFailure(
252ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
253ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
254ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
255ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
256ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
257ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// A session receiving a GOAWAY frame with active streams should close
258ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// when the last active stream is closed.
259ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CreateMockRead(*goaway, 2),
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MockRead(ASYNC, 0, 3)  // EOF
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockWrite writes[] = {
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CreateMockWrite(*req1, 0),
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CreateMockWrite(*req2, 1),
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               writes, arraysize(writes));
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CreateDeterministicNetworkSession();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
2877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL url("http://www.google.com");
292a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
298a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream2 =
29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateDoNothing delegate2(spdy_stream2);
30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream2->SetDelegate(&delegate2);
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
3067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
309ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
311ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.RunFor(2);
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(1u, spdy_stream1->stream_id());
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(3u, spdy_stream2->stream_id());
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Read and process the GOAWAY frame.
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.RunFor(1);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(session->IsStreamActive(3));
326ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
327ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
329ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(session->IsClosed());
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Should close the session.
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  spdy_stream1->Close();
333a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
335ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
336ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
338ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Have a session receive two GOAWAY frames, with the last one causing
339ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the last active stream to be closed. The session should then be
340ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// closed after the second GOAWAY frame.
341ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayTwice) {
342ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
343ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
344ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
345ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
346ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
347ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
348ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway1, 2),
349ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway2, 3),
350ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 4)  // EOF
351ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req1(
353ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
354ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req2(
355ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
356ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockWrite writes[] = {
357ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req1, 0),
358ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req2, 1),
359ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
360ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
361ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               writes, arraysize(writes));
362ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
363ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
364ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
365ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
366ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
368ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
369ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
370ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
371ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
372ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
373ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
374ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
375ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  GURL url("http://www.google.com");
376ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
377ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
378ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
379ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
380ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream1->SetDelegate(&delegate1);
381ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
382ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
383ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
384ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
385ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate2(spdy_stream2);
386ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream2->SetDelegate(&delegate2);
387ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
388ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
389ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
391ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
392ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
393ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
394ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
395ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
396ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
397ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(2);
398ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
399ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(1u, spdy_stream1->stream_id());
400ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(3u, spdy_stream2->stream_id());
401ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
402ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
403ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
404ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the first GOAWAY frame.
405ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
406ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
407ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
408ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
409ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(session->IsStreamActive(3));
410a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream2.get());
411ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
412ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
413ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(session->IsClosed());
414ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
415ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the second GOAWAY frame, which should close the
416ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // session.
417ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
418ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
419ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
420ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
421ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
422ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Have a session with active streams receive a GOAWAY frame and then
423ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// close it. It should handle the close properly (i.e., not try to
424ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// make itself unavailable in its pool twice).
425ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
426ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
427ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
428ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
429ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
430ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
431ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 2),
432ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 3)  // EOF
433ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
434ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req1(
435ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
436ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req2(
437ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
438ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockWrite writes[] = {
439ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req1, 0),
440ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req2, 1),
441ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
442ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
443ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               writes, arraysize(writes));
444ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
445ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
446ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
447ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
448ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
449ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
450ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
451ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
453ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
454ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
455ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
456ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
457ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  GURL url("http://www.google.com");
458ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
459ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
460ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
461ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
462ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream1->SetDelegate(&delegate1);
463ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
464ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
465ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
466ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
467ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate2(spdy_stream2);
468ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream2->SetDelegate(&delegate2);
469ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
470ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
471ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
472ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
473ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
474ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
475ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
476ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
477ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
478ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
479ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(2);
480ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
481ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(1u, spdy_stream1->stream_id());
482ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(3u, spdy_stream2->stream_id());
483ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
484ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
485ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
486ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the GOAWAY frame.
487ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
488ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
489ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
490ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
491ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(session->IsStreamActive(3));
492ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
493ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
494ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
495ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(session->IsClosed());
496ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
497ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
498ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
499ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
500ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
501ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
502ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
503ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Try to create a stream after receiving a GOAWAY frame. It should
504ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// fail.
505ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
506ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const char kStreamUrl[] = "http://www.google.com";
507ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
508ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
509ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
510ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
511ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
512ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 1),
513ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 2)  // EOF
514ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
515ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req(
516ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
517ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockWrite writes[] = {
518ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req, 0),
519ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
520ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
521ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               writes, arraysize(writes));
522ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
523ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
524ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
525ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
526ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
527ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
528ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
529ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
530ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
531ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
532ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
533ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
534ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
535ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  GURL url(kStreamUrl);
536ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
537ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
538ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
539ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate(spdy_stream);
540ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SetDelegate(&delegate);
541ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
542ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
543ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
544ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
545ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
546ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
547ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
548ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
549ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(1u, spdy_stream->stream_id());
550ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
551ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
552ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
553ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the GOAWAY frame.
554ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
555ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
556ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
557ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
558ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
559ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdyStreamRequest stream_request;
560ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int rv = stream_request.StartRequest(
561ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog(),
562ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CompletionCallback());
563ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(ERR_FAILED, rv);
564ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
565ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process EOF.
566ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
567ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
568ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
569ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
570ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
571ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Receiving a SYN_STREAM frame after a GOAWAY frame should result in
572ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the stream being refused.
573ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, SynStreamAfterGoAway) {
574ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const char kStreamUrl[] = "http://www.google.com";
575ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
576ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
577ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
578ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
579ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame>
580ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
581ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
582ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 1),
583ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*push, 2),
584ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 4)  // EOF
585ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
586ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req(
587ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
588ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> rst(
589ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
590ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockWrite writes[] = {
591ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req, 0),
592ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*rst, 3)
593ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
594ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
595ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               writes, arraysize(writes));
596ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
597ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
598ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
599ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
600ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
601ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
602ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
603ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
604ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
605ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
606ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
607ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
608ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
609ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  GURL url(kStreamUrl);
610ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
611ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
612ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
613ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate(spdy_stream);
614ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SetDelegate(&delegate);
615ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
616ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
617ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
618ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
619ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
620ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
621ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
622ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
623ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(1u, spdy_stream->stream_id());
624ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
625ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
626ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
627ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the GOAWAY frame.
628ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
629ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
630ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
631ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
632ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
633ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
634ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // and EOF.
635ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(3);
636ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
637ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ClientPing) {
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.enable_ping = true;
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
64590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1));
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
647ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*read_ping, 1),
648ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 0, 2)  // EOF
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
65090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1));
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
652ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*write_ping, 0),
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
654ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
657ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
660ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
662ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
664ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
6657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
667a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
66890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
66990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, test_url_, MEDIUM, BoundNetLog());
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
67190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks before_ping_time = base::TimeTicks::Now();
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session->set_connection_at_risk_of_loss_time(
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TimeDelta::FromSeconds(-1));
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->SendPrefacePingIfNoneInFlight();
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
682ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(2);
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->CheckPingStatus(before_ping_time);
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, session->pings_in_flight());
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1));
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(session->check_ping_status_pending());
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(session->last_activity_time(), before_ping_time);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
691ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
692ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
693ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
696ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ServerPing) {
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
70390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2));
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*read_ping),
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SYNCHRONOUS, 0, 0)  // EOF
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
70890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2));
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*write_ping),
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
722ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
7237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
72690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
72790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, test_url_, MEDIUM, BoundNetLog());
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
72990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate);
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
732ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Flush the read completion task.
73390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
737ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
738a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
741ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Cause a ping to be sent out while producing a write. The write loop
742ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// should handle this properly, i.e. another DoWriteLoop task should
743ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// not be posted. This is a regression test for
744ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// http://crbug.com/261043 .
745ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, PingAndWriteLoop) {
746ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.enable_ping = true;
747ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.time_func = TheNearFuture;
748ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
749ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
750ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1));
751ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req(
752ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
753ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockWrite writes[] = {
754ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req, 0),
755ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*write_ping, 1),
756ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
757ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
758ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
759ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 2)  // EOF
760ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
761ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
762ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
763ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
764ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
765ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               writes, arraysize(writes));
766ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
767ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
768ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
769ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
770ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
771ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
772ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
773ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
774ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
775ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
776ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
777ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  GURL url("http://www.google.com");
778ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
779ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
780ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, LOWEST, BoundNetLog());
781ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate(spdy_stream);
782ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SetDelegate(&delegate);
783ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
784ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
785ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
786ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
787ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
788ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Shift time so that a ping will be sent out.
789ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  g_time_delta = base::TimeDelta::FromSeconds(11);
790ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
791ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(2);
792ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
793ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, "Aborting");
794ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
795ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
7967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.time_func = TheNearFuture;
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
8067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_);
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  session->buffered_spdy_framer_.reset(
8097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      new BufferedSpdyFramer(spdy_util_.spdy_version(), false));
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the associated stream and add to active streams.
8127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> request_headers(
8137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<SpdyStream> stream(new SpdyStream(SPDY_REQUEST_RESPONSE_STREAM,
816ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                               session,
817ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                               GURL(),
818868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                               DEFAULT_PRIORITY,
819868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                               kSpdyStreamInitialWindowSize,
820868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                               kSpdyStreamInitialWindowSize,
821868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                               session->net_log_));
82290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  stream->SendRequestHeaders(request_headers.Pass(), NO_MORE_DATA_TO_SEND);
823a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  SpdyStream* stream_ptr = stream.get();
824a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  session->InsertCreatedStream(stream.Pass());
825a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  stream = session->ActivateCreatedStream(stream_ptr);
826a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  session->InsertActivatedStream(stream.Pass());
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpdyHeaderBlock headers;
8297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  spdy_util_.AddUrlToHeaderBlock("http://www.google.com/a.dat", &headers);
8307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
831ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // OnSynStream() expects |in_io_loop_| to be true.
832ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->in_io_loop_ = true;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->OnSynStream(2, 1, 0, 0, true, false, headers);
834ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->in_io_loop_ = false;
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that there is one unclaimed push stream.
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
83890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SpdySession::PushedStreamMap::iterator iter =
839ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      session->unclaimed_pushed_streams_.find(
840ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          GURL("http://www.google.com/a.dat"));
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
843ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Shift time to expire the push stream.
844ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  g_time_delta = base::TimeDelta::FromSeconds(301);
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat", &headers);
847ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->in_io_loop_ = true;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->OnSynStream(4, 1, 0, 0, true, false, headers);
849ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->in_io_loop_ = false;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that the second pushed stream evicted the first pushed stream.
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
853ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  iter = session->unclaimed_pushed_streams_.find(
854ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      GURL("http://www.google.com/b.dat"));
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, FailedPing) {
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
863ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 0, 0)  // EOF
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
86590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1));
866ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
868ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
871ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
873ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
8767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
878a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
87990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
88090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, test_url_, MEDIUM, BoundNetLog());
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
88290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate);
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->set_hung_interval(base::TimeDelta::FromSeconds(0));
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send a PING frame.
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->WritePingFrame(1);
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(0, session->pings_in_flight());
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1));
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(session->check_ping_status_pending());
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assert session is not closed.
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(session->IsClosed());
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams());
8977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We set last time we have received any data in 1 sec less than now.
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CheckPingStatus will trigger timeout because hung interval is zero.
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks now = base::TimeTicks::Now();
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->CheckPingStatus(now);
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
9067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
908ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
909a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
912a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Request kInitialMaxConcurrentStreams + 1 streams.  Receive a
913a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// settings frame increasing the max concurrent streams by 1.  Make
914a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// sure nothing blows up. This is a regression test for
915a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// http://crbug.com/57331 .
9167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, OnSettings) {
9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
919ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
920ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsMap new_settings;
922a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
923ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  new_settings[kSpdySettingsIds] =
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
92590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
92690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(new_settings));
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
928a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    CreateMockRead(*settings_frame, 0),
929a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    MockRead(ASYNC, 0, 1),
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
932a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
933ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
935ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
938ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
940ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
942ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
9437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create the maximum number of concurrent streams.
946a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
947a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream =
948a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
949a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  session, test_url_, MEDIUM, BoundNetLog());
950a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
951a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
953a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  StreamReleaserCallback stream_releaser;
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyStreamRequest request;
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING,
95690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            request.StartRequest(
95790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
95890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                BoundNetLog(),
95990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                stream_releaser.MakeCallback(&request)));
960ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
961a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.RunFor(1);
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  EXPECT_EQ(OK, stream_releaser.WaitForResult());
964ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
965ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
966ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
969a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Start with a persisted value for max concurrent streams. Receive a
970a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// settings frame increasing the max concurrent streams by 1 and which
971a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// also clears the persisted data. Verify that persisted data is
972a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// correct.
9737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ClearSettings) {
974c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
975c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
976c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SettingsMap new_settings;
977a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
978a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
98090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
98190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(new_settings));
982c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
983eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
984c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockRead reads[] = {
985a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    CreateMockRead(*settings_frame, 0),
986a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    MockRead(ASYNC, 0, 1),
987c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
988c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
989a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
990ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
991c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.set_connect_data(connect_data);
992ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
993c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
994c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
995ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
996c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
997ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
998c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
999a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Initialize the SpdySetting with the default.
1000c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  spdy_session_pool_->http_server_properties()->SetSpdySetting(
1001c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      test_host_port_pair_,
1002a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      SETTINGS_MAX_CONCURRENT_STREAMS,
1003c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SETTINGS_FLAG_PLEASE_PERSIST,
1004a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      kInitialMaxConcurrentStreams);
1005c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1006a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_FALSE(
1007a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      spdy_session_pool_->http_server_properties()->GetSpdySettings(
1008a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          test_host_port_pair_).empty());
1009c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1010ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
10117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1012c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1013a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create the maximum number of concurrent streams.
1014a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1015a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream =
1016a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1017a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  session, test_url_, MEDIUM, BoundNetLog());
1018a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
1019a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1020c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1021a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  StreamReleaserCallback stream_releaser;
1022c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1023c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SpdyStreamRequest request;
1024c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING,
102590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            request.StartRequest(
102690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
102790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                BoundNetLog(),
102890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                stream_releaser.MakeCallback(&request)));
1029c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1030a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.RunFor(1);
1031ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
10329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  EXPECT_EQ(OK, stream_releaser.WaitForResult());
1033c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1034c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure that persisted data is cleared.
1035a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_TRUE(
1036a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      spdy_session_pool_->http_server_properties()->GetSpdySettings(
1037a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          test_host_port_pair_).empty());
1038c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1039a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Make sure session's max_concurrent_streams is correct.
1040a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1041a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            session->max_concurrent_streams());
10427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1043ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
1044ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
1045c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1046c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1047a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Start with max concurrent streams set to 1.  Request two streams.
1048a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// When the first completes, have the callback close its stream, which
1049a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// should trigger the second stream creation.  Then cancel that one
1050a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// immediately.  Don't crash.  This is a regression test for
1051a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// http://crbug.com/63532 .
10527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, CancelPendingCreateStream) {
10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
10632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
10662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the SpdySetting with 1 max concurrent streams.
10712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_session_pool_->http_server_properties()->SetSpdySetting(
10722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_,
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_MAX_CONCURRENT_STREAMS,
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_FLAG_PLEASE_PERSIST,
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1);
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1077ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
10787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1080a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Leave room for only one more stream to be created.
1081a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1082a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream =
1083a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1084a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  session, test_url_, MEDIUM, BoundNetLog());
1085a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
1086a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1087a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1088a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create 2 more streams.  First will succeed.  Second will be pending.
1089a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
109090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
109190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, test_url_, MEDIUM, BoundNetLog());
10922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a valgrind error if the callback is invoked when it's not supposed to be.
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyStreamRequest request;
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING,
110090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            request.StartRequest(
110190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
110290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                BoundNetLog(),
110390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                callback->callback()));
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Release the first one, this will allow the second to be created.
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  spdy_stream1->Cancel();
1107a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request.CancelRequest();
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.reset();
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should not crash when running the pending callback.
111390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsMap settings;
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdySettingsIds kSpdySettingsIds2 = SETTINGS_INITIAL_WINDOW_SIZE;
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32 kInitialRecvWindowSize = 10 * 1024 * 1024;
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings[kSpdySettingsIds1] =
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
11297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (spdy_util_.spdy_version() >= SPDY3) {
11307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    settings[kSpdySettingsIds2] =
11317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialRecvWindowSize);
11327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
113490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
113590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(settings));
1136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> initial_window_update(
1137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(
1138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kSessionFlowControlStreamId,
1139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
1140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::vector<MockWrite> writes;
1141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (GetParam() == kProtoHTTP2Draft04) {
1142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    writes.push_back(
1143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        MockWrite(ASYNC,
1144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  kHttp2ConnectionHeaderPrefix,
1145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  kHttp2ConnectionHeaderPrefixSize));
1146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  writes.push_back(CreateMockWrite(*settings_frame));
1148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (GetParam() >= kProtoSPDY31) {
1149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    writes.push_back(CreateMockWrite(*initial_window_update));
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  SettingsMap server_settings;
1153a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const uint32 initial_max_concurrent_streams = 1;
1154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            initial_max_concurrent_streams);
1157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<SpdyFrame> server_settings_frame(
1158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      spdy_util_.ConstructSpdySettings(server_settings));
1159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  writes.push_back(CreateMockWrite(*server_settings_frame));
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize;
1162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads),
1164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                vector_as_array(&writes), writes.size());
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
11662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
11692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_session_pool_->http_server_properties()->SetSpdySetting(
11742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_,
1175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      SETTINGS_MAX_CONCURRENT_STREAMS,
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_FLAG_PLEASE_PERSIST,
1177a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      initial_max_concurrent_streams);
1178a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1180a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  pool_peer.SetEnableSendingInitialData(true);
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1182ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
11837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
118590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
11867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(data.at_write_eof());
11872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
11902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1192ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<HttpServerProperties> test_http_server_properties =
11932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spdy_session_pool_->http_server_properties();
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_http_server_properties->SetSpdySetting(
11962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_,
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_MAX_CONCURRENT_STREAMS,
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_FLAG_PLEASE_PERSIST,
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      2);
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
12012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_).size());
12022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_session_pool_->OnIPAddressChanged();
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
12042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_).size());
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, Initialize) {
1208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CapturingBoundNetLog log;
1209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.net_log = log.bound().net_log();
1210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
1211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockRead reads[] = {
1214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
1215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
1216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.set_connect_data(connect_data);
1219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
1220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CreateNetworkSession();
1225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1226ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
12277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, log.bound());
12287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1230ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Flush the read completion task.
123190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  net::CapturingNetLog::CapturedEntryList entries;
1234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  log.GetEntries(&entries);
1235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(0u, entries.size());
1236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly.
1238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int pos = net::ExpectLogContainsSomewhere(
1239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      entries, 0,
1240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      net::NetLog::TYPE_SPDY_SESSION_INITIALIZED,
1241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      net::NetLog::PHASE_NONE);
1242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(0, pos);
1243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CapturingNetLog::CapturedEntry entry = entries[pos];
1245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NetLog::Source socket_source;
1246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                  &socket_source));
1248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(socket_source.IsValid());
1249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_NE(log.bound().source().id, socket_source.id);
1250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
12527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, CloseSessionOnError) {
12532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
125690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
12582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*goaway),
12592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(SYNCHRONOUS, 0, 0)  // EOF
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
12612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
12642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
12672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CapturingBoundNetLog log;
1272ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
12737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, log.bound());
12747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1276ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Flush the read completion task.
127790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1280ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that the NetLog was filled reasonably.
12832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::CapturingNetLog::CapturedEntryList entries;
12842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  log.GetEntries(&entries);
12852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_LT(0u, entries.size());
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that we logged SPDY_SESSION_CLOSE correctly.
12882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int pos = net::ExpectLogContainsSomewhere(
12892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      entries, 0,
12902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::NetLog::TYPE_SPDY_SESSION_CLOSE,
12912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::NetLog::PHASE_NONE);
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (pos < static_cast<int>(entries.size())) {
1294ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CapturingNetLog::CapturedEntry entry = entries[pos];
1295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    int error_code = 0;
1296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1298ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  } else {
1299ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ADD_FAILURE();
1300ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
13012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Queue up a low-priority SYN_STREAM followed by a high-priority
1304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// one. The high priority one should still send first and receive
1305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// first.
13067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
13072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Construct the request.
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req_highest(
131090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true));
1311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req_lowest(
131290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
1314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req_highest, 0),
1315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req_lowest, 1),
13162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
13172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp_highest(
1319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body_highest(
1321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
1322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp_lowest(
1323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body_lowest(
1325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(3, true));
13262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
1327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp_highest, 2),
1328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body_highest, 3),
1329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp_lowest, 4),
1330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body_lowest, 5),
1331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 6)  // EOF
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
13332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
13352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
1337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
1339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1346ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
13477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url("http://www.google.com");
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream_lowest =
135290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
135390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
1354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream_lowest);
1355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream_lowest->SetDelegate(&delegate_lowest);
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream_highest =
136090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
136190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, HIGHEST, BoundNetLog());
1362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream_highest);
1363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream_highest->SetDelegate(&delegate_highest);
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Queue the lower priority one first.
1368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers_lowest(
1370b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
1371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream_lowest->SendRequestHeaders(
1372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1373ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers_highest(
1376b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
1377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream_highest->SendRequestHeaders(
1378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1379ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(7);
13822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(spdy_stream_lowest);
1384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(spdy_stream_highest);
1385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, delegate_lowest.stream_id());
1386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, delegate_highest.stream_id());
13872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, CancelStream) {
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
13912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Request 1, at HIGHEST priority, will be cancelled before it writes data.
13922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Request 2, at LOWEST priority, will be a full request and will be id 1.
139390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
139490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
13952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
13962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req2, 0),
13972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
13982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
14007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
14022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp2, 1),
14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*body2, 2),
14042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(ASYNC, 0, 3)  // EOF
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
14102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
14122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
14152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1419ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
14207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url1("http://www.google.com");
1423a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
142490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
142590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, HIGHEST, BoundNetLog());
14262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
14272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
1428a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
1429a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url2("http://www.google.com");
1432a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream2 =
143390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
143490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url2, LOWEST, BoundNetLog());
14352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream2.get() != NULL);
14362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream2->stream_id());
1437a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate2(spdy_stream2);
1438a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream2->SetDelegate(&delegate2);
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
144090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
1441b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
144290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1443ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
144590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
1446b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
144790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1448ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_stream1->Cancel();
1453a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.RunFor(1);
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1459a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
1460a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(1u, delegate2.stream_id());
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  spdy_stream2->Cancel();
1463a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream2.get());
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to re-close themselves on close,
1467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// and then close the session. Nothing should blow up. Also a
1468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// regression test for http://crbug.com/139518 .
1469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
14702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
14712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No actual data will be sent.
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, 0, 1)  // EOF
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
14852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
14882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1492ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
14937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url1("http://www.google.com");
1496a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
149790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
149890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, HIGHEST, BoundNetLog());
14992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url2("http://www.google.com");
1503a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream2 =
150490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
150590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url2, LOWEST, BoundNetLog());
15062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream2.get() != NULL);
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, spdy_stream2->stream_id());
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate1(spdy_stream1);
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate2(spdy_stream2);
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  spdy_stream2->SetDelegate(&delegate2);
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
151590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
151690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
151790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1518ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
151990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
152090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
152190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
152290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1523ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the streams have not yet been activated and assigned an id.
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, spdy_stream2->stream_id());
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure we don't crash while closing the session.
15307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, std::string());
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1532a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
1533a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream2.get());
1534a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1535a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_TRUE(delegate1.StreamIsClosed());
1536a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_TRUE(delegate2.StreamIsClosed());
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1538ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to close each other on close, and
1542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// then close the session. Nothing should blow up.
1543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
15442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
15452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No actual data will be sent.
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, 0, 1)  // EOF
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
15592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
15622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1566ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
15677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url1("http://www.google.com");
1570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
1571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, HIGHEST, BoundNetLog());
1573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
1574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url2("http://www.google.com");
1577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
1578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url2, LOWEST, BoundNetLog());
1580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream2.get() != NULL);
1581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Make |spdy_stream1| close |spdy_stream2|.
1584eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate1(spdy_stream2);
1585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
1586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Make |spdy_stream2| close |spdy_stream1|.
1588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate2(spdy_stream1);
1589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SetDelegate(&delegate2);
1590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
1592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1594ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
1595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
1597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1599ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
16007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure that the streams have not yet been activated and assigned an id.
1602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
1603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
1604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure we don't crash while closing the session.
16067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, std::string());
1607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
1609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
1610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.StreamIsClosed());
1612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.StreamIsClosed());
1613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1614ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
1615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
1616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to re-close themselves on close,
1618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// activate them, and then close the session. Nothing should blow up.
1619eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
16202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
16212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
1625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
1627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
1629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
1630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
1634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 2)  // EOF
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
16402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
16432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1647ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
16487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
16492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url1("http://www.google.com");
1651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
1652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, MEDIUM, BoundNetLog());
1654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
1655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
16562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url2("http://www.google.com");
1658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
1659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url2, MEDIUM, BoundNetLog());
1661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream2.get() != NULL);
1662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
16637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate1(spdy_stream1);
1665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
16662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate2(spdy_stream2);
1668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SetDelegate(&delegate2);
16692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
1671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
1672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1673ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
16742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
1676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1678ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
16792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure that the streams have not yet been activated and assigned an id.
1681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
1682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
16832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
16852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, spdy_stream1->stream_id());
1687eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, spdy_stream2->stream_id());
1688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure we don't crash while closing the session.
16907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, std::string());
1691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
1693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
1694eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1695eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.StreamIsClosed());
1696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.StreamIsClosed());
1697eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1698ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
1699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
1700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to close each other on close,
1702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// activate them, and then close the session. Nothing should blow up.
1703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
1704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
1705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
1707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
1709eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
1711eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
1712eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
1713eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
1714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
1715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
17162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
1718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 2)  // EOF
17192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
17202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
17222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
17232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
17242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
17252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
17272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
17282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
17302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1731ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
17327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
17332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url1("http://www.google.com");
1735a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
173690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, MEDIUM, BoundNetLog());
17382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
17392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
17402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url2("http://www.google.com");
1742eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
1743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1744eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url2, MEDIUM, BoundNetLog());
1745eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream2.get() != NULL);
1746eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
17472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1748eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Make |spdy_stream1| close |spdy_stream2|.
1749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate1(spdy_stream2);
1750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
17512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Make |spdy_stream2| close |spdy_stream1|.
1753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate2(spdy_stream1);
1754eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SetDelegate(&delegate2);
17552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
175690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
1757b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
175890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1759ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
17602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
176190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
176290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
1763eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1764ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
17652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1766eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure that the streams have not yet been activated and assigned an id.
17672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
1768eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
17692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
17712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, spdy_stream1->stream_id());
1773eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, spdy_stream2->stream_id());
17742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure we don't crash while closing the session.
17767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, std::string());
17772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1778a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
1779a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream2.get());
17802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.StreamIsClosed());
1782eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.StreamIsClosed());
1783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1784ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
17852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
17862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1787bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Delegate that closes a given session when the stream is closed.
1788bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochclass SessionClosingDelegate : public test::StreamDelegateDoNothing {
1789bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch public:
1790bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
1791bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                         const base::WeakPtr<SpdySession>& session_to_close)
1792bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      : StreamDelegateDoNothing(stream),
1793bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        session_to_close_(session_to_close) {}
1794bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1795bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual ~SessionClosingDelegate() {}
1796bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1797bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual void OnClose(int status) OVERRIDE {
1798bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    session_to_close_->CloseSessionOnError(ERR_ABORTED, "Aborted");
1799bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  }
1800bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1801bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch private:
1802bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdySession> session_to_close_;
1803bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch};
1804bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1805bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Close an activated stream that closes its session. Nothing should
1806bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// blow up. This is a regression test for http://crbug.com/263691 .
1807bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
1808bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
1809bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1810bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
1811bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1812bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyFrame> req(
1813bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
1814bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockWrite writes[] = {
1815bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    CreateMockWrite(*req, 0),
1816bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  };
1817bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1818bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockRead reads[] = {
1819bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    MockRead(ASYNC, 0, 1)  // EOF
1820bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  };
1821bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
1822bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                               writes, arraysize(writes));
1823bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.set_connect_data(connect_data);
1824bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1825bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1826bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1827bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1828bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1829bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  CreateDeterministicNetworkSession();
1830bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1831bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdySession> session =
1832bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1833bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1834bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  GURL url("http://www.google.com");
1835bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
1836bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
1837bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
1838bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  ASSERT_TRUE(spdy_stream.get() != NULL);
1839bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, spdy_stream->stream_id());
1840bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1841bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  SessionClosingDelegate delegate(spdy_stream, session);
1842bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->SetDelegate(&delegate);
1843bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1844bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
1845bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
1846bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1847bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
1848bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1849bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, spdy_stream->stream_id());
1850bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1851bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.RunFor(1);
1852bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1853bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(1u, spdy_stream->stream_id());
1854bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1855bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Ensure we don't crash while closing the stream (which closes the
1856bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // session).
1857bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->Cancel();
1858bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1859bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(NULL, spdy_stream.get());
1860bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(delegate.StreamIsClosed());
1861bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(session == NULL);
1862bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
1863bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, VerifyDomainAuthentication) {
1865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
18667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
18672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1868eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // No actual data will be sent.
1870eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
1871eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(ASYNC, 0, 1)  // EOF
1872eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
1873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
18742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
1875eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
18762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1877eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
1878eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
18792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
1880eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1882eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Load a cert that is valid for:
1883eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   www.example.org
1884eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   mail.example.org
1885eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   www.example.com
1886eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::FilePath certs_dir = GetTestCertsDirectory();
1887eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<X509Certificate> test_cert(
1888eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
1889eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert);
18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ssl.cert = test_cert;
1893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
18962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1897ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
18987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateSecureSpdySession(http_session_, key_, BoundNetLog());
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1900eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
1901eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
1902eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
1903eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
19042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
19052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1906eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
1907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
19087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
19092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1910eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1911eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // No actual data will be sent.
19122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
1913eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(ASYNC, 0, 1)  // EOF
19142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1915eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
1917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
1918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
1919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
1920eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
19212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
1922eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1923eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Load a cert that is valid for:
1925eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   www.example.org
1926eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   mail.example.org
1927eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   www.example.com
1928eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::FilePath certs_dir = GetTestCertsDirectory();
1929eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<X509Certificate> test_cert(
1930eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
1931eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert);
19322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ssl.channel_id_sent = true;
1935eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ssl.cert = test_cert;
1936eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
19372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1938eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
19392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1940ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
19417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateSecureSpdySession(http_session_, key_, BoundNetLog());
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1943eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
1944eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
1945eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
1946eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
19472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
19482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1949eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
1950eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(rtenneti): Define a helper class/methods and move the common code in
1951eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // this file.
19522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
19537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1954eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SettingsMap new_settings;
1955eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
1956eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const uint32 max_concurrent_streams = 1;
1957eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  new_settings[kSpdySettingsIds1] =
1958eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
19592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
196090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
1961eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1962eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
1963eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1964eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req3(
1965eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
19662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
1967eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 1),
1968eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 4),
1969eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req3, 7),
19702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
19712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1972eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set up the socket so we read a SETTINGS frame that sets max concurrent
1973eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // streams to 1.
1974eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame(
1975eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(new_settings));
19762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1978eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
1979eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1980eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1981eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1982eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1983eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1984eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
19852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
1987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*settings_frame),
1988eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp1, 2),
1989eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body1, 3),
1990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 5),
1991eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2, 6),
1992eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp3, 8),
1993eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body3, 9),
1994eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 10)  // EOF
19952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
19962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
19982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
19992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
20002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
20012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
20042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
20062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2007ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
20087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
20092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2010eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the settings frame.
2011eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
2012eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
20132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url1("http://www.google.com");
2014a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
201590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2016eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, LOWEST, BoundNetLog());
20172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
20182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
2019a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2020a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
20212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
2023eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url2("http://www.google.com");
2024eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request2;
2025eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2026eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request2.StartRequest(
2027eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_REQUEST_RESPONSE_STREAM,
2028eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2029eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2030eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback3;
2031eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url3("http://www.google.com");
2032eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request3;
2033eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2034eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request3.StartRequest(
2035eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_REQUEST_RESPONSE_STREAM,
2036eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2037eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2038a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2039a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
20407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2043b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2044eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2045ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
20462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2047a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Run until 1st stream is activated and then closed.
2048a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
2049eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(3);
2050a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
2051eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, delegate1.stream_id());
2052a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2053a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2054a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
2055a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2056a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2057a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2058a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // create the 2nd stream.
2059a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2060a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2061a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2062a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
2063a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
20642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2065eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2066eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate2(stream2);
2067eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream2->SetDelegate(&delegate2);
2068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
2069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2071ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
2072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2073a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Run until 2nd stream is activated and then closed.
2074eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, delegate2.stream_id());
2075eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(3);
2076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream2.get());
2077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, delegate2.stream_id());
2078a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2079a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2080a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
2081a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2082a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2083a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2084a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // create the 3rd stream.
2085a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2086a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2087a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2088a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
20897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate3(stream3);
2093eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream3->SetDelegate(&delegate3);
2094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers3(
2095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2097ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream3->HasUrlFromHeaders());
2098eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2099a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Run until 2nd stream is activated and then closed.
2100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, delegate3.stream_id());
2101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(3);
2102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream3.get());
2103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(5u, delegate3.stream_id());
2104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
21077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2108ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
2109ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
2110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
2114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
2123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
2124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
2129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2130ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
21317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Leave room for only one more stream to be created.
2134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream =
2136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  session, test_url_, MEDIUM, BoundNetLog());
2138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
2139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
2140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url1("http://www.google.com");
2142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
2143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, LOWEST, BoundNetLog());
2145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
2146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
2147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
2149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url2("http://www.google.com");
2150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request2;
2151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request2.StartRequest(
2153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                callback2.callback()));
2155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback3;
2157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url3("http://www.google.com");
2158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request3;
2159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request3.StartRequest(
2161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                callback3.callback()));
2163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
21667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Cancel the first stream; this will allow the second stream to be created.
2169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(spdy_stream1.get() != NULL);
2170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->Cancel();
2171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
2172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2173a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(OK, callback2.WaitForResult());
2174a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2176a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2178a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Cancel the second stream; this will allow the third stream to be created.
2179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->Cancel();
2181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
2182a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2183a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(OK, callback3.WaitForResult());
2184a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2185a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
21867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Cancel the third stream.
2189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream3->Cancel();
2191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream3.get());
2192a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2193a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
21947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, NeedsCredentials) {
2198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
2204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
2205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ssl.channel_id_sent = true;
2208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ssl.protocol_negotiated = GetParam();
2209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
2212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const GURL url("https://www.foo.com");
2214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair test_host_port_pair(url.host(), 443);
2215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key(test_host_port_pair, ProxyServer::Direct(),
2216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     kPrivacyModeDisabled);
2217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2218ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
22197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateSecureSpdySession(http_session_, key, BoundNetLog());
2220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(spdy_util_.spdy_version() >= SPDY3, session->NeedsCredentials());
2222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2223ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Flush the read completion task.
2224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
2225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
22267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, std::string());
2227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2229ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop reads data from the socket
2230ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// without yielding.  This test makes 32k - 1 bytes of data available
2231ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// on the socket for reading. It then verifies that it has read all
2232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the available data without yielding.
2233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
2238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
2241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2243ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2244ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // (-spdy_data_frame_size).
2245ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int kPayloadSize =
2247ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestDataStream test_stream;
2249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  char* payload_data = payload->data();
2251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test_stream.GetBytes(payload_data, kPayloadSize);
2252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> partial_data_frame(
2254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> finish_data_frame(
2256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // bytes.
2262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp1, 1),
2264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*partial_data_frame, 2),
2265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 6)  // EOF
2269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create SpdySession and SpdyStream and send the request.
2272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
2273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
2274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
2275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
2276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
2282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2283ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
22847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url1("http://www.google.com");
2287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
2288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, MEDIUM, BoundNetLog());
2290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
2291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
2292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
2294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers1(
2296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2298ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2300ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // post a task.
2302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Run until 1st read.
2305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, delegate1.stream_id());
2306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
2307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, delegate1.stream_id());
2308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, observer.executed_count());
2309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2310ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read all the data and verify SpdySession::DoReadLoop has not
2311ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // posted a task.
2312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(4);
2313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
2314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify task observer's executed_count is zero, which indicates DoRead read
2316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // all the available data.
2317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, observer.executed_count());
23182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
23192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
23202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
23212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2322ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop yields while reading the
2323ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// data. This test makes 32k + 1 bytes of data available on the socket
2324ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// for reading. It then verifies that DoRead has yielded even though
2325ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// there is data available for it to read (i.e, socket()->Read didn't
2326ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// return ERR_IO_PENDING during socket reads).
23277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
23282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
23297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
23302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
233190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
233290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
23332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
23342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req1, 0),
23352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
23362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2337ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2338ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // (-spdy_data_frame_size).
2339ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
23402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kPayloadSize =
2341ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
23422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestDataStream test_stream;
23432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
23442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char* payload_data = payload->data();
23452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test_stream.GetBytes(payload_data, kPayloadSize);
23462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> partial_data_frame(
23482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
23492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> finish_data_frame(
23502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
23512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
23532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
23552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
23562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp1, 1),
23572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 2),
23582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
23592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
23602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
23612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
23622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(ASYNC, 0, 7)  // EOF
23632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
23642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
23662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
23672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
23682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
23692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
23702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
23712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
23732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
23742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
23762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2377ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
23787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
23792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url1("http://www.google.com");
2381a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
238290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
238390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, MEDIUM, BoundNetLog());
23842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
23852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
2386a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2387a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
23882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
238990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
2390b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
239190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2392ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
23932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2394ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2395ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // task.
2396ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
23972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until 1st read.
2399a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
24002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(2);
2401a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(1u, delegate1.stream_id());
24022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, observer.executed_count());
24032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2404ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read all the data and verify SpdySession::DoReadLoop has posted a
2405ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // task.
24062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(6);
2407a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
24082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify task observer's executed_count is 1, which indicates DoRead has
24102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // posted only one task and thus yielded though there is data available for it
24112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to read.
24122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, observer.executed_count());
24132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
24142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
24152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
24162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2417ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop() tests interactions of yielding
2418ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// + async, by doing the following MockReads.
24192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
24202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
24212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
24222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
2423ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// The above reads 26K synchronously. Since that is less that 32K, we
2424ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// will attempt to read again. However, that DoRead() will return
2425ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// ERR_IO_PENDING (because of async read), so DoReadLoop() will
2426ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// yield. When we come back, DoRead() will read the results from the
2427ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// async read, and rest of the data synchronously.
24287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
24292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
24307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
24312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
243290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
243390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
24342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
24352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req1, 0),
24362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
24372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2438ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2439ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // (-spdy_data_frame_size).
2440ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
24412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestDataStream test_stream;
24422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kEightKPayloadSize =
2443ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
24442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> eightk_payload(
24452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new net::IOBuffer(kEightKPayloadSize));
24462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char* eightk_payload_data = eightk_payload->data();
24472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
24482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Build buffer of 2k size.
24502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestDataStream test_stream2;
24512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
24522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> twok_payload(
24532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new net::IOBuffer(kTwoKPayloadSize));
24542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char* twok_payload_data = twok_payload->data();
24552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
24562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
24582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
24592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
24602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
24612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
24622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1, "h", 1, DATA_FLAG_FIN));
24632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
24652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
24672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp1, 1),
24682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 2),
24692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
24702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
24712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
24722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 6, ASYNC),
24732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
24742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
24752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
24762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
24772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
24782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(ASYNC, 0, 12)  // EOF
24792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
24802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
24822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
24832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
24842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
24852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
24862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
24872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
24892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
24902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
24922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2493ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
24947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
24952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url1("http://www.google.com");
2497a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
249890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
249990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, MEDIUM, BoundNetLog());
25002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
25012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
2502a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2503a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
25042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
250590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
2506b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
250790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2508ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
25092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2510ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2511ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // posting of tasks.
2512ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
25132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until 1st read.
2515a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
25162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(2);
2517a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(1u, delegate1.stream_id());
25182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, observer.executed_count());
25192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2520ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read all the data and verify SpdySession::DoReadLoop has posted a
2521ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // task.
25222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(12);
2523a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
25242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify task observer's executed_count is 1, which indicates DoRead has
25262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // posted only one task and thus yielded though there is data available for
25272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // it to read.
25282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, observer.executed_count());
25292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
25302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
25312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
25322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2533ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2534ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// nothing blows up.
2535ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
25362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
25377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
25382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
253990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
254090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
25412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
25422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req1, 0),
25432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
25442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
25467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
254790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
25482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
25502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp1, 1),
25512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*body1, 2),
25522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*goaway, 3),
25532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
25542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
25562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
25572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
25582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
25592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
25602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
25612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
25632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
25642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
25662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2567ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
25687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
25692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url1("http://www.google.com");
2571a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
257290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
257390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, MEDIUM, BoundNetLog());
257490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
257590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
25762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
25772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
25782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
257990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
2580b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
258190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2582ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
25832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until 1st read.
25852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
25862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
25872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, spdy_stream1->stream_id());
25882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until GoAway.
2590ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(3);
2591a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
25922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
25932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
2594ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
25952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
25962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Within this framework, a SpdySession should be initialized with
25987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// flow control disabled for protocol version 2, with flow control
25997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// enabled only for streams for protocol version 3, and with flow
26007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// control enabled for streams and sessions for higher versions.
26017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ProtocolNegotiation) {
26022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
26032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
26052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
26062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(SYNCHRONOUS, 0, 0)  // EOF
26072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
26082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
26092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
26102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
26112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
2613ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
26147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_);
26152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(spdy_util_.spdy_version(),
26177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            session->buffered_spdy_framer_->protocol_version());
26187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() == kProtoSPDY2) {
26197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state());
26207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_send_window_size_);
26217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_recv_window_size_);
26227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else if (GetParam() == kProtoSPDY3) {
26237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
26247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_send_window_size_);
26257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_recv_window_size_);
26267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else {
26277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
26287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              session->flow_control_state());
26297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(kSpdySessionInitialWindowSize,
26307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              session->session_send_window_size_);
2631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(kSpdySessionInitialWindowSize,
26327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              session->session_recv_window_size_);
26337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
26342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
26352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
26362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Tests the case of a non-SPDY request closing an idle SPDY session when no
2638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// pointers to the idle session are currently held.
2639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseOneIdleConnection) {
2640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_group(
2641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_pool(
2643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
26442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
26462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
2647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
26482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
2649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
26502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
2651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
2652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
26532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
26552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransportClientSocketPool* pool =
2657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      http_session_->GetTransportSocketPool(
2658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          HttpNetworkSession::NORMAL_SOCKET_POOL);
26592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create an idle SPDY session.
2661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                      kPrivacyModeDisabled);
2663ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session1 =
26647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
26662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Trying to create a new connection should cause the pool to be stalled, and
2668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // post a task asynchronously to try and close the session.
2669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
2670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port2("2.com", 80);
2671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<TransportSocketParams> params2(
2672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false,
2673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                OnHostResolutionCallback()));
2674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
2675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
2676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
2677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              callback2.callback(), pool, BoundNetLog()));
2678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
26792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The socket pool should close the connection asynchronously and establish a
2681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // new connection.
2682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, callback2.WaitForResult());
2683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
2684ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session1 == NULL);
26852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
26862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2687eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Tests the case of a non-SPDY request closing an idle SPDY session when no
2688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// pointers to the idle session are currently held, in the case the SPDY session
2689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// has an alias.
2690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
2691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_group(
2692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_pool(
2694eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
26952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
26972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
2698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
26992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
27002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
27012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
27022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
2703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
2704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
2706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->rules()->AddIPLiteralRule(
2707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "1.com", "192.168.0.2", std::string());
2708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->rules()->AddIPLiteralRule(
2709eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "2.com", "192.168.0.2", std::string());
2710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Not strictly needed.
2711eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->rules()->AddIPLiteralRule(
2712eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "3.com", "192.168.0.3", std::string());
27132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
27152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransportClientSocketPool* pool =
2717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      http_session_->GetTransportSocketPool(
2718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          HttpNetworkSession::NORMAL_SOCKET_POOL);
27192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create an idle SPDY session.
2721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
2722eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                      kPrivacyModeDisabled);
2723ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session1 =
27247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2725eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
27262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2727eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set up an alias for the idle SPDY session, increasing its ref count to 2.
2728eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
2729eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                      kPrivacyModeDisabled);
2730eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostResolver::RequestInfo info(key2.host_port_pair());
2731eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddressList addresses;
2732eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Pre-populate the DNS cache, since a synchronous resolution is required in
2733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // order to create the alias.
2734eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->Resolve(
2735eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      info, &addresses, CompletionCallback(), NULL, BoundNetLog());
2736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Get a session for |key2|, which should return the session created earlier.
2737ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session2 =
27387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
2739eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(session1.get(), session2.get());
2740eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
27412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2742eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Trying to create a new connection should cause the pool to be stalled, and
2743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // post a task asynchronously to try and close the session.
2744eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback3;
2745eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port3("3.com", 80);
2746eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<TransportSocketParams> params3(
2747eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new TransportSocketParams(host_port3, DEFAULT_PRIORITY, false, false,
2748eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                OnHostResolutionCallback()));
2749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
2750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
2751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
2752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              callback3.callback(), pool, BoundNetLog()));
2753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
27547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2755eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The socket pool should close the connection asynchronously and establish a
2756eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // new connection.
2757eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, callback3.WaitForResult());
2758eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
2759ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session1 == NULL);
2760ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session2 == NULL);
2761eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2762eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2763eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Tests that a non-SPDY request can't close a SPDY session that's currently in
2764eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// use.
2765eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseOneIdleConnectionFailsWhenSessionInUse) {
2766eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_group(
2767eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2768eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_pool(
2769eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
2770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2773eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
2776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> cancel1(
2778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 1),
2781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*cancel1, 1),
2782eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads),
2784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     writes, arraysize(writes));
2785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
2786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
2787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
2789eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2790eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransportClientSocketPool* pool =
2791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      http_session_->GetTransportSocketPool(
2792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          HttpNetworkSession::NORMAL_SOCKET_POOL);
2793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create a SPDY session.
2795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url1("http://www.google.com");
2796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key1(HostPortPair(url1.host(), 80),
2797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                      ProxyServer::Direct(), kPrivacyModeDisabled);
2798ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session1 =
27997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
2800eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
2801eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2802eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create a stream using the session, and send a request.
2803eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2804eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback1;
2805eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
2806eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2807eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session1, url1, DEFAULT_PRIORITY,
2808eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                BoundNetLog());
2809eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get());
2810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2811eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
2812eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2813eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers1(
2814eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2815eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
2816eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            spdy_stream1->SendRequestHeaders(
2817eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                headers1.Pass(), NO_MORE_DATA_TO_SEND));
2818ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2819eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2820eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
2821eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2822eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Trying to create a new connection should cause the pool to be stalled, and
2823eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // post a task asynchronously to try and close the session.
2824eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
2825eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port2("2.com", 80);
2826eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<TransportSocketParams> params2(
2827eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new TransportSocketParams(host_port2, DEFAULT_PRIORITY, false, false,
2828eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                OnHostResolutionCallback()));
2829eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
2830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
2831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
2832eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              callback2.callback(), pool, BoundNetLog()));
2833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
2834eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2835eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Running the message loop should cause the socket pool to ask the SPDY
2836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // session to close an idle socket, but since the socket is in use, nothing
2837eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // happens.
2838eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::RunLoop().RunUntilIdle();
2839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
2840eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(callback2.have_result());
2841eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2842eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Cancelling the request should still not release the session's socket,
2843eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // since the session is still kept alive by the SpdySessionPool.
2844eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get());
2845eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->Cancel();
2846eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::RunLoop().RunUntilIdle();
2847eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
2848eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(callback2.have_result());
2849ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session1 != NULL);
2850eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2851eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2852eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that SpdySessionKey and therefore SpdySession is different when
2853eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// privacy mode is enabled or disabled.
2854eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
2855eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
2856eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2857eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port_pair("www.google.com", 443);
2858eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
2859eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     kPrivacyModeEnabled);
2860eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
2861eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     kPrivacyModeDisabled);
2862eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
28637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
28647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add SpdySession with PrivacyMode Enabled to the pool.
2867ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session_privacy_enabled =
28687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
2869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
28707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
28717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2872eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add SpdySession with PrivacyMode Disabled to the pool.
2874ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session_privacy_disabled =
28757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
2876eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
28777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
28787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2879eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
28807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
28817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
28827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2883eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
28847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
28857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
28867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
2887eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2888eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2889bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Delegate that creates another stream when its stream is closed.
2890bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochclass StreamCreatingDelegate : public test::StreamDelegateDoNothing {
2891bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch public:
2892bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
2893bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                         const base::WeakPtr<SpdySession>& session)
2894bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      : StreamDelegateDoNothing(stream),
2895bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        session_(session) {}
2896bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2897bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual ~StreamCreatingDelegate() {}
2898bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2899bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual void OnClose(int status) OVERRIDE {
2900bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    GURL url("http://www.google.com");
2901bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    ignore_result(
2902bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2903bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                  session_, url, MEDIUM, BoundNetLog()));
2904bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  }
2905bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2906bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch private:
2907bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  const base::WeakPtr<SpdySession> session_;
2908bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch};
2909bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2910bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Create another stream in response to a stream being reset. Nothing
2911bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// should blow up. This is a regression test for
2912bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// http://crbug.com/263690 .
2913bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
2914bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
2915bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2916bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2917bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2918bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyFrame> req(
2919bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2920bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockWrite writes[] = {
2921bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    CreateMockWrite(*req, 0),
2922bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  };
2923bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2924bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyFrame> rst(
2925bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
2926bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockRead reads[] = {
2927bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    CreateMockRead(*rst, 1),
2928bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    MockRead(ASYNC, 0, 2)  // EOF
2929bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  };
2930bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
2931bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                               writes, arraysize(writes));
2932bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.set_connect_data(connect_data);
2933bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2934bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2935bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2936bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2937bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2938bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  CreateDeterministicNetworkSession();
2939bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2940bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdySession> session =
2941bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2942bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2943bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  GURL url("http://www.google.com");
2944bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
2945bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2946bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
2947bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  ASSERT_TRUE(spdy_stream.get() != NULL);
2948bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, spdy_stream->stream_id());
2949bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2950bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  StreamCreatingDelegate delegate(spdy_stream, session);
2951bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->SetDelegate(&delegate);
2952bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2953bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2954bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
2955bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2956bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2957bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2958bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, spdy_stream->stream_id());
2959bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2960bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.RunFor(1);
2961bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2962bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(1u, spdy_stream->stream_id());
2963bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2964bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Cause the stream to be reset, which should cause another stream
2965bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // to be created.
2966bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.RunFor(1);
2967bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2968bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(NULL, spdy_stream.get());
2969bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(delegate.StreamIsClosed());
2970bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, session->num_active_streams());
2971bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(1u, session->num_created_streams());
2972bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
2973bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2974eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The tests below are only for SPDY/3 and above.
2975eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2976eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SendCredentials) {
2977eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY3)
2978eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
2979eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2980eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2981eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2982eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2983eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2984eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SettingsMap settings;
2985eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame(
2986eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(settings));
2987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2988eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*settings_frame),
2989eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads),
2991eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                writes, arraysize(writes));
2992eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
2993eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
2994eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2995eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2996eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ssl.channel_id_sent = true;
2997eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ssl.protocol_negotiated = GetParam();
2998eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
3001eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3002eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const GURL kTestUrl("https://www.foo.com");
3003eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair test_host_port_pair(kTestUrl.host(), 443);
3004eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key(test_host_port_pair, ProxyServer::Direct(),
3005eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     kPrivacyModeDisabled);
3006eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3007ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
30087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateSecureSpdySession(http_session_, key, BoundNetLog());
3009eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3010eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->NeedsCredentials());
3011eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3012ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Flush the read completion task.
3013eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
3014eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
30157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, std::string());
30167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key));
3017eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3018eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3019eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3020eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY3)
3021eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3022eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3023eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3024eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // gets sent.
3025eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SettingsMap new_settings;
3026eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int32 window_size = 1;
3027eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3028eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3029eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3030eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set up the socket so we read a SETTINGS frame that sets
3031eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // INITIAL_WINDOW_SIZE.
3032eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3033eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame(
3034eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(new_settings));
3035eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3036eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*settings_frame, 0),
3037eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 1)  // EOF
3038eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<DeterministicSocketData> data(
3043eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new DeterministicSocketData(reads, arraysize(reads), NULL, 0));
3044eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data->set_connect_data(connect_data);
3045eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(data.get());
3046eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3047eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
3048eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3049eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3050eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3051eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3052ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
30537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3054eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
3055eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3056eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, test_url_, MEDIUM, BoundNetLog());
3057eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
3058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback1;
3059eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3060eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data->RunFor(1);  // Process the SETTINGS frame, but not the EOF
3062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
3063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3064eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3065eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3066eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Release the first one, this will allow the second to be created.
3067eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->Cancel();
3068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
3069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
3071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, test_url_, MEDIUM, BoundNetLog());
3073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream2.get() != NULL);
3074eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3075eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->Cancel();
3076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
3077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The tests below are only for SPDY/3.1 and above.
3080eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3081eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// SpdySession::{Increase,Decrease}RecvWindowSize should properly
3082eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// adjust the session receive window size for SPDY 3.1 and higher. In
3083eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// addition, SpdySession::IncreaseRecvWindowSize should trigger
3084eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// sending a WINDOW_UPDATE frame for a large enough delta.
3085eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3086eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
3087eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3088eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3089eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int32 delta_window_size = 100;
3092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3093eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 1)  // EOF
3096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update(
3098eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(
3099eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kSessionFlowControlStreamId,
3100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kSpdySessionInitialWindowSize + delta_window_size));
3101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
3102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*window_update, 0),
3103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
3105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
3106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
3110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
31147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
3117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->IncreaseRecvWindowSize(delta_window_size);
3122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->session_recv_window_size_);
3124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Should trigger sending a WINDOW_UPDATE frame.
3127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize);
3128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size +
3129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            kSpdySessionInitialWindowSize,
3130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->session_recv_window_size_);
3131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
3134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3135ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3136ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->in_io_loop_ = true;
3137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->DecreaseRecvWindowSize(
3138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSpdySessionInitialWindowSize + delta_window_size +
3139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSpdySessionInitialWindowSize);
3140ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->in_io_loop_ = false;
3141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_recv_window_size_);
3142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// SpdySession::{Increase,Decrease}SendWindowSize should properly
3146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// adjust the session send window size when the "enable_spdy_31" flag
3147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// is set.
3148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, AdjustSendWindowSize) {
3149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
3150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, 0, 0)  // EOF
3157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
3161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
3163ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
31647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_);
3165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
3167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int32 delta_window_size = 100;
3169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->IncreaseSendWindowSize(delta_window_size);
3173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->session_send_window_size_);
3175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->DecreaseSendWindowSize(delta_window_size);
3177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Incoming data for an inactive stream should not cause the session
3181c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// receive window size to decrease, but it should cause the unacked
3182c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// bytes to increase.
3183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
3185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 0),
3193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 1)  // EOF
3194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
3200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3203ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
32047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
3207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3211ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
3212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3214c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3215ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
3216ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
3217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// A delegate that drops any received data.
3220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
3222a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           base::StringPiece data)
322490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      : StreamDelegateSendImmediate(stream, data) {}
3225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~DropReceivedDataDelegate() {}
3227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Drop any received data.
3229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) OVERRIDE {}
3230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
3231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Send data back and forth but use a delegate that drops its received
3233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// data. The receive window should still increase to its original
3234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// value, i.e. we shouldn't "leak" receive window bytes.
32357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
32367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
32377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
3238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
32397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
3240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int32 msg_data_size = 100;
3242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string msg_data(msg_data_size, 'a');
3243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
3245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
32477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
32487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> msg(
32507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
32517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
3252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockWrite writes[] = {
3253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*msg, 2),
3255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
32577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> echo(
32597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
32607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
3261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> window_update(
326290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyWindowUpdate(
3263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          kSessionFlowControlStreamId, msg_data_size));
3264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockRead reads[] = {
3265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1),
3266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*echo, 3),
3267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 4)  // EOF
3268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
3271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
3272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               writes, arraysize(writes));
3273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.set_connect_data(connect_data);
3274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
3275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
3278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CreateDeterministicNetworkSession();
3281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3282ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
32837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL url(kStreamUrl);
3286a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
328790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
328890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
3289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
3290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0u, stream->stream_id());
3291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DropReceivedDataDelegate delegate(stream, msg_data);
3293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->SetDelegate(&delegate);
3294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
329590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3296b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
329790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
329890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3299ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
3300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(4);
3305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
3307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
3308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->Close();
3313a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, stream.get());
3314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(OK, delegate.WaitForClose());
3316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Send data back and forth but close the stream before its data frame
3322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// can be written to the socket. The send window should then increase
3323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// to its original value, i.e. we shouldn't "leak" send window bytes.
33247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
33257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
33267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
3327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
33287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
3329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int32 msg_data_size = 100;
3331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string msg_data(msg_data_size, 'a');
3332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
3334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
33367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
33377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockWrite writes[] = {
3339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
33427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockRead reads[] = {
3344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1),
3345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 2)  // EOF
3346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
3349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
3350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               writes, arraysize(writes));
3351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.set_connect_data(connect_data);
3352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
3353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
3356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CreateDeterministicNetworkSession();
3359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3360ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
33617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL url(kStreamUrl);
3364a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
336590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
336690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
3367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
3368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0u, stream->stream_id());
3369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
337090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(stream, msg_data);
3371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->SetDelegate(&delegate);
3372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
337390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3374b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
337590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
337690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3377ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
3378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
3382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.RunFor(1);
3386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
3388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
3389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            session->session_send_window_size_);
3392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Closing the stream should increase the session's send window.
3394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->Close();
3395a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, stream.get());
3396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(OK, delegate.WaitForClose());
3400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
34022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Send data back and forth; the send and receive windows should
34032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// change appropriately.
34047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
34057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
34067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
34072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
34092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int32 msg_data_size = 100;
34112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string msg_data(msg_data_size, 'a');
34122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
34142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
34167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
34177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
34182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> msg(
34197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
34207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
34212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
3422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*msg, 2),
34242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
34252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
34272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> echo(
34287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
34297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
34302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> window_update(
343190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyWindowUpdate(
34322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kSessionFlowControlStreamId, msg_data_size));
34332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1),
3435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*echo, 3),
3436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update, 4),
3437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 5)  // EOF
34382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
34392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
34412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
34422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
34432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
34442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
34452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
34462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
34482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
34492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
34512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
34537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
34542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
3456a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
345790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
345890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
34592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
34602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, stream->stream_id());
34612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
346290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(stream, msg_data);
34632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->SetDelegate(&delegate);
34642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
346590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3466b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
346790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
346890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3469ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
34702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
34732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
34742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
34762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
34792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
34802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
34822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
34842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_send_window_size_);
3485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
34862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
34872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
34892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
34912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_send_window_size_);
3492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
34932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
34942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
34962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
34982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_send_window_size_);
3499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
35002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_recv_window_size_);
35012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
35022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
35042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
35072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_recv_window_size_);
35082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
35092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
35112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
35122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data, delegate.TakeReceivedData());
35142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Draining the delegate's read queue should increase the session's
3516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // receive window.
3517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
35192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
35202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->Close();
3522a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, stream.get());
35232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, delegate.WaitForClose());
3525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
35292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
35302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Given a stall function and an unstall function, runs a test to make
3532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// sure that a stream resumes after unstall.
35337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void SpdySessionTest::RunResumeAfterUnstallTest(
35347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
353590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
353690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        unstall_function) {
35372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
35382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
35392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
35412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
35437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
35447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
354590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> body(
35467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
35472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
3548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body, 1),
35502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
35512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(
35537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
35542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> echo(
35557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
35562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 2),
3558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 3), // EOF
35592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
35602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
35622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
35632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
35642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
35652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
35672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
3569ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
35707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
35712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
35722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->flow_control_state());
35732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3574a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
357590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
357690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
35772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
35782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3579a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
35802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->SetDelegate(&delegate);
35812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3582ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream->HasUrlFromHeaders());
358390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(stream->send_stalled_by_flow_control());
35842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
358590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3586b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
358790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
358890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3589ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
3590ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
35912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  stall_function.Run(session.get(), stream.get());
35932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
35952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream->send_stalled_by_flow_control());
35972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
35992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
36002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream->send_stalled_by_flow_control());
36012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
36022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(3);
36032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
36042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
36052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
36062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate.send_headers_completed());
36072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
36082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version"));
360990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate.TakeReceivedData());
361090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
36112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
36122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Run the resume-after-unstall test with all possible stall and
3614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// unstall sequences.
3615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
36177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
36187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
36197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
36207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
36217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallSessionOnly,
3622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
36237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallSessionOnly,
3624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
3625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Equivalent to
36287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
36297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
36307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
36317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
36327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
36337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
36347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallStreamOnly,
3635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
36367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallStreamOnly,
3637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
3638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
36417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
36427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
36437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
36447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
36457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallSessionStream,
3646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
36477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallSessionStream,
3648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
3649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
36527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
36537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
36547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
36557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
36567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallStreamSession,
3657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
36587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallSessionStream,
3659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
3660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
36637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
36647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
36657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
36667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
36677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallStreamSession,
3668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
36697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallStreamSession,
3670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
3671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
36747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
36757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
36767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
36777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
36787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallSessionStream,
3679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
36807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallStreamSession,
3681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
3682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Cause a stall by reducing the flow control send window to 0. The
36852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// streams should resume in priority order when that window is then
36862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// increased.
36877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
36887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
36897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
36907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
36912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
36922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
36932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
36942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
36952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
36962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
36977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
36987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
36992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
37007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
37017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
370290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> body1(
37037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
370490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> body2(
37057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
37062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
3707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
3708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
3709eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body2, 2),
3710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body1, 3),
37112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
37122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
37147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
37152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp1, 4),
3717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 5),
3718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 6), // EOF
37192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
37202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
37222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
37232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
37242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
37252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
37272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
3729ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
37307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
37312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
37322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->flow_control_state());
37332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3734a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream1 =
373590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
373690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
37372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream1.get() != NULL);
37382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3739a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
37402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream1->SetDelegate(&delegate1);
37412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3742ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream1->HasUrlFromHeaders());
37432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3744a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream2 =
374590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
374690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
37472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream2.get() != NULL);
37482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3749a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
37502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream2->SetDelegate(&delegate2);
37512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3752ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream2->HasUrlFromHeaders());
37532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
37552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
37562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3757868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StallSessionSend(session.get());
37582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
375990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
376090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
376190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
376290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
3763ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream1->HasUrlFromHeaders());
3764ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
37652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3766eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
376790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1u, stream1->stream_id());
37682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
376990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
377090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
377190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
377290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
377390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
3774ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
3775ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
377690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
377790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
377890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(3u, stream2->stream_id());
37792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
37802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should unstall only stream2.
3782868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UnstallSessionSend(session.get(), kBodyDataSize);
37832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
37852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
37862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
378790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
37882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
37902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
37912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should then unstall stream1.
3793868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UnstallSessionSend(session.get(), kBodyDataSize);
37942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
3796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
37972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3798eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(4);
37992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
38012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
38022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate1.send_headers_completed());
3804eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
3805eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version"));
3806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
38072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate2.send_headers_completed());
38092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
38102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version"));
381190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
38122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
381390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
381490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
38152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3816eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Delegate that closes a given stream after sending its body.
3817eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass StreamClosingDelegate : public test::StreamDelegateWithBody {
3818eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
3819eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
3820eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        base::StringPiece data)
3821eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : StreamDelegateWithBody(stream, data) {}
3822eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3823eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual ~StreamClosingDelegate() {}
3824eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3825eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
3826eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    stream_to_close_ = stream_to_close;
3827eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
3828eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3829eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnDataSent() OVERRIDE {
3830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    test::StreamDelegateWithBody::OnDataSent();
3831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (stream_to_close_.get()) {
3832eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream_to_close_->Close();
3833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_EQ(NULL, stream_to_close_.get());
3834eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
3835eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
3836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3837eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
3838eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream_to_close_;
3839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
3840eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
38412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Cause a stall by reducing the flow control send window to
3842eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 0. Unstalling the session should properly handle deleted streams.
3843eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
38447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
38457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
38467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
38472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
38482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
38492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
38512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
38537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
38547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
38552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
38567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
38577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
3858eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req3(
3859eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPost(
3860eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
3861eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(
3862eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
38632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
3864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
3865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
3866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req3, 2),
3867eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body2, 3),
38682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
38692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3870eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
38712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3872eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 4),
3873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 5), // EOF
38742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
38752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
38772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
38782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
38792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
38802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
38822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
3884ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
38857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
38862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
38872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->flow_control_state());
38882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3889a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream1 =
389090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
389190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
38922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream1.get() != NULL);
38932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
389490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
38952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream1->SetDelegate(&delegate1);
38962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3897ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream1->HasUrlFromHeaders());
38982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3899a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream2 =
390090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
390190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
39022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream2.get() != NULL);
39032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3904eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
39052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream2->SetDelegate(&delegate2);
39062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3907ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream2->HasUrlFromHeaders());
39082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3909eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream3 =
3910eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3911eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url, LOWEST, BoundNetLog());
3912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream3.get() != NULL);
3913eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3914eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
3915eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream3->SetDelegate(&delegate3);
3916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3917ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream3->HasUrlFromHeaders());
3918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
39192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
39202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3921eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream3->send_stalled_by_flow_control());
39222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3923868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StallSessionSend(session.get());
39242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
392690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
392790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
392890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
3929ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream1->HasUrlFromHeaders());
3930ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
39312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3932eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
393390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1u, stream1->stream_id());
39342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
393590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
393690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
393790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
393890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
393990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
3940ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
3941ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
394290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
394390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
394490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(3u, stream2->stream_id());
39452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
39462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3947eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers3(
3948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
3949a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
3950eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
3951ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream3->HasUrlFromHeaders());
3952ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
3953868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3954eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
3955eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(5u, stream3->stream_id());
3956eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream3->send_stalled_by_flow_control());
3957868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3958eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamId stream_id1 = stream1->stream_id();
3959eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamId stream_id2 = stream2->stream_id();
3960eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamId stream_id3 = stream3->stream_id();
3961868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3962eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Close stream1 preemptively.
3963eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
3964eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream1.get());
3965868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3966eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->IsStreamActive(stream_id1));
3967eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->IsStreamActive(stream_id2));
3968eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->IsStreamActive(stream_id3));
39697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3970eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Unstall stream2, which should then close stream3.
3971eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  delegate2.set_stream_to_close(stream3);
3972eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UnstallSessionSend(session.get(), kBodyDataSize);
3973a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
3974eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
3975eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream3.get());
3976a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
3977eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
3978eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->IsStreamActive(stream_id1));
3979eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->IsStreamActive(stream_id2));
3980eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->IsStreamActive(stream_id3));
3981a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
3982eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
3983eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream2.get());
3984a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
3985eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
3986eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
3987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, delegate3.WaitForClose());
3988a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
3989eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.send_headers_completed());
3990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
3991a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
3992eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.send_headers_completed());
3993eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
3994eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version"));
3995eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
3996a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
3997eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate3.send_headers_completed());
3998eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
3999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
4001a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
4002a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4003eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Cause a stall by reducing the flow control send window to
4004eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 0. Unstalling the session should properly handle the session itself
4005eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// being closed.
4006eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4007eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
40087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
40097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4010eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kStreamUrl[] = "http://www.google.com/";
4011eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url(kStreamUrl);
4012eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4013eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
4014a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
401590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
4016eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPost(
4017eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4018eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
4019eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPost(
4020eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4021eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(
4022eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4023a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  MockWrite writes[] = {
4024eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
4025eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
4026a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  };
4027eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4028eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
4029eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 2), // EOF
4030eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4031eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4032eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
4033eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
4034eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
4035a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  data.set_connect_data(connect_data);
4036a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4037eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4038a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
4040ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
40417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4043eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
4044a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4045eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream1 =
4046eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4047eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url, LOWEST, BoundNetLog());
4048eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream1.get() != NULL);
4049a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4050eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4051eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream1->SetDelegate(&delegate1);
4052a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4053ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream1->HasUrlFromHeaders());
4054eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4055eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream2 =
405690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4057eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url, LOWEST, BoundNetLog());
4058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream2.get() != NULL);
4059a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4060eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream2->SetDelegate(&delegate2);
4062a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4063ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream2->HasUrlFromHeaders());
4064a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4065eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4066eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4067a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StallSessionSend(session.get());
4069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers1(
4071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4072a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
4073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4074ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream1->HasUrlFromHeaders());
4075ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4076a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
4078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, stream1->stream_id());
4079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4080a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4081eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
4082eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4083eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
4084eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4085ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
4086ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4087a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4088eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
4089eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, stream2->stream_id());
4090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
409190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
409390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Unstall stream1.
4095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UnstallSessionSend(session.get(), kBodyDataSize);
409690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Close the session (since we can't do it from within the delegate
4098eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // method, since it's in the stream's loop).
40997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
410190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
41027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
410390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
410690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.send_headers_completed());
4108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
410990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.send_headers_completed());
4111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
411290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
411490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
411590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
41165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
4117