spdy_session_unittest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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(),
110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch             PRIVACY_MODE_DISABLED) {
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,
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    testing::Values(kProtoDeprecatedSPDY2,
185a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
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
192effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::WeakPtr<SpdySession> session = TryCreateFakeSpdySessionExpectingFailure(
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_session_pool_, key_, ERR_CONNECTION_CLOSED);
194effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_TRUE(session);
195effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Flush the read.
196effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::RunLoop().RunUntilIdle();
197effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_FALSE(session);
198ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
199ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace {
2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// A helper class that vends a callback that, when fired, destroys a
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// given SpdyStreamRequest.
2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)class StreamRequestDestroyingCallback : public TestCompletionCallbackBase {
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public:
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StreamRequestDestroyingCallback() {}
2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  virtual ~StreamRequestDestroyingCallback() {}
2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void SetRequestToDestroy(scoped_ptr<SpdyStreamRequest> request) {
2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    request_ = request.Pass();
2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  CompletionCallback MakeCallback() {
2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return base::Bind(&StreamRequestDestroyingCallback::OnComplete,
2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                      base::Unretained(this));
2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private:
2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void OnComplete(int result) {
2213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    request_.reset();
2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    SetResult(result);
2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<SpdyStreamRequest> request_;
2263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
2273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace
2293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Request kInitialMaxConcurrentStreams streams.  Request two more
2313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// streams, but have the callback for one destroy the second stream
2323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// request. Close the session. Nothing should blow up. This is a
2333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// regression test for http://crbug.com/250841 .
2343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
2353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
2363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  MockRead reads[] = {MockRead(ASYNC, 0, 0), };
2383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
2403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
2413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  data.set_connect_data(connect_data);
2423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  CreateDeterministicNetworkSession();
2453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::WeakPtr<SpdySession> session =
2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Create the maximum number of concurrent streams.
2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
2513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
2523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog());
2533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  SpdyStreamRequest request1;
2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<SpdyStreamRequest> request2(new SpdyStreamRequest);
2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StreamRequestDestroyingCallback callback1;
2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING,
2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM,
2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  session,
2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  test_url_,
2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  MEDIUM,
2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  BoundNetLog(),
2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  callback1.MakeCallback()));
2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // |callback2| is never called.
2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  TestCompletionCallback callback2;
2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING,
2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM,
2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   session,
2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   test_url_,
2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   MEDIUM,
2753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   BoundNetLog(),
2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   callback2.callback()));
2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  callback1.SetRequestToDestroy(request2.Pass());
2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// A session receiving a GOAWAY frame with no active streams should close.
286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
291ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 0),
293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
294ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
298ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
299ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
300ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
304ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
305ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
306ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
307ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the GOAWAY frame.
308ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
309ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
311ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
312ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
313ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
314ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// A session receiving a GOAWAY frame immediately with no active
315ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// streams should then close.
316ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
317ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
319ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
320ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
321ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
322ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 0, SYNCHRONOUS),
323ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
324ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
325ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
326ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
327ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
328ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
329ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.StopAfter(1);
331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
332effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::WeakPtr<SpdySession> session =
333effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      TryCreateInsecureSpdySessionExpectingFailure(
334effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
335effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::RunLoop().RunUntilIdle();
336ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
337effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_FALSE(session);
338ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
339ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
340ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
341ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// A session receiving a GOAWAY frame with active streams should close
342ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// when the last active stream is closed.
343ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CreateMockRead(*goaway, 2),
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MockRead(ASYNC, 0, 3)  // EOF
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockWrite writes[] = {
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CreateMockWrite(*req1, 0),
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CreateMockWrite(*req2, 1),
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               writes, arraysize(writes));
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CreateDeterministicNetworkSession();
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
3687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
373a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
379a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream2 =
38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateDoNothing delegate2(spdy_stream2);
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream2->SetDelegate(&delegate2);
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
3877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
392ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.RunFor(2);
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(1u, spdy_stream1->stream_id());
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(3u, spdy_stream2->stream_id());
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Read and process the GOAWAY frame.
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.RunFor(1);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(session->IsStreamActive(3));
407ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
408ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(session->IsGoingAway());
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
412ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Should close the session.
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  spdy_stream1->Close();
414a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
417ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
418ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
420ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Have a session receive two GOAWAY frames, with the last one causing
421ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the last active stream to be closed. The session should then be
422ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// closed after the second GOAWAY frame.
423ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayTwice) {
424ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
425ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
426ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
427ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
428ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
429ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
430ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway1, 2),
431ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway2, 3),
432ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 4)  // 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  CreateDeterministicNetworkSession();
448ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
449ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
450ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
451ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
453ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
455ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
456ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
457ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
458ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
459ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream1->SetDelegate(&delegate1);
460ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
461ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
462ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
463ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
464ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate2(spdy_stream2);
465ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream2->SetDelegate(&delegate2);
466ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
467ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
468ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
469ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
470ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
471ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
472ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
473ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
474ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
475ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
476ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(2);
477ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
478ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(1u, spdy_stream1->stream_id());
479ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(3u, spdy_stream2->stream_id());
480ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
481ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
482ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
483ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the first GOAWAY frame.
484ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
485ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
486ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
487ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
488ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(session->IsStreamActive(3));
489a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream2.get());
490ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(session->IsGoingAway());
492ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
493ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the second GOAWAY frame, which should close the
494ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // session.
495ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
497ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
498ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
499ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
500ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Have a session with active streams receive a GOAWAY frame and then
501ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// close it. It should handle the close properly (i.e., not try to
502ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// make itself unavailable in its pool twice).
503ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
504ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
505ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
506ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
507ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
508ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
509ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 2),
510ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 3)  // EOF
511ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
512ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req1(
513ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
514ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req2(
515ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
516ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockWrite writes[] = {
517ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req1, 0),
518ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req2, 1),
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  CreateDeterministicNetworkSession();
526ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
527ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
528ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
529ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
530ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
531ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
533ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
534ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
535ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
536ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
537ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream1->SetDelegate(&delegate1);
538ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
539ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
540ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
541ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
542ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate2(spdy_stream2);
543ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream2->SetDelegate(&delegate2);
544ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
545ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
546ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
547ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(new SpdyHeaderBlock(*headers));
548ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
549ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
550ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
551ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
552ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
553ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
554ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(2);
555ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
556ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(1u, spdy_stream1->stream_id());
557ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(3u, spdy_stream2->stream_id());
558ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
559ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
560ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
561ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the GOAWAY frame.
562ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
563ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
564ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
565ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
566ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(session->IsStreamActive(3));
567ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
568ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
569cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(session->IsGoingAway());
570ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
571ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
572ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
573cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
574cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
575ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
576ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
577ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
57846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Process a joint read buffer which causes the session to begin draining, and
57946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// then processes a GOAWAY. The session should gracefully drain. Regression test
58046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// for crbug.com/379469
58146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_P(SpdySessionTest, GoAwayWhileDraining) {
58246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
58346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
58446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
58546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
58646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  MockWrite writes[] = {
58746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      CreateMockWrite(*req, 0),
58846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  };
58946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
59046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
59146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
59246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
59346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  size_t joint_size = goaway->size() * 2 + body->size();
59446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
59546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Compose interleaved |goaway| and |body| frames into a single read.
59646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<char[]> buffer(new char[joint_size]);
59746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  {
59846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    size_t out = 0;
59946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    memcpy(&buffer[out], goaway->data(), goaway->size());
60046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    out += goaway->size();
60146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    memcpy(&buffer[out], body->data(), body->size());
60246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    out += body->size();
60346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    memcpy(&buffer[out], goaway->data(), goaway->size());
60446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    out += goaway->size();
60546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ASSERT_EQ(out, joint_size);
60646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
60746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SpdyFrame joint_frames(buffer.get(), joint_size, false);
60846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
60946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  MockRead reads[] = {
61046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      CreateMockRead(*resp, 1), CreateMockRead(joint_frames, 2),
61146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      MockRead(ASYNC, 0, 3)  // EOF
61246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  };
61346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
61446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
61546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DeterministicSocketData data(
61646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
61746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  data.set_connect_data(connect_data);
61846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
61946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
62046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  CreateDeterministicNetworkSession();
62146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::WeakPtr<SpdySession> session =
62246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
62346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
62446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  GURL url(kDefaultURL);
62546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
62646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
62746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  test::StreamDelegateDoNothing delegate(spdy_stream);
62846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  spdy_stream->SetDelegate(&delegate);
62946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
63046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
63146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
63246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
63346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
63446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
63546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  data.RunFor(3);
63646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
63746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
63846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Stream and session closed gracefully.
63946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_TRUE(delegate.StreamIsClosed());
64046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_EQ(OK, delegate.WaitForClose());
64146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_EQ(kUploadData, delegate.TakeReceivedData());
64246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_TRUE(session == NULL);
64346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
64446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
645ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Try to create a stream after receiving a GOAWAY frame. It should
646ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// fail.
647ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
648ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
649ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
650ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
651ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
652ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
653ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 1),
654ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 2)  // EOF
655ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
656ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req(
657ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
658ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockWrite writes[] = {
659ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req, 0),
660ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
661ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
662ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               writes, arraysize(writes));
663ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
664ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
665ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
666ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
667ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
668ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
669ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
670ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
671ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
672ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
674ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
675ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
676ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
677ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate(spdy_stream);
678ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SetDelegate(&delegate);
679ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
680ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
681ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
682ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
683ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
684ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
685ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
686ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
687ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(1u, spdy_stream->stream_id());
688ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
689ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
690ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
691ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the GOAWAY frame.
692ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
693ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
694ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
695ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
696ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
697ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdyStreamRequest stream_request;
698ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int rv = stream_request.StartRequest(
699ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog(),
700ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CompletionCallback());
701ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(ERR_FAILED, rv);
702ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
703ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process EOF.
704ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
705ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
706ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
707ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
708ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
709ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Receiving a SYN_STREAM frame after a GOAWAY frame should result in
710ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the stream being refused.
711ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, SynStreamAfterGoAway) {
712ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
713ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
714ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
715ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
716ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame>
7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kDefaultURL));
718ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
719ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*goaway, 1),
720ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*push, 2),
721ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 4)  // EOF
722ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
723ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req(
724ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
725ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> rst(
726ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
727ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockWrite writes[] = {
728ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req, 0),
729ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*rst, 3)
730ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
731ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
732ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               writes, arraysize(writes));
733ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
734ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
735ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
736ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
737ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
738ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
739ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
740ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
741ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
742ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
744ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
745ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
746ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
747ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate(spdy_stream);
748ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SetDelegate(&delegate);
749ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
750ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
751ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
752ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
753ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
754ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
755ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
756ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
757ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(1u, spdy_stream->stream_id());
758ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
759ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
760ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
761ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the GOAWAY frame.
762ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
763ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
764ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
765ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session->IsStreamActive(1));
766ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
767ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read and process the SYN_STREAM frame, the subsequent RST_STREAM,
768ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // and EOF.
769ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(3);
770cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
771ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A session observing a network change with active streams should close
7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// when the last active stream is closed.
7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockRead reads[] = {
7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MockRead(ASYNC, 0, 1)  // EOF
7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockWrite writes[] = {
7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CreateMockWrite(*req1, 0),
7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               writes, arraysize(writes));
7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.set_connect_data(connect_data);
7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CreateDeterministicNetworkSession();
7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::WeakPtr<SpdySession> session =
7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion());
7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream =
8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM, session,
8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                GURL(kDefaultURL), MEDIUM, BoundNetLog());
8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  test::StreamDelegateDoNothing delegate(spdy_stream);
8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  spdy_stream->SetDelegate(&delegate);
8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.RunFor(1);
8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1u, spdy_stream->stream_id());
8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  spdy_session_pool_->OnIPAddressChanged();
8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The SpdySessionPool behavior differs based on how the OSs reacts to
8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // network changes; see comment in SpdySessionPool::OnIPAddressChanged().
8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // For OSs where the TCP connections will close upon relevant network
8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // changes, SpdySessionPool doesn't need to force them to close, so in these
8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // cases verify the session has become unavailable but remains open and the
8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // pre-existing stream is still active.
8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
829cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(session->IsGoingAway());
8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(session->IsStreamActive(1));
8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Should close the session.
8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  spdy_stream->Close();
8355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream.get());
8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
838cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
8395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(session == NULL);
8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ClientPing) {
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.enable_ping = true;
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
847a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
849ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockRead(*read_ping, 1),
850ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 0, 2)  // EOF
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
852a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
854ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*write_ping, 0),
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
856ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
859ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
861ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
863ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
8647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
866a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
86790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
86890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, test_url_, MEDIUM, BoundNetLog());
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
87090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate);
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks before_ping_time = base::TimeTicks::Now();
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session->set_connection_at_risk_of_loss_time(
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TimeDelta::FromSeconds(-1));
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->SendPrefacePingIfNoneInFlight();
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
881ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(2);
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->CheckPingStatus(before_ping_time);
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, session->pings_in_flight());
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1));
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(session->check_ping_status_pending());
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(session->last_activity_time(), before_ping_time);
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
890ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
891ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
892ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
894ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
895ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ServerPing) {
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
902a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*read_ping),
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SYNCHRONOUS, 0, 0)  // EOF
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
907a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*write_ping),
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
918ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
9197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
921a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
92290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
92390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, test_url_, MEDIUM, BoundNetLog());
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
92590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate);
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
928ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Flush the read completion task.
92990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
933ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
934a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
937ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Cause a ping to be sent out while producing a write. The write loop
938ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// should handle this properly, i.e. another DoWriteLoop task should
939ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// not be posted. This is a regression test for
940ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// http://crbug.com/261043 .
941ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, PingAndWriteLoop) {
942ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.enable_ping = true;
943ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.time_func = TheNearFuture;
944ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
945ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
946a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
947ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> req(
948ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
949ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockWrite writes[] = {
950ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*req, 0),
951ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*write_ping, 1),
952ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
953ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
954ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockRead reads[] = {
955ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 2)  // EOF
956ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
957ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
958ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
959ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
960ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
961ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               writes, arraysize(writes));
962ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.set_connect_data(connect_data);
963ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
964ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
965ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
966ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
967ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
968ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
969ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
9705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
971ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
972ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
973ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                session, url, LOWEST, BoundNetLog());
974ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  test::StreamDelegateDoNothing delegate(spdy_stream);
975ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SetDelegate(&delegate);
976ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
977ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
978ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
979ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
980ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
981ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Shift time so that a ping will be sent out.
982ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  g_time_delta = base::TimeDelta::FromSeconds(11);
983ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
984ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(2);
985ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
986ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, "Aborting");
987ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
988ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
989cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
990cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const SpdyStreamId kLastStreamId = 0x7fffffff;
991cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
992cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
993cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Test setup: |stream_hi_water_mark_| and |max_concurrent_streams_| are
994cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // fixed to allow for two stream ID assignments, and three concurrent
995cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // streams. Four streams are started, and two are activated. Verify the
996cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // session goes away, and that the created (but not activated) and
997cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // stalled streams are aborted. Also verify the activated streams complete,
998cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // at which point the session closes.
999cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1000cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
1001cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      NULL, 0, false, kLastStreamId - 2, MEDIUM, true));
1002cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
1003cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, kLastStreamId, MEDIUM, true));
1004cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1005cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockWrite writes[] = {
1006cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
1007cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
1008cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1009cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(
1010cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId - 2));
1011cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(
1012cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, kLastStreamId));
1013cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1014cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> body1(
1015cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
1016cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(
1017cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
1018cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1019cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockRead reads[] = {
1020cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CreateMockRead(*resp1, 2), CreateMockRead(*resp2, 3),
1021cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CreateMockRead(*body1, 4), CreateMockRead(*body2, 5),
1022cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      MockRead(ASYNC, 0, 6)  // EOF
1023cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
1024cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1025cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DeterministicSocketData data(
1026cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
1027cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1028cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1029cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.set_connect_data(connect_data);
1030cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1031cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1032cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CreateDeterministicNetworkSession();
1033cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdySession> session =
1034cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1035cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1036cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fix stream_hi_water_mark_ to allow for two stream activations.
1037cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session->stream_hi_water_mark_ = kLastStreamId - 2;
1038cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fix max_concurrent_streams to allow for three stream creations.
1039cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session->max_concurrent_streams_ = 3;
1040cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1041cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create three streams synchronously, and begin a fourth (which is stalled).
1042cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GURL url(kDefaultURL);
1043cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1044cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1045cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  test::StreamDelegateDoNothing delegate1(stream1);
1046cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream1->SetDelegate(&delegate1);
1047cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1048cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(
1049cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1050cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  test::StreamDelegateDoNothing delegate2(stream2);
1051cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream2->SetDelegate(&delegate2);
1052cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1053cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1054cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1055cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  test::StreamDelegateDoNothing delegate3(stream3);
1056cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream3->SetDelegate(&delegate3);
1057cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1058cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SpdyStreamRequest request4;
1059cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestCompletionCallback callback4;
1060cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
1061cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1062cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  session,
1063cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  url,
1064cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  MEDIUM,
1065cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  BoundNetLog(),
1066cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  callback4.callback()));
1067cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1068cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Streams 1-3 were created. 4th is stalled. No streams are active yet.
1069cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
1070cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(3u, session->num_created_streams());
1071cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1072cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1073cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Activate stream 1. One ID remains available.
1074cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream1->SendRequestHeaders(
1075cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scoped_ptr<SpdyHeaderBlock>(
1076cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          spdy_util_.ConstructGetHeaderBlock(url.spec())),
1077cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      NO_MORE_DATA_TO_SEND);
1078cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.RunFor(1);
1079cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1080cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(kLastStreamId - 2u, stream1->stream_id());
1081cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->num_active_streams());
1082cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(2u, session->num_created_streams());
1083cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1084cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1085cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Activate stream 2. ID space is exhausted.
1086cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream2->SendRequestHeaders(
1087cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scoped_ptr<SpdyHeaderBlock>(
1088cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          spdy_util_.ConstructGetHeaderBlock(url.spec())),
1089cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      NO_MORE_DATA_TO_SEND);
1090cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.RunFor(1);
1091cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1092cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Active streams remain active.
1093cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(kLastStreamId, stream2->stream_id());
1094cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(2u, session->num_active_streams());
1095cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1096cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Session is going away. Created and stalled streams were aborted.
1097cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(SpdySession::STATE_GOING_AWAY, session->availability_state_);
1098cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(ERR_ABORTED, delegate3.WaitForClose());
1099cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(ERR_ABORTED, callback4.WaitForResult());
1100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
1101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Read responses on remaining active streams.
1104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.RunFor(4);
1105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(OK, delegate1.WaitForClose());
1106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(kUploadData, delegate1.TakeReceivedData());
1107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(OK, delegate2.WaitForClose());
1108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(kUploadData, delegate2.TakeReceivedData());
1109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Session was destroyed.
1111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_FALSE(session.get());
1113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Verifies that an unstalled pending stream creation racing with a new stream
1116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// creation doesn't violate the maximum stream concurrency. Regression test for
1117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// crbug.com/373858.
1118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdySessionTest, UnstallRacesWithStreamCreation) {
1119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
1120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockRead reads[] = {
1122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
1124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.set_connect_data(connect_data);
1129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
1130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CreateNetworkSession();
1132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdySession> session =
1133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fix max_concurrent_streams to allow for one open stream.
1136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session->max_concurrent_streams_ = 1;
1137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create two streams: one synchronously, and one which stalls.
1139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GURL url(kDefaultURL);
1140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdyStream> stream1 = CreateStreamSynchronously(
1141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SpdyStreamRequest request2;
1144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestCompletionCallback callback2;
1145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
1146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM,
1147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  session,
1148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  url,
1149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  MEDIUM,
1150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  BoundNetLog(),
1151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  callback2.callback()));
1152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
1154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Cancel the first stream. A callback to unstall the second stream was
1157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // posted. Don't run it yet.
1158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream1->Cancel();
1159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
1161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create a third stream prior to the second stream's callback.
1164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(
1165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
1166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
1168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // NOW run the message loop. The unstalled stream will re-stall itself.
1171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
1173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(MEDIUM));
1174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Cancel the third stream and run the message loop. Verify that the second
1176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // stream creation now completes.
1177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream3->Cancel();
1178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
1181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(0u, session->pending_create_stream_queue_size(MEDIUM));
1182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(OK, callback2.WaitForResult());
1183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
11857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
11862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
11872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.time_func = TheNearFuture;
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyFrame> req(
11905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
11915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyFrame> rst(
11925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
11935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
11945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
11955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NULL, 0, 2, 1, "http://www.google.com/a.dat"));
11965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyFrame> push_a_body(
11975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(2, false));
11985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
11995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NULL, 0, 4, 1, "http://www.google.com/b.dat"));
12005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)};
12015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockRead reads[] = {
12025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CreateMockRead(*push_a, 1), CreateMockRead(*push_a_body, 2),
12035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CreateMockRead(*push_b, 3), MockRead(ASYNC, 0, 5),  // EOF
12045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
12055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeterministicSocketData data(
12065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
12095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.set_connect_data(connect_data);
12105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
12115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CreateDeterministicNetworkSession();
1213ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
12145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Process the principal request, and the first push stream request & body.
12175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
12185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
12195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, BoundNetLog());
12205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  test::StreamDelegateDoNothing delegate(spdy_stream);
12215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  spdy_stream->SetDelegate(&delegate);
12225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
12245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
12255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
12265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.RunFor(3);
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that there is one unclaimed push stream.
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
123190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SpdySession::PushedStreamMap::iterator iter =
1232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      session->unclaimed_pushed_streams_.find(
1233ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          GURL("http://www.google.com/a.dat"));
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (session->flow_control_state_ ==
12375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
12385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Unclaimed push body consumed bytes from the session window.
12395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(kSpdySessionInitialWindowSize - kUploadDataSize,
12405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              session->session_recv_window_size_);
12415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
12425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Shift time to expire the push stream. Read the second SYN_STREAM,
12455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // and verify a RST_STREAM was written.
12465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  g_time_delta = base::TimeDelta::FromSeconds(301);
12475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.RunFor(2);
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that the second pushed stream evicted the first pushed stream.
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1u, session->num_unclaimed_pushed_streams());
1251ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  iter = session->unclaimed_pushed_streams_.find(
1252ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      GURL("http://www.google.com/b.dat"));
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(session->unclaimed_pushed_streams_.end() != iter);
12545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (session->flow_control_state_ ==
12565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SpdySession::FLOW_CONTROL_STREAM_AND_SESSION) {
12575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Verify that the session window reclaimed the evicted stream body.
12585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(kSpdySessionInitialWindowSize,
12595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              session->session_recv_window_size_);
12605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
12615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
12625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Read and process EOF.
12645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.RunFor(1);
1265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
12665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(session == NULL);
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, FailedPing) {
12702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
1274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
1277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(
1278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping."));
1279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)};
1280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  StaticSocketDataProvider data(
1281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
1283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CreateNetworkSession();
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
12887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1290a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
129190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
129290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, test_url_, MEDIUM, BoundNetLog());
12932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
129490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(spdy_stream1, NULL);
12952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate);
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->set_hung_interval(base::TimeDelta::FromSeconds(0));
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send a PING frame.
1301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  session->WritePingFrame(1, false);
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(0, session->pings_in_flight());
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(session->next_ping_id(), static_cast<uint32>(1));
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(session->check_ping_status_pending());
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assert session is not closed.
1307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(session->IsAvailable());
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams());
13097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We set last time we have received any data in 1 sec less than now.
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CheckPingStatus will trigger timeout because hung interval is zero.
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks now = base::TimeTicks::Now();
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->last_activity_time_ = now - base::TimeDelta::FromSeconds(1);
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session->CheckPingStatus(now);
1316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
13197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1320a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Request kInitialMaxConcurrentStreams + 1 streams.  Receive a
1324a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// settings frame increasing the max concurrent streams by 1.  Make
1325a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// sure nothing blows up. This is a regression test for
1326a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// http://crbug.com/57331 .
13277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, OnSettings) {
13282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const SpdySettingsIds kSpdySettingsIds = SETTINGS_MAX_CONCURRENT_STREAMS;
1331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsMap new_settings;
1333a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1334ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  new_settings[kSpdySettingsIds] =
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
133690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
133790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(new_settings));
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
1339a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    CreateMockRead(*settings_frame, 0),
1340a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    MockRead(ASYNC, 0, 1),
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockWrite writes[] = {
1345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*settings_ack, 2),
1346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
1347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
1349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               writes, arraysize(writes));
1350ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
1352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1354ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1356ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
13577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create the maximum number of concurrent streams.
1360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream =
1362a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  session, test_url_, MEDIUM, BoundNetLog());
1364a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
1365a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1367a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  StreamReleaserCallback stream_releaser;
13682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyStreamRequest request;
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING,
137090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            request.StartRequest(
137190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
137290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                BoundNetLog(),
137390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                stream_releaser.MakeCallback(&request)));
1374ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1375a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.RunFor(1);
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13779ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  EXPECT_EQ(OK, stream_releaser.WaitForResult());
1378ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1379ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
1380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (spdy_util_.spdy_version() >= SPDY4) {
1381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Allow the SETTINGS+ACK to write, so the session finishes draining.
1382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    data.RunFor(1);
1383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1385ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1388a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Start with a persisted value for max concurrent streams. Receive a
1389a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// settings frame increasing the max concurrent streams by 1 and which
1390a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// also clears the persisted data. Verify that persisted data is
1391a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// correct.
13927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ClearSettings) {
1393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (spdy_util_.spdy_version() >= SPDY4) {
1394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // SPDY4 doesn't include settings persistence, or a CLEAR_SETTINGS flag.
1395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Flag 0x1, CLEAR_SETTINGS in SPDY3, is instead settings ACK in SPDY4.
1396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
1397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
1398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
1399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SettingsMap new_settings;
1401a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const uint32 max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
1402a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
140490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
140590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(new_settings));
1406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint8 flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
1408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockRead reads[] = {
1409a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    CreateMockRead(*settings_frame, 0),
1410a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    MockRead(ASYNC, 0, 1),
1411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
1412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
1414ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
1415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.set_connect_data(connect_data);
1416ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1418ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  CreateDeterministicNetworkSession();
1419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1420a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Initialize the SpdySetting with the default.
1421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  spdy_session_pool_->http_server_properties()->SetSpdySetting(
1422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      test_host_port_pair_,
1423a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      SETTINGS_MAX_CONCURRENT_STREAMS,
1424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SETTINGS_FLAG_PLEASE_PERSIST,
1425a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      kInitialMaxConcurrentStreams);
1426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1427a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_FALSE(
1428a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      spdy_session_pool_->http_server_properties()->GetSpdySettings(
1429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          test_host_port_pair_).empty());
1430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1431ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
14327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
1433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create the maximum number of concurrent streams.
1435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams; ++i) {
1436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream =
1437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  session, test_url_, MEDIUM, BoundNetLog());
1439a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
1440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1442a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  StreamReleaserCallback stream_releaser;
1443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SpdyStreamRequest request;
1445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING,
144690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            request.StartRequest(
144790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
144890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                BoundNetLog(),
144990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                stream_releaser.MakeCallback(&request)));
1450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1451a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.RunFor(1);
1452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
14539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  EXPECT_EQ(OK, stream_releaser.WaitForResult());
1454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure that persisted data is cleared.
1456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_TRUE(
1457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      spdy_session_pool_->http_server_properties()->GetSpdySettings(
1458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          test_host_port_pair_).empty());
1459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1460a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Make sure session's max_concurrent_streams is correct.
1461a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
1462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            session->max_concurrent_streams());
14637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1464ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
1465ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
1466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1468a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Start with max concurrent streams set to 1.  Request two streams.
1469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// When the first completes, have the callback close its stream, which
1470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// should trigger the second stream creation.  Then cancel that one
1471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// immediately.  Don't crash.  This is a regression test for
1472a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// http://crbug.com/63532 .
14737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, CancelPendingCreateStream) {
14742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
14842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the SpdySetting with 1 max concurrent streams.
14892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_session_pool_->http_server_properties()->SetSpdySetting(
14902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_,
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_MAX_CONCURRENT_STREAMS,
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_FLAG_PLEASE_PERSIST,
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1);
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
14967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1498a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Leave room for only one more stream to be created.
1499a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
1500a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream =
1501a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
1502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  session, test_url_, MEDIUM, BoundNetLog());
1503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
1504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create 2 more streams.  First will succeed.  Second will be pending.
1507a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
150890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
150990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, test_url_, MEDIUM, BoundNetLog());
15102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a valgrind error if the callback is invoked when it's not supposed to be.
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TestCompletionCallback> callback(new TestCompletionCallback);
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyStreamRequest request;
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING,
151890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            request.StartRequest(
151990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM,
152090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                BoundNetLog(),
152190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                callback->callback()));
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Release the first one, this will allow the second to be created.
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  spdy_stream1->Cancel();
1525a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request.CancelRequest();
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.reset();
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should not crash when running the pending callback.
153190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1534a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
15352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsMap settings;
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdySettingsIds kSpdySettingsIds2 = SETTINGS_INITIAL_WINDOW_SIZE;
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32 kInitialRecvWindowSize = 10 * 1024 * 1024;
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings[kSpdySettingsIds1] =
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
15477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (spdy_util_.spdy_version() >= SPDY3) {
15487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    settings[kSpdySettingsIds2] =
15497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialRecvWindowSize);
15507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
155290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
155390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(settings));
1554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> initial_window_update(
1555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(
1556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kSessionFlowControlStreamId,
1557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
1558a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::vector<MockWrite> writes;
1559a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (GetParam() == kProtoSPDY4) {
1560a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    writes.push_back(
1561a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        MockWrite(ASYNC,
1562a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  kHttp2ConnectionHeaderPrefix,
1563a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  kHttp2ConnectionHeaderPrefixSize));
1564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1565a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  writes.push_back(CreateMockWrite(*settings_frame));
1566a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (GetParam() >= kProtoSPDY31) {
1567a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    writes.push_back(CreateMockWrite(*initial_window_update));
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1570a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  SettingsMap server_settings;
1571a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const uint32 initial_max_concurrent_streams = 1;
1572a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1573a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
1574a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            initial_max_concurrent_streams);
1575a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<SpdyFrame> server_settings_frame(
1576a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      spdy_util_.ConstructSpdySettings(server_settings));
1577a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  writes.push_back(CreateMockWrite(*server_settings_frame));
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1579a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  session_deps_.stream_initial_recv_window_size = kInitialRecvWindowSize;
1580a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1581a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads),
1582a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                vector_as_array(&writes), writes.size());
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
15842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_session_pool_->http_server_properties()->SetSpdySetting(
15892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_,
1590a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      SETTINGS_MAX_CONCURRENT_STREAMS,
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_FLAG_PLEASE_PERSIST,
1592a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      initial_max_concurrent_streams);
1593a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1594a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  SpdySessionPoolPeer pool_peer(spdy_session_pool_);
1595a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  pool_peer.SetEnableSendingInitialData(true);
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1597ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
15987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
160090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
16017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(data.at_write_eof());
16022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) {
16052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1607ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<HttpServerProperties> test_http_server_properties =
16082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spdy_session_pool_->http_server_properties();
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsFlagsAndValue flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST, 2);
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_http_server_properties->SetSpdySetting(
16112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_,
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_MAX_CONCURRENT_STREAMS,
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SETTINGS_FLAG_PLEASE_PERSIST,
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      2);
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(0u, test_http_server_properties->GetSpdySettings(
16162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_).size());
16172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_session_pool_->OnIPAddressChanged();
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, test_http_server_properties->GetSpdySettings(
16192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_host_port_pair_).size());
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, Initialize) {
1623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CapturingBoundNetLog log;
1624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.net_log = log.bound().net_log();
1625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
1626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockRead reads[] = {
1629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
1630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
1631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.set_connect_data(connect_data);
1634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
1635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CreateNetworkSession();
1637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1638ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
16397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, log.bound());
16407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1642ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Flush the read completion task.
164390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  net::CapturingNetLog::CapturedEntryList entries;
1646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  log.GetEntries(&entries);
1647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(0u, entries.size());
1648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check that we logged TYPE_SPDY_SESSION_INITIALIZED correctly.
1650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int pos = net::ExpectLogContainsSomewhere(
1651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      entries, 0,
1652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      net::NetLog::TYPE_SPDY_SESSION_INITIALIZED,
1653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      net::NetLog::PHASE_NONE);
1654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(0, pos);
1655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CapturingNetLog::CapturedEntry entry = entries[pos];
1657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NetLog::Source socket_source;
1658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(),
1659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                  &socket_source));
1660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(socket_source.IsValid());
1661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_NE(log.bound().source().id, socket_source.id);
1662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1664cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
16652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
166890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
16702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*goaway),
16712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(SYNCHRONOUS, 0, 0)  // EOF
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
16732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
16762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CapturingBoundNetLog log;
1681ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
16827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, log.bound());
16837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Flush the read completion task.
168690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1689ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that the NetLog was filled reasonably.
16922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::CapturingNetLog::CapturedEntryList entries;
16932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  log.GetEntries(&entries);
16942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_LT(0u, entries.size());
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that we logged SPDY_SESSION_CLOSE correctly.
16972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int pos = net::ExpectLogContainsSomewhere(
16982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      entries, 0,
16992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::NetLog::TYPE_SPDY_SESSION_CLOSE,
17002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::NetLog::PHASE_NONE);
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1702ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (pos < static_cast<int>(entries.size())) {
1703ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CapturingNetLog::CapturedEntry entry = entries[pos];
1704ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    int error_code = 0;
1705ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1706cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_EQ(OK, error_code);
1707cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
1708cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ADD_FAILURE();
1709cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1710cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1711cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1712cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
1713cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
1714cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1715cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1716cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockRead reads[] = {
1717cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      MockRead(SYNCHRONOUS, 0, 0)  // EOF
1718cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
1719cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1720cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
1721cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.set_connect_data(connect_data);
1722cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
1723cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1724cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CreateNetworkSession();
1725cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1726cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CapturingBoundNetLog log;
1727cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<SpdySession> session =
1728cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, log.bound());
1729cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
1730cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1731cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Flush the read completion task.
1732cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1733cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1734cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
1735cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(session == NULL);
1736cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1737cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check that the NetLog was filled reasonably.
1738cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  net::CapturingNetLog::CapturedEntryList entries;
1739cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  log.GetEntries(&entries);
1740cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_LT(0u, entries.size());
1741cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1742cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check that we logged SPDY_SESSION_CLOSE correctly.
1743cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int pos =
1744cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      net::ExpectLogContainsSomewhere(entries,
1745cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      0,
1746cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      net::NetLog::TYPE_SPDY_SESSION_CLOSE,
1747cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      net::NetLog::PHASE_NONE);
1748cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1749cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (pos < static_cast<int>(entries.size())) {
1750cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CapturingNetLog::CapturedEntry entry = entries[pos];
1751cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int error_code = 0;
1752cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ASSERT_TRUE(entry.GetNetErrorCode(&error_code));
1753ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code);
1754ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  } else {
1755ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ADD_FAILURE();
1756ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
17572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1759eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Queue up a low-priority SYN_STREAM followed by a high-priority
1760eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// one. The high priority one should still send first and receive
1761eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// first.
17627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
17632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Construct the request.
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1765eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req_highest(
176690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, HIGHEST, true));
1767eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req_lowest(
176890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
1770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req_highest, 0),
1771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req_lowest, 1),
17722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
17732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp_highest(
1775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body_highest(
1777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
1778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp_lowest(
1779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body_lowest(
1781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(3, true));
17822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
1783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp_highest, 2),
1784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body_highest, 3),
1785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp_lowest, 4),
1786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body_lowest, 5),
1787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 6)  // EOF
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
17892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
17912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
1793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
1795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1799ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
18007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1804eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream_lowest =
180590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
180690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
1807eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream_lowest);
1808eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream_lowest->stream_id());
1809eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate_lowest(spdy_stream_lowest);
1810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream_lowest->SetDelegate(&delegate_lowest);
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1812eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream_highest =
181390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
181490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, HIGHEST, BoundNetLog());
1815eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream_highest);
1816eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream_highest->stream_id());
1817eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate_highest(spdy_stream_highest);
1818eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream_highest->SetDelegate(&delegate_highest);
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1820eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Queue the lower priority one first.
1821eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1822eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers_lowest(
1823b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
1824eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream_lowest->SendRequestHeaders(
1825eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      headers_lowest.Pass(), NO_MORE_DATA_TO_SEND);
1826ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream_lowest->HasUrlFromHeaders());
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1828eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers_highest(
1829b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
1830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream_highest->SendRequestHeaders(
1831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      headers_highest.Pass(), NO_MORE_DATA_TO_SEND);
1832ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream_highest->HasUrlFromHeaders());
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1834eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(7);
18352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(spdy_stream_lowest);
1837eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(spdy_stream_highest);
1838eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, delegate_lowest.stream_id());
1839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, delegate_highest.stream_id());
18402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
18412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, CancelStream) {
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
18442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Request 1, at HIGHEST priority, will be cancelled before it writes data.
18452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Request 2, at LOWEST priority, will be a full request and will be id 1.
184690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
184790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
18482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
18492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req2, 0),
18502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
18512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
18537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
18552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp2, 1),
18562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*body2, 2),
18572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(ASYNC, 0, 3)  // EOF
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
18632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
18652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1869ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
18707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
1873a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
187490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
187590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, HIGHEST, BoundNetLog());
18762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
18772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
1878a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
1879a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
1882a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream2 =
188390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
188490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url2, LOWEST, BoundNetLog());
18852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream2.get() != NULL);
18862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream2->stream_id());
1887a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate2(spdy_stream2);
1888a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream2->SetDelegate(&delegate2);
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
189090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
1891b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
189290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1893ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
189590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
1896b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
189790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1898ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spdy_stream1->Cancel();
1903a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.RunFor(1);
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1909a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
1910a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(1u, delegate2.stream_id());
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  spdy_stream2->Cancel();
1913a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream2.get());
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to re-close themselves on close,
1917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// and then close the session. Nothing should blow up. Also a
1918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// regression test for http://crbug.com/139518 .
1919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) {
19202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
19212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No actual data will be sent.
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, 0, 1)  // EOF
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
19352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1939ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
19407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
1943a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
194490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
194590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, HIGHEST, BoundNetLog());
19462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
1950a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream2 =
195190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
195290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url2, LOWEST, BoundNetLog());
19532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream2.get() != NULL);
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, spdy_stream2->stream_id());
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1956eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate1(spdy_stream1);
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1959eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate2(spdy_stream2);
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  spdy_stream2->SetDelegate(&delegate2);
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
196290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
196390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
196490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
1965ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
196690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
196790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
196890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
196990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
1970ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the streams have not yet been activated and assigned an id.
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, spdy_stream2->stream_id());
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure we don't crash while closing the session.
19777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, std::string());
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1979a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
1980a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream2.get());
1981a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1982a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_TRUE(delegate1.StreamIsClosed());
1983a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_TRUE(delegate2.StreamIsClosed());
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1986ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1989eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to close each other on close, and
1990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// then close the session. Nothing should blow up.
1991eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
19922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
19932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No actual data will be sent.
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, 0, 1)  // EOF
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
20072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2011ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
20127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2015eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
2016eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2017eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, HIGHEST, BoundNetLog());
2018eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
2019eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
2022eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
2023eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2024eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url2, LOWEST, BoundNetLog());
2025eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream2.get() != NULL);
2026eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2028eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Make |spdy_stream1| close |spdy_stream2|.
2029eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate1(spdy_stream2);
2030eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
2031eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2032eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Make |spdy_stream2| close |spdy_stream1|.
2033eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate2(spdy_stream1);
2034eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SetDelegate(&delegate2);
2035eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2036eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2037eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2038eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2039ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
2042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2043eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2044ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
20457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2046eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure that the streams have not yet been activated and assigned an id.
2047eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
2048eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
2049eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2050eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure we don't crash while closing the session.
20517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, std::string());
2052eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2053eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
2054eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
2055eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2056eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.StreamIsClosed());
2057eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.StreamIsClosed());
2058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2059cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2060ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
2061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to re-close themselves on close,
2064eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// activate them, and then close the session. Nothing should blow up.
2065eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
20662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
20672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
2071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
2073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
2075eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
2076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2080eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 2)  // EOF
20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2082eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
20862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2090ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
20917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
20922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
2095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, MEDIUM, BoundNetLog());
2097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
2098eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
20992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
2101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
2102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url2, MEDIUM, BoundNetLog());
2104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream2.get() != NULL);
2105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
21067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate1(spdy_stream1);
2108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
21092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate2(spdy_stream2);
2111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SetDelegate(&delegate2);
21122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2116ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
21172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
2119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2121ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
21222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure that the streams have not yet been activated and assigned an id.
2124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
2125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
21262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
21282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, spdy_stream1->stream_id());
2130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, spdy_stream2->stream_id());
2131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure we don't crash while closing the session.
21337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, std::string());
2134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
2136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
2137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.StreamIsClosed());
2139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.StreamIsClosed());
2140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
2143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Create two streams that are set to close each other on close,
2146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// activate them, and then close the session. Nothing should blow up.
2147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
2148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
2149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
2153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
2155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, MEDIUM, true));
2156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
2158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
2159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
21602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
2162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 2)  // EOF
21632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
21642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
21662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
21672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
21682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
21692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
21712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
21737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
21742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2176a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
217790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, MEDIUM, BoundNetLog());
21792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
21802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
21812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
2183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
2184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url2, MEDIUM, BoundNetLog());
2186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream2.get() != NULL);
2187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
21882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Make |spdy_stream1| close |spdy_stream2|.
2190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate1(spdy_stream2);
2191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
21922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Make |spdy_stream2| close |spdy_stream1|.
2194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::ClosingDelegate delegate2(spdy_stream1);
2195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SetDelegate(&delegate2);
21962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
219790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
2198b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
219990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2200ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
22012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
220290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
220390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2205ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream2->HasUrlFromHeaders());
22062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure that the streams have not yet been activated and assigned an id.
22082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
2209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream2->stream_id());
22102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
22122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, spdy_stream1->stream_id());
2214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, spdy_stream2->stream_id());
22152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure we don't crash while closing the session.
22177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_ABORTED, std::string());
22182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2219a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
2220a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream2.get());
22212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.StreamIsClosed());
2223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.StreamIsClosed());
2224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2226ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
22272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
22282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2229bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Delegate that closes a given session when the stream is closed.
2230bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochclass SessionClosingDelegate : public test::StreamDelegateDoNothing {
2231bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch public:
2232bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
2233bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                         const base::WeakPtr<SpdySession>& session_to_close)
2234bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      : StreamDelegateDoNothing(stream),
2235bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        session_to_close_(session_to_close) {}
2236bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2237bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual ~SessionClosingDelegate() {}
2238bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2239bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual void OnClose(int status) OVERRIDE {
2240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    session_to_close_->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error");
2241bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  }
2242bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2243bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch private:
2244bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdySession> session_to_close_;
2245bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch};
2246bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2247bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Close an activated stream that closes its session. Nothing should
2248bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// blow up. This is a regression test for http://crbug.com/263691 .
2249bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
2250bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
2251bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2252bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2253bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2254bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyFrame> req(
2255bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> rst(
2257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(
2259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
2260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // The GOAWAY has higher-priority than the RST_STREAM, and is written first
2261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // despite being queued second.
2262bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockWrite writes[] = {
2263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 1),
2264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateMockWrite(*rst, 2),
2265bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  };
2266bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2267bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockRead reads[] = {
2268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MockRead(ASYNC, 0, 3)  // EOF
2269bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  };
2270bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
2271bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                               writes, arraysize(writes));
2272bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.set_connect_data(connect_data);
2273bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2274bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2275bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  CreateDeterministicNetworkSession();
2276bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2277bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdySession> session =
2278bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2279bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
22805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
2281bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
2282bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2283bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
2284bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  ASSERT_TRUE(spdy_stream.get() != NULL);
2285bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, spdy_stream->stream_id());
2286bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2287bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  SessionClosingDelegate delegate(spdy_stream, session);
2288bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->SetDelegate(&delegate);
2289bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2290bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2291bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
2292bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2293bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
2294bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2295bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, spdy_stream->stream_id());
2296bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2297bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.RunFor(1);
2298bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2299bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(1u, spdy_stream->stream_id());
2300bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2301bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Ensure we don't crash while closing the stream (which closes the
2302bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // session).
2303bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->Cancel();
2304bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2305bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(NULL, spdy_stream.get());
2306bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(delegate.StreamIsClosed());
2307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data.RunFor(2);  // Write the RST_STREAM & GOAWAY.
2309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2310bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(session == NULL);
2311bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
2312bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
2313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, VerifyDomainAuthentication) {
2314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
23157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
23162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
2317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // No actual data will be sent.
2319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(ASYNC, 0, 1)  // EOF
2321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
23232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
2324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
23252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
2326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
2327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
23282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
2329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Load a cert that is valid for:
2332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   www.example.org
2333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   mail.example.org
2334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   www.example.com
2335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::FilePath certs_dir = GetTestCertsDirectory();
2336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<X509Certificate> test_cert(
2337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert);
23392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ssl.cert = test_cert;
2342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
23432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
23452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2346ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
23477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateSecureSpdySession(http_session_, key_, BoundNetLog());
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com"));
2352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
23532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
23542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) {
2356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
23577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
23582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
2359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // No actual data will be sent.
23612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
2362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(ASYNC, 0, 1)  // EOF
23632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
2364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
2367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
2369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
23702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
2371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Load a cert that is valid for:
2374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   www.example.org
2375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   mail.example.org
2376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   www.example.com
2377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::FilePath certs_dir = GetTestCertsDirectory();
2378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<X509Certificate> test_cert(
2379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
2380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert);
23812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
23832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ssl.channel_id_sent = true;
2384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ssl.cert = test_cert;
2385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
23862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
23882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2389ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
23907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateSecureSpdySession(http_session_, key_, BoundNetLog());
23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org"));
2393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org"));
2394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com"));
2395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->VerifyDomainAuthentication("mail.google.com"));
23962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
23972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
2399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(rtenneti): Define a helper class/methods and move the common code in
2400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // this file.
24012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
24027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SettingsMap new_settings;
2404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const SpdySettingsIds kSpdySettingsIds1 = SETTINGS_MAX_CONCURRENT_STREAMS;
2405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const uint32 max_concurrent_streams = 1;
2406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  new_settings[kSpdySettingsIds1] =
2407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
24082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
241090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
2411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
2413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
2414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req3(
2415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
24162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
2417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*settings_ack, 1),
2418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*req1, 2),
2419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*req2, 5),
2420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*req3, 8),
24212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
24222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set up the socket so we read a SETTINGS frame that sets max concurrent
2424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // streams to 1.
2425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame(
2426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(new_settings));
24272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
2430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
2433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
2435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
24362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
2438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*settings_frame),
2439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp1, 3),
2440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*body1, 4),
2441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp2, 6),
2442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*body2, 7),
2443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp3, 9),
2444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*body3, 10),
2445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MockRead(ASYNC, 0, 11)  // EOF
24462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
24472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
24492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
24502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
24512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
24522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
24542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2455ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
24567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
24572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the settings frame.
2459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
2460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
24615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2462a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
246390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, LOWEST, BoundNetLog());
24652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
24662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
2467a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2468a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
24692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
24715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
2472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request2;
2473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request2.StartRequest(
2475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_REQUEST_RESPONSE_STREAM,
2476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                session, url2, LOWEST, BoundNetLog(), callback2.callback()));
2477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback3;
24795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url3(kDefaultURL);
2480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request3;
2481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request3.StartRequest(
2483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_REQUEST_RESPONSE_STREAM,
2484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                session, url3, LOWEST, BoundNetLog(), callback3.callback()));
2485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2486a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2487a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
24887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2491b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
2493ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
24942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2495a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Run until 1st stream is activated and then closed.
2496a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
2497cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.RunFor(4);
2498a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
2499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, delegate1.stream_id());
2500a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2501a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
2503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // create the 2nd stream.
2507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2509a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2510a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
2511a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
25122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream2 = request2.ReleaseStream();
2514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate2(stream2);
2515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream2->SetDelegate(&delegate2);
2516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
2517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url2.spec()));
2518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream2->SendRequestHeaders(headers2.Pass(), NO_MORE_DATA_TO_SEND);
2519ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
2520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2521a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Run until 2nd stream is activated and then closed.
2522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, delegate2.stream_id());
2523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(3);
2524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream2.get());
2525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, delegate2.stream_id());
2526a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2527a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2528a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
2529a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2530a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2531a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Pump loop for SpdySession::ProcessPendingStreamRequests() to
2532a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // create the 3rd stream.
2533a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2534a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2535a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2536a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->num_created_streams());
25377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream3 = request3.ReleaseStream();
2540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate3(stream3);
2541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream3->SetDelegate(&delegate3);
2542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers3(
2543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url3.spec()));
2544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream3->SendRequestHeaders(headers3.Pass(), NO_MORE_DATA_TO_SEND);
2545ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream3->HasUrlFromHeaders());
2546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2547a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Run until 2nd stream is activated and then closed.
2548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, delegate3.stream_id());
2549ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(3);
2550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream3.get());
2551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(5u, delegate3.stream_id());
2552a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2553a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2554a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_created_streams());
25557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2556ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
2557ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
2558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
2561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
2562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
2565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
2568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
2571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
2572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
2574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2575ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
25767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2578a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Leave room for only one more stream to be created.
2579a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < kInitialMaxConcurrentStreams - 1; ++i) {
2580a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::WeakPtr<SpdyStream> spdy_stream =
2581a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2582a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  session, test_url_, MEDIUM, BoundNetLog());
2583a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_TRUE(spdy_stream != NULL);
2584a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
2585a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
25865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
2588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
2589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, LOWEST, BoundNetLog());
2590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
2591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
2592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
25945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url2(kDefaultURL);
2595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request2;
2596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request2.StartRequest(
2598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_BIDIRECTIONAL_STREAM, session, url2, LOWEST, BoundNetLog(),
2599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                callback2.callback()));
2600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback3;
26025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url3(kDefaultURL);
2603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamRequest request3;
2604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING,
2605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request3.StartRequest(
2606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                SPDY_BIDIRECTIONAL_STREAM, session, url3, LOWEST, BoundNetLog(),
2607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                callback3.callback()));
2608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2609a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2610a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
26117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(2u, session->pending_create_stream_queue_size(LOWEST));
2612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2613a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Cancel the first stream; this will allow the second stream to be created.
2614eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(spdy_stream1.get() != NULL);
2615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->Cancel();
2616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
2617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2618a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(OK, callback2.WaitForResult());
2619a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2620a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
2621a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(1u, session->pending_create_stream_queue_size(LOWEST));
2622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2623a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Cancel the second stream; this will allow the third stream to be created.
2624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 = request2.ReleaseStream();
2625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->Cancel();
2626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
2627a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2628a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(OK, callback3.WaitForResult());
2629a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2630a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams, session->num_created_streams());
26317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Cancel the third stream.
2634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream3 = request3.ReleaseStream();
2635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream3->Cancel();
2636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream3.get());
2637a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(0u, session->num_active_streams());
2638a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(kInitialMaxConcurrentStreams - 1, session->num_created_streams());
26397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
2640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2642ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop reads data from the socket
2643ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// without yielding.  This test makes 32k - 1 bytes of data available
2644ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// on the socket for reading. It then verifies that it has read all
2645ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the available data without yielding.
2646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, ReadDataWithoutYielding) {
2647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
2648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
2649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
2651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
2652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
2654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2656ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2657ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // (-spdy_data_frame_size).
2658ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
2659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int kPayloadSize =
2660ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
2661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestDataStream test_stream;
2662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
2663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  char* payload_data = payload->data();
2664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test_stream.GetBytes(payload_data, kPayloadSize);
2665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> partial_data_frame(
2667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
2668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> finish_data_frame(
2669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
2670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
2674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // bytes.
2675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp1, 1),
2677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*partial_data_frame, 2),
2678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
2679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
2680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
2681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 6)  // EOF
2682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create SpdySession and SpdyStream and send the request.
2685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
2686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
2687eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
2688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
2689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
2692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2693ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
26947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
2695eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
26965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2697eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
2698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
2699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url1, MEDIUM, BoundNetLog());
2700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
2701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, spdy_stream1->stream_id());
2702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
2704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers1(
2706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
2707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2708ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
2709eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2710ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Set up the TaskObserver to verify SpdySession::DoReadLoop doesn't
2711ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // post a task.
2712ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
2713eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Run until 1st read.
2715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, delegate1.stream_id());
2716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
2717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, delegate1.stream_id());
2718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, observer.executed_count());
2719eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2720ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read all the data and verify SpdySession::DoReadLoop has not
2721ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // posted a task.
2722eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(4);
2723eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
2724eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2725eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify task observer's executed_count is zero, which indicates DoRead read
2726eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // all the available data.
2727eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0u, observer.executed_count());
27282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
27292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
27302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
27312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2732ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop yields while reading the
2733ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// data. This test makes 32k + 1 bytes of data available on the socket
2734ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// for reading. It then verifies that DoRead has yielded even though
2735ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// there is data available for it to read (i.e, socket()->Read didn't
2736ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// return ERR_IO_PENDING during socket reads).
27377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
27382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
27397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
27402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
274190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
274290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
27432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
27442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req1, 0),
27452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
27462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2747ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2748ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // (-spdy_data_frame_size).
2749ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
27502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kPayloadSize =
2751ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
27522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestDataStream test_stream;
27532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
27542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char* payload_data = payload->data();
27552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test_stream.GetBytes(payload_data, kPayloadSize);
27562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> partial_data_frame(
27582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
27592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> finish_data_frame(
27602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
27612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
27632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
27652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
27662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp1, 1),
27672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 2),
27682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
27692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
27702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
27712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
27722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(ASYNC, 0, 7)  // EOF
27732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
27742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
27762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
27772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
27782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
27792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
27802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
27812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
27832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2784ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
27857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
27862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2788a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
278990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
279090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, MEDIUM, BoundNetLog());
27912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
27922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
2793a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2794a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
27952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
279690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
2797b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
279890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2799ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
28002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2801ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Set up the TaskObserver to verify SpdySession::DoReadLoop posts a
2802ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // task.
2803ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
28042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until 1st read.
2806a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
28072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(2);
2808a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(1u, delegate1.stream_id());
28092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, observer.executed_count());
28102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2811ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read all the data and verify SpdySession::DoReadLoop has posted a
2812ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // task.
28132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(6);
2814a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
28152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify task observer's executed_count is 1, which indicates DoRead has
28172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // posted only one task and thus yielded though there is data available for it
28182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to read.
28192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, observer.executed_count());
28202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
28212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
28222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
28232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2824ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that SpdySession::DoReadLoop() tests interactions of yielding
2825ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// + async, by doing the following MockReads.
28262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
28272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
28282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
28292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
2830ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// The above reads 26K synchronously. Since that is less that 32K, we
2831ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// will attempt to read again. However, that DoRead() will return
2832ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// ERR_IO_PENDING (because of async read), so DoReadLoop() will
2833ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// yield. When we come back, DoRead() will read the results from the
2834ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// async read, and rest of the data synchronously.
28357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
28362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
28377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
28382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
283990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
284090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
28412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
28422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req1, 0),
28432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
28442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2845ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Build buffer of size kMaxReadBytesWithoutYielding / 4
2846ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // (-spdy_data_frame_size).
2847ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ASSERT_EQ(32 * 1024, kMaxReadBytesWithoutYielding);
28482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestDataStream test_stream;
28492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kEightKPayloadSize =
2850ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize();
28512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> eightk_payload(
28522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new net::IOBuffer(kEightKPayloadSize));
28532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char* eightk_payload_data = eightk_payload->data();
28542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
28552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Build buffer of 2k size.
28572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestDataStream test_stream2;
28582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
28592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> twok_payload(
28602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new net::IOBuffer(kTwoKPayloadSize));
28612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char* twok_payload_data = twok_payload->data();
28622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
28632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
28652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
28662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
28672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
28682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
28692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1, "h", 1, DATA_FLAG_FIN));
28702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
28722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
28742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp1, 1),
28752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 2),
28762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
28772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
28782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
28792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 6, ASYNC),
28802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
28812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
28822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
28832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
28842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
28852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(ASYNC, 0, 12)  // EOF
28862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
28872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
28892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
28902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
28912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
28922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
28932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
28942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
28962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2897ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
28987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
28992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2901a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
290290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
290390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, MEDIUM, BoundNetLog());
29042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
29052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
2906a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
2907a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
29082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
290990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
2910b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
291190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2912ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
29132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2914ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Set up the TaskObserver to monitor SpdySession::DoReadLoop
2915ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // posting of tasks.
2916ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdySessionTestTaskObserver observer("spdy_session.cc", "DoReadLoop");
29172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until 1st read.
2919a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(0u, delegate1.stream_id());
29202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(2);
2921a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(1u, delegate1.stream_id());
29222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, observer.executed_count());
29232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2924ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Read all the data and verify SpdySession::DoReadLoop has posted a
2925ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // task.
29262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(12);
2927a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
29282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify task observer's executed_count is 1, which indicates DoRead has
29302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // posted only one task and thus yielded though there is data available for
29312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // it to read.
29322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, observer.executed_count());
29332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
29342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
29352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
29362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2937ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Send a GoAway frame when SpdySession is in DoReadLoop. Make sure
2938ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// nothing blows up.
2939ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
29402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
29417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
29422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
294390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
294490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
29452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
29462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req1, 0),
29472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
29482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
29507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
295190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
29522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
29542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp1, 1),
29552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*body1, 2),
29562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*goaway, 3),
29572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
29582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
29602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
29612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
29622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
29632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
29642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
29652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
29672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2968ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
29697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
29702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
2972a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream1 =
297390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
297490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url1, MEDIUM, BoundNetLog());
297590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateDoNothing delegate1(spdy_stream1);
297690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SetDelegate(&delegate1);
29772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(spdy_stream1.get() != NULL);
29782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
29792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
298090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
2981b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
298290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND);
2983ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
29842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until 1st read.
29862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, spdy_stream1->stream_id());
29872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
29882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, spdy_stream1->stream_id());
29892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run until GoAway.
2991ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(3);
2992a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, spdy_stream1.get());
29932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
29942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
2995ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
29962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
29972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Within this framework, a SpdySession should be initialized with
29997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// flow control disabled for protocol version 2, with flow control
30007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// enabled only for streams for protocol version 3, and with flow
30017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// control enabled for streams and sessions for higher versions.
30027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ProtocolNegotiation) {
30032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
30042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
30062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
30072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(SYNCHRONOUS, 0, 0)  // EOF
30082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
30092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
30102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
30112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
30122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
3014ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
30157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_);
30162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(spdy_util_.spdy_version(),
30187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            session->buffered_spdy_framer_->protocol_version());
30194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (GetParam() == kProtoDeprecatedSPDY2) {
30207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state());
30217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_send_window_size_);
30227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_recv_window_size_);
30237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else if (GetParam() == kProtoSPDY3) {
30247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state());
30257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_send_window_size_);
30267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(0, session->session_recv_window_size_);
30277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else {
30287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
30297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              session->flow_control_state());
30307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(kSpdySessionInitialWindowSize,
30317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              session->session_send_window_size_);
3032eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(kSpdySessionInitialWindowSize,
30337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              session->session_recv_window_size_);
30347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
30352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
30362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
30372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3038eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Tests the case of a non-SPDY request closing an idle SPDY session when no
3039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// pointers to the idle session are currently held.
3040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseOneIdleConnection) {
3041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_group(
3042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3043eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_pool(
3044eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
30452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
30472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3048eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
30492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
3050eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
30512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
3052eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
3053eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
30542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3055eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
30562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3057eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransportClientSocketPool* pool =
3058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      http_session_->GetTransportSocketPool(
3059eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          HttpNetworkSession::NORMAL_SOCKET_POOL);
30602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create an idle SPDY session.
3062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3063e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      PRIVACY_MODE_DISABLED);
3064ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session1 =
30657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3066eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
30672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Trying to create a new connection should cause the pool to be stalled, and
3069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // post a task asynchronously to try and close the session.
3070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
3071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port2("2.com", 80);
3072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<TransportSocketParams> params2(
30733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new TransportSocketParams(host_port2, false, false,
3074eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                OnHostResolutionCallback()));
3075eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
3077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              callback2.callback(), pool, BoundNetLog()));
3079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
30802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3081eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The socket pool should close the connection asynchronously and establish a
3082eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // new connection.
3083eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, callback2.WaitForResult());
3084eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
3085ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session1 == NULL);
30862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
30872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3088eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Tests the case of a non-SPDY request closing an idle SPDY session when no
3089eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// pointers to the idle session are currently held, in the case the SPDY session
3090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// has an alias.
3091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
3092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_group(
3093eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_pool(
3095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
30962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
30982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3099eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
31002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
31012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
31022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
31032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
3104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
3105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->rules()->AddIPLiteralRule(
3108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "1.com", "192.168.0.2", std::string());
3109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->rules()->AddIPLiteralRule(
3110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "2.com", "192.168.0.2", std::string());
3111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Not strictly needed.
3112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->rules()->AddIPLiteralRule(
3113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "3.com", "192.168.0.3", std::string());
31142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
31152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateNetworkSession();
31162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransportClientSocketPool* pool =
3118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      http_session_->GetTransportSocketPool(
3119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          HttpNetworkSession::NORMAL_SOCKET_POOL);
31202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create an idle SPDY session.
3122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(),
3123e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      PRIVACY_MODE_DISABLED);
3124ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session1 =
31257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
31272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set up an alias for the idle SPDY session, increasing its ref count to 2.
3129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(),
3130e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      PRIVACY_MODE_DISABLED);
3131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostResolver::RequestInfo info(key2.host_port_pair());
3132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddressList addresses;
3133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Pre-populate the DNS cache, since a synchronous resolution is required in
3134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // order to create the alias.
31353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  session_deps_.host_resolver->Resolve(info,
31363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       DEFAULT_PRIORITY,
31373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       &addresses,
31383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       CompletionCallback(),
31393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       NULL,
31403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       BoundNetLog());
3141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Get a session for |key2|, which should return the session created earlier.
3142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session2 =
31437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
3144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(session1.get(), session2.get());
3145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
31462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Trying to create a new connection should cause the pool to be stalled, and
3148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // post a task asynchronously to try and close the session.
3149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback3;
3150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port3("3.com", 80);
3151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<TransportSocketParams> params3(
31523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new TransportSocketParams(host_port3, false, false,
3153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                OnHostResolutionCallback()));
3154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
3155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
3156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
3157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              callback3.callback(), pool, BoundNetLog()));
3158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
31597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The socket pool should close the connection asynchronously and establish a
3161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // new connection.
3162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, callback3.WaitForResult());
3163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
3164ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session1 == NULL);
3165ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session2 == NULL);
3166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
31683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Tests that when a SPDY session becomes idle, it closes itself if there is
31693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// a lower layer pool stalled on the per-pool socket limit.
31703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
3171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_group(
3172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ClientSocketPoolManager::set_max_sockets_per_pool(
3174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
3175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
3179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
3181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> cancel1(
3183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
3185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 1),
3186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*cancel1, 1),
3187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads),
31893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                writes, arraysize(writes));
3190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
3192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
31933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  MockRead http_reads[] = {
31943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
31953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  };
31963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
31973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     NULL, 0);
31983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  http_data.set_connect_data(connect_data);
31993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&http_data);
32003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
32013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
3203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransportClientSocketPool* pool =
3205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      http_session_->GetTransportSocketPool(
3206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          HttpNetworkSession::NORMAL_SOCKET_POOL);
3207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create a SPDY session.
32095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url1(kDefaultURL);
3210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key1(HostPortPair(url1.host(), 80),
3211e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3212ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session1 =
32137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
3214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(pool->IsStalled());
3215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create a stream using the session, and send a request.
3217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback1;
3219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
3220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session1, url1, DEFAULT_PRIORITY,
3222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                BoundNetLog());
3223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get());
3224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateDoNothing delegate1(spdy_stream1);
3225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->SetDelegate(&delegate1);
3226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers1(
3228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(url1.spec()));
3229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
3230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            spdy_stream1->SendRequestHeaders(
3231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                headers1.Pass(), NO_MORE_DATA_TO_SEND));
3232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders());
3233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
3235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Trying to create a new connection should cause the pool to be stalled, and
3237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // post a task asynchronously to try and close the session.
3238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
3239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port2("2.com", 80);
3240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<TransportSocketParams> params2(
32413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new TransportSocketParams(host_port2, false, false,
3242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                OnHostResolutionCallback()));
3243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
3244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
3245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
3246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              callback2.callback(), pool, BoundNetLog()));
3247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
3248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Running the message loop should cause the socket pool to ask the SPDY
3250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // session to close an idle socket, but since the socket is in use, nothing
3251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // happens.
3252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::RunLoop().RunUntilIdle();
3253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(pool->IsStalled());
3254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(callback2.have_result());
3255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Cancelling the request should result in the session's socket being
32573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // closed, since the pool is stalled.
3258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get());
3259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->Cancel();
3260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::RunLoop().RunUntilIdle();
32613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ASSERT_FALSE(pool->IsStalled());
32623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(OK, callback2.WaitForResult());
3263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that SpdySessionKey and therefore SpdySession is different when
3266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// privacy mode is enabled or disabled.
3267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) {
3268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port_pair("www.google.com", 443);
3271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(),
3272e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                     PRIVACY_MODE_ENABLED);
3273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(),
3274e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                     PRIVACY_MODE_DISABLED);
3275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
32777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add SpdySession with PrivacyMode Enabled to the pool.
3280ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session_privacy_enabled =
32817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled);
3282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
32847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add SpdySession with PrivacyMode Disabled to the pool.
3287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session_privacy_disabled =
32887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled);
3289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
32917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session_privacy_enabled->CloseSessionOnError(ERR_ABORTED, std::string());
32947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
32957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session_privacy_disabled->CloseSessionOnError(ERR_ABORTED, std::string());
32987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled));
32997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
3300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3302bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Delegate that creates another stream when its stream is closed.
3303bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochclass StreamCreatingDelegate : public test::StreamDelegateDoNothing {
3304bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch public:
3305bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  StreamCreatingDelegate(const base::WeakPtr<SpdyStream>& stream,
3306bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                         const base::WeakPtr<SpdySession>& session)
3307bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      : StreamDelegateDoNothing(stream),
3308bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        session_(session) {}
3309bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3310bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual ~StreamCreatingDelegate() {}
3311bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3312bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual void OnClose(int status) OVERRIDE {
33135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    GURL url(kDefaultURL);
3314bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    ignore_result(
3315bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3316bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                  session_, url, MEDIUM, BoundNetLog()));
3317bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  }
3318bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3319bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch private:
3320bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  const base::WeakPtr<SpdySession> session_;
3321bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch};
3322bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3323bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Create another stream in response to a stream being reset. Nothing
3324bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// should blow up. This is a regression test for
3325bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// http://crbug.com/263690 .
3326bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
3327bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3328bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3329bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3330bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3331bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyFrame> req(
3332bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, MEDIUM, true));
3333bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockWrite writes[] = {
3334bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    CreateMockWrite(*req, 0),
3335bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  };
3336bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3337bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyFrame> rst(
3338bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
3339bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MockRead reads[] = {
3340bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    CreateMockRead(*rst, 1),
3341bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    MockRead(ASYNC, 0, 2)  // EOF
3342bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  };
3343bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DeterministicSocketData data(reads, arraysize(reads),
3344bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                               writes, arraysize(writes));
3345bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.set_connect_data(connect_data);
3346bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3347bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3348bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  CreateDeterministicNetworkSession();
3349bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3350bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdySession> session =
3351bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3352bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
33535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(kDefaultURL);
3354bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  base::WeakPtr<SpdyStream> spdy_stream =
3355bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
3356bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                session, url, MEDIUM, BoundNetLog());
3357bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  ASSERT_TRUE(spdy_stream.get() != NULL);
3358bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, spdy_stream->stream_id());
3359bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3360bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  StreamCreatingDelegate delegate(spdy_stream, session);
3361bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->SetDelegate(&delegate);
3362bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3363bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
3364bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      spdy_util_.ConstructGetHeaderBlock(url.spec()));
3365bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
3366bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(spdy_stream->HasUrlFromHeaders());
3367bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3368bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, spdy_stream->stream_id());
3369bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3370bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.RunFor(1);
3371bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3372bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(1u, spdy_stream->stream_id());
3373bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3374bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Cause the stream to be reset, which should cause another stream
3375bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // to be created.
3376bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  data.RunFor(1);
3377bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3378bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(NULL, spdy_stream.get());
3379bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(delegate.StreamIsClosed());
3380bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, session->num_active_streams());
3381bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(1u, session->num_created_streams());
3382bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
3383bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The tests below are only for SPDY/3 and above.
3385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
3387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY3)
3388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set SETTINGS_INITIAL_WINDOW_SIZE to a small number so that WINDOW_UPDATE
3391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // gets sent.
3392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SettingsMap new_settings;
3393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int32 window_size = 1;
3394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
3395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, window_size);
3396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set up the socket so we read a SETTINGS frame that sets
3398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // INITIAL_WINDOW_SIZE.
3399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame(
3401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(new_settings));
3402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*settings_frame, 0),
3404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 1)  // EOF
3405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
3408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockWrite writes[] = {
3409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*settings_ack, 2),
3410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
3411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
3415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               writes, arraysize(writes));
3416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.set_connect_data(connect_data);
3417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3421ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
34227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream1 =
3424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, test_url_, MEDIUM, BoundNetLog());
3426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream1.get() != NULL);
3427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback1;
3428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_NE(spdy_stream1->send_window_size(), window_size);
3429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3430cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.RunFor(1);  // Process the SETTINGS frame, but not the EOF
3431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
3432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(session->stream_initial_send_window_size(), window_size);
3433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(spdy_stream1->send_window_size(), window_size);
3434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Release the first one, this will allow the second to be created.
3436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream1->Cancel();
3437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream1.get());
3438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> spdy_stream2 =
3440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
3441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, test_url_, MEDIUM, BoundNetLog());
3442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(spdy_stream2.get() != NULL);
3443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
3444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_stream2->Cancel();
3445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, spdy_stream2.get());
3446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The tests below are only for SPDY/3.1 and above.
3449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// SpdySession::{Increase,Decrease}RecvWindowSize should properly
3451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// adjust the session receive window size for SPDY 3.1 and higher. In
3452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// addition, SpdySession::IncreaseRecvWindowSize should trigger
3453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// sending a WINDOW_UPDATE frame for a large enough delta.
3454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, AdjustRecvWindowSize) {
3455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
3456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int32 delta_window_size = 100;
3461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 1)  // EOF
3465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update(
3467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(
3468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kSessionFlowControlStreamId,
3469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kSpdySessionInitialWindowSize + delta_window_size));
3470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
3471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*window_update, 0),
3472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
3474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
3475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3479ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
34807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
3483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->IncreaseRecvWindowSize(delta_window_size);
3488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->session_recv_window_size_);
3490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(delta_window_size, session->session_unacked_recv_window_bytes_);
3491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Should trigger sending a WINDOW_UPDATE frame.
3493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->IncreaseRecvWindowSize(kSpdySessionInitialWindowSize);
3494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size +
3495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            kSpdySessionInitialWindowSize,
3496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->session_recv_window_size_);
3497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
3500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3501ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // DecreaseRecvWindowSize() expects |in_io_loop_| to be true.
3502ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->in_io_loop_ = true;
3503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->DecreaseRecvWindowSize(
3504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSpdySessionInitialWindowSize + delta_window_size +
3505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSpdySessionInitialWindowSize);
3506ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session->in_io_loop_ = false;
3507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_recv_window_size_);
3508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// SpdySession::{Increase,Decrease}SendWindowSize should properly
3512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// adjust the session send window size when the "enable_spdy_31" flag
3513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// is set.
3514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, AdjustSendWindowSize) {
3515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
3516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, 0, 0)  // EOF
3523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
3525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.socket_factory->AddSocketDataProvider(&data);
3527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateNetworkSession();
3529ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
35307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateFakeSpdySession(spdy_session_pool_, key_);
3531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
3533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int32 delta_window_size = 100;
3535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->IncreaseSendWindowSize(delta_window_size);
3539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize + delta_window_size,
3540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->session_send_window_size_);
3541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->DecreaseSendWindowSize(delta_window_size);
3543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Incoming data for an inactive stream should not cause the session
3547c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// receive window size to decrease, but it should cause the unacked
3548c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch// bytes to increase.
3549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
3550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
3551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
3554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
3556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
3557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
3558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 0),
3559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 1)  // EOF
3560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
3561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads), NULL, 0);
3562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
3563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
3566ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
35677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
3569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
3570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3574ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
3575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3577c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  EXPECT_EQ(kUploadDataSize, session->session_unacked_recv_window_bytes_);
3578ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
3579ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(1);
3580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
3581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// A delegate that drops any received data.
3583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate {
3584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
3585a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DropReceivedDataDelegate(const base::WeakPtr<SpdyStream>& stream,
3586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           base::StringPiece data)
358790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      : StreamDelegateSendImmediate(stream, data) {}
3588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~DropReceivedDataDelegate() {}
3590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Drop any received data.
3592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) OVERRIDE {}
3593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
3594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Send data back and forth but use a delegate that drops its received
3596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// data. The receive window should still increase to its original
3597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// value, i.e. we shouldn't "leak" receive window bytes.
35987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
35997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
36007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
3601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
3603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int32 msg_data_size = 100;
3605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string msg_data(msg_data_size, 'a');
3606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
3608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
36107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
36117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> msg(
36137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
36147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
3615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockWrite writes[] = {
3616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*msg, 2),
3618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> echo(
36227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
36237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
3624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> window_update(
362590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyWindowUpdate(
3626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          kSessionFlowControlStreamId, msg_data_size));
3627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockRead reads[] = {
3628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1),
3629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*echo, 3),
3630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 4)  // EOF
3631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
3634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
3635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               writes, arraysize(writes));
3636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.set_connect_data(connect_data);
3637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
3638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CreateDeterministicNetworkSession();
3641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3642ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
36437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL url(kStreamUrl);
3646a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
364790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
364890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
3649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
3650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0u, stream->stream_id());
3651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DropReceivedDataDelegate delegate(stream, msg_data);
3653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->SetDelegate(&delegate);
3654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
365590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3656b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
365790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
365890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3659ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
3660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
3663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(4);
3665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
3667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
3668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->Close();
3673a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, stream.get());
3674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(OK, delegate.WaitForClose());
3676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
3679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Send data back and forth but close the stream before its data frame
3682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// can be written to the socket. The send window should then increase
3683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// to its original value, i.e. we shouldn't "leak" send window bytes.
36847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
36857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
36867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
3687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
3689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int32 msg_data_size = 100;
3691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string msg_data(msg_data_size, 'a');
3692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
3694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
36967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
36977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
3698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockWrite writes[] = {
3699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
37027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockRead reads[] = {
3704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1),
3705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 2)  // EOF
3706c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
3707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
3709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
3710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               writes, arraysize(writes));
3711c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.set_connect_data(connect_data);
3712c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
3713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
3714c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CreateDeterministicNetworkSession();
3716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3717ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
37187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
3719c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL url(kStreamUrl);
3721a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
372290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
372390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
3724c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
3725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0u, stream->stream_id());
3726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
372790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(stream, msg_data);
3728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->SetDelegate(&delegate);
3729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
373090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3731b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
373290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
373390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3734ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
3735c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3738eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
3739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3741c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3742c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data.RunFor(1);
3743c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3744c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
3745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
3746c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3747c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
3748c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            session->session_send_window_size_);
3749c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3750c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Closing the stream should increase the session's send window.
3751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->Close();
3752a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, stream.get());
3753c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3754c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3755c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3756c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(OK, delegate.WaitForClose());
3757c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3758c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
37592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Send data back and forth; the send and receive windows should
37602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// change appropriately.
37617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
37627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
37637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
37642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
37662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int32 msg_data_size = 100;
37682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string msg_data(msg_data_size, 'a');
37692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
37712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
37737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
37747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0));
37752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> msg(
37767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
37777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
37782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
3779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*msg, 2),
37812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
37822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
37842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> echo(
37857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
37867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          1, msg_data.data(), msg_data_size, false));
37872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> window_update(
378890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyWindowUpdate(
37892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kSessionFlowControlStreamId, msg_data_size));
37902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1),
3792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*echo, 3),
3793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update, 4),
3794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 5)  // EOF
37952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
37962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create SpdySession and SpdyStream and send the request.
37982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
37992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
38002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
38012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
38022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
38032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
38052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3806ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
38077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
38082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
3810a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
381190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
381290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
38132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
38142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, stream->stream_id());
38152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
381690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateSendImmediate delegate(stream, msg_data);
38172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->SetDelegate(&delegate);
38182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
381990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3820b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(url.spec(), msg_data_size));
382190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
382290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3823ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
38242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3826eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
38272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
38282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3829eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
38302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3832eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
38332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
38342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
38362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
38382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_send_window_size_);
3839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
38402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
38412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
38432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
38452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_send_window_size_);
3846eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
38472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
38482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
38502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
38522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_send_window_size_);
3853eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
38542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_recv_window_size_);
38552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
38562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(1);
38582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3860eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize - msg_data_size,
38612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->session_recv_window_size_);
38622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, session->session_unacked_recv_window_bytes_);
38632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
38652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.at_read_eof());
38662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3867c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data, delegate.TakeReceivedData());
38682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3869c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Draining the delegate's read queue should increase the session's
3870c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // receive window.
3871c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3872eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
38732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
38742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->Close();
3876a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, stream.get());
38772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, delegate.WaitForClose());
3879c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_);
3881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_);
3882c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_);
38832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
38842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3885c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Given a stall function and an unstall function, runs a test to make
3886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// sure that a stream resumes after unstall.
38877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void SpdySessionTest::RunResumeAfterUnstallTest(
38887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function,
388990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::Callback<void(SpdySession*, SpdyStream*, int32)>&
389090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        unstall_function) {
38912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
38922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
38932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
38952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
38977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
38987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
389990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> body(
39007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
39012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
3902eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
3903eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body, 1),
39042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
39052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(
39077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
39082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> echo(
39097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
39102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
3911eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 2),
3912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 3), // EOF
39132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
39142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
39162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
39172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
39182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
39192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
39212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
3923ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
39247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
39252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
39262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->flow_control_state());
39272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3928a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
392990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
393090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
39312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
39322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3933a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateWithBody delegate(stream, kBodyDataStringPiece);
39342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->SetDelegate(&delegate);
39352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3936ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream->HasUrlFromHeaders());
393790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(stream->send_stalled_by_flow_control());
39382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
393990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
3940b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
394190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
394290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
3943ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
3944ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
39452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  stall_function.Run(session.get(), stream.get());
39472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
39492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream->send_stalled_by_flow_control());
39512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3952868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  unstall_function.Run(session.get(), stream.get(), kBodyDataSize);
39532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream->send_stalled_by_flow_control());
39552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(3);
39572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
39592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate.send_headers_completed());
39612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
396290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate.TakeReceivedData());
396390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
39642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
39652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3966c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Run the resume-after-unstall test with all possible stall and
3967c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// unstall sequences.
3968c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
39697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeAfterUnstallSession) {
39707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
39717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
39727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
39737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
39747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallSessionOnly,
3975c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
39767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallSessionOnly,
3977c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
3978c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3980c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Equivalent to
39817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// SpdyStreamTest.ResumeAfterSendWindowSizeIncrease.
39827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeAfterUnstallStream) {
39837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
39847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
39857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
39867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
39877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallStreamOnly,
3988c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
39897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallStreamOnly,
3990c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
3991c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3992c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
39937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallSessionStream) {
39947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
39957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
39967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
39977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
39987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallSessionStream,
3999c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
40007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallSessionStream,
4001c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
4002c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4003c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallSessionStream) {
40057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
40067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
40077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
40087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
40097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallStreamSession,
4010c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
40117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallSessionStream,
4012c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
4013c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4014c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallStreamSessionResumeAfterUnstallStreamSession) {
40167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
40177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
40187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
40197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
40207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallStreamSession,
4021c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
40227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallStreamSession,
4023c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
4024c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4025c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
40277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
40287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
40297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
40307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RunResumeAfterUnstallTest(
40317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::StallSessionStream,
4032c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
40337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SpdySessionTest::UnstallStreamSession,
4034c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
4035c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4036c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Cause a stall by reducing the flow control send window to 0. The
40382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// streams should resume in priority order when that window is then
40392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// increased.
40407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
40417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
40427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
40437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
40442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
40452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
40462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
40482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
40507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
40517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
40522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
40537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
40547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0));
405590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> body1(
40567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
405790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> body2(
40587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
40592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
4060eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
4061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
4062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body2, 2),
4063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body1, 3),
40642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
40652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
40677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
40682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
4069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp1, 4),
4070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 5),
4071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 6), // EOF
40722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
40732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
40752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
40762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
40772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
40782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
40802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
4082ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
40837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
40842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
40852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->flow_control_state());
40862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4087a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream1 =
408890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
408990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
40902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream1.get() != NULL);
40912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4092a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
40932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream1->SetDelegate(&delegate1);
40942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4095ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream1->HasUrlFromHeaders());
40962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4097a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream2 =
409890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
409990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, MEDIUM, BoundNetLog());
41002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream2.get() != NULL);
41012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4102a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
41032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream2->SetDelegate(&delegate2);
41042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4105ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream2->HasUrlFromHeaders());
41062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
41082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
41092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StallSessionSend(session.get());
41112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
411290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
411390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
411490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
411590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4116ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream1->HasUrlFromHeaders());
4117ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
41182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
412090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1u, stream1->stream_id());
41212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
412290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
412390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
412490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
412590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
412690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4127ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
4128ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
412990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
413090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
413190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(3u, stream2->stream_id());
41322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
41332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should unstall only stream2.
4135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UnstallSessionSend(session.get(), kBodyDataSize);
41362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
41382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
41392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
414090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
41412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
41432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
41442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should then unstall stream1.
4146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UnstallSessionSend(session.get(), kBodyDataSize);
41472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
41502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(4);
41522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
41542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
41552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate1.send_headers_completed());
4157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status"));
4158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
41592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate2.send_headers_completed());
41612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
416290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
41632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
416490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
416590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
41662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Delegate that closes a given stream after sending its body.
4168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass StreamClosingDelegate : public test::StreamDelegateWithBody {
4169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
4170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StreamClosingDelegate(const base::WeakPtr<SpdyStream>& stream,
4171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        base::StringPiece data)
4172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : StreamDelegateWithBody(stream, data) {}
4173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual ~StreamClosingDelegate() {}
4175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void set_stream_to_close(const base::WeakPtr<SpdyStream>& stream_to_close) {
4177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    stream_to_close_ = stream_to_close;
4178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnDataSent() OVERRIDE {
4181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    test::StreamDelegateWithBody::OnDataSent();
4182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (stream_to_close_.get()) {
4183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream_to_close_->Close();
4184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_EQ(NULL, stream_to_close_.get());
4185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
4186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
4189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream_to_close_;
4190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
4191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
41922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Cause a stall by reducing the flow control send window to
4193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 0. Unstalling the session should properly handle deleted streams.
4194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
41957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
41967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
41977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
41982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kStreamUrl[] = "http://www.google.com/";
41992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
42002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.host_resolver->set_synchronous_mode(true);
42022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
42047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
42057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
42062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
42077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
42087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req3(
4210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPost(
4211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0));
4212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(
4213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
42142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
4215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
4216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
4217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req3, 2),
4218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body2, 3),
42192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
42202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
42222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
4223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 4),
4224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 5), // EOF
42252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
42262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
42282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               writes, arraysize(writes));
42292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
42302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
42312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
42332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateDeterministicNetworkSession();
4235ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
42367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
42372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
42382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            session->flow_control_state());
42392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4240a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream1 =
424190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
424290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
42432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream1.get() != NULL);
42442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
424590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
42462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream1->SetDelegate(&delegate1);
42472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4248ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream1->HasUrlFromHeaders());
42492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4250a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream2 =
425190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
425290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                session, url, LOWEST, BoundNetLog());
42532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream2.get() != NULL);
42542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StreamClosingDelegate delegate2(stream2, kBodyDataStringPiece);
42562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream2->SetDelegate(&delegate2);
42572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4258ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream2->HasUrlFromHeaders());
42592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream3 =
4261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url, LOWEST, BoundNetLog());
4263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream3.get() != NULL);
4264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateWithBody delegate3(stream3, kBodyDataStringPiece);
4266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream3->SetDelegate(&delegate3);
4267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4268ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream3->HasUrlFromHeaders());
4269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
42702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
42712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream3->send_stalled_by_flow_control());
42732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StallSessionSend(session.get());
42752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
427690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers1(
427790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
427890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
427990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4280ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream1->HasUrlFromHeaders());
4281ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
42822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
428490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1u, stream1->stream_id());
42852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
428690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
428790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers2(
428890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
428990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
429090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4291ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
4292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
429390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
429490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
429590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(3u, stream2->stream_id());
42962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
42972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers3(
4299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4300a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
4301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream3->SendRequestHeaders(headers3.Pass(), MORE_DATA_TO_SEND));
4302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream3->HasUrlFromHeaders());
4303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream3->GetUrlFromHeaders().spec());
4304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
4306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(5u, stream3->stream_id());
4307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream3->send_stalled_by_flow_control());
4308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamId stream_id1 = stream1->stream_id();
4310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamId stream_id2 = stream2->stream_id();
4311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyStreamId stream_id3 = stream3->stream_id();
4312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Close stream1 preemptively.
4314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session->CloseActiveStream(stream_id1, ERR_CONNECTION_CLOSED);
4315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream1.get());
4316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->IsStreamActive(stream_id1));
4318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->IsStreamActive(stream_id2));
4319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->IsStreamActive(stream_id3));
43207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Unstall stream2, which should then close stream3.
4322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  delegate2.set_stream_to_close(stream3);
4323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UnstallSessionSend(session.get(), kBodyDataSize);
4324a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
4326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream3.get());
4327a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->IsStreamActive(stream_id1));
4330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(session->IsStreamActive(stream_id2));
4331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(session->IsStreamActive(stream_id3));
4332a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
4334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL, stream2.get());
4335a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
4338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, delegate3.WaitForClose());
4339a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.send_headers_completed());
4341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
4342a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.send_headers_completed());
4344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
4345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
4346a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate3.send_headers_completed());
4348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate3.TakeReceivedData());
4349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
4351a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
4352a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Cause a stall by reducing the flow control send window to
4354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 0. Unstalling the session should properly handle the session itself
4355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// being closed.
4356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
4357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam() < kProtoSPDY31)
43587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
43597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kStreamUrl[] = "http://www.google.com/";
4361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url(kStreamUrl);
4362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.host_resolver->set_synchronous_mode(true);
4364a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
436590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req1(
4366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPost(
4367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0));
4368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
4369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPost(
4370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0));
4371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(
4372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
4373a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  MockWrite writes[] = {
4374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
4375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
4376a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  };
4377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
4379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 2), // EOF
4380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
4383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
4384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
4385a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  data.set_connect_data(connect_data);
4386a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4388a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CreateDeterministicNetworkSession();
4390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session =
43917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION,
4393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            session->flow_control_state());
4394a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream1 =
4396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url, LOWEST, BoundNetLog());
4398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream1.get() != NULL);
4399a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece);
4401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream1->SetDelegate(&delegate1);
4402a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4403ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream1->HasUrlFromHeaders());
4404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream2 =
440690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(SPDY_REQUEST_RESPONSE_STREAM,
4407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                session, url, LOWEST, BoundNetLog());
4408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream2.get() != NULL);
4409a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  test::StreamDelegateWithBody delegate2(stream2, kBodyDataStringPiece);
4411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream2->SetDelegate(&delegate2);
4412a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4413ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream2->HasUrlFromHeaders());
4414a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream1->send_stalled_by_flow_control());
4416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(stream2->send_stalled_by_flow_control());
4417a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StallSessionSend(session.get());
4419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers1(
4421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4422a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
4423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream1->SendRequestHeaders(headers1.Pass(), MORE_DATA_TO_SEND));
4424ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream1->HasUrlFromHeaders());
4425ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream1->GetUrlFromHeaders().spec());
4426a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
4428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(1u, stream1->stream_id());
4429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream1->send_stalled_by_flow_control());
4430a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
4432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kBodyDataSize));
4433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
4434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream2->SendRequestHeaders(headers2.Pass(), MORE_DATA_TO_SEND));
4435ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream2->HasUrlFromHeaders());
4436ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream2->GetUrlFromHeaders().spec());
4437a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
4439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3u, stream2->stream_id());
4440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream2->send_stalled_by_flow_control());
444190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
44427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_));
444390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Unstall stream1.
4445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UnstallSessionSend(session.get(), kBodyDataSize);
444690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Close the session (since we can't do it from within the delegate
4448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // method, since it's in the stream's loop).
44497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session");
4450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
4451ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(session == NULL);
445290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
44537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
445490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose());
4456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose());
445790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate1.send_headers_completed());
4459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate1.TakeReceivedData());
446090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(delegate2.send_headers_completed());
4462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(std::string(), delegate2.TakeReceivedData());
446390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
446590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
446690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4467f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
4468f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (GetParam() < kProtoSPDY31)
4469f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
4470f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4471f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
4472f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4473f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> req(
4474f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
4476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      0,
4477f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      GOAWAY_FLOW_CONTROL_ERROR,
4478f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
4479f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      "the receive window size of 1"));
4480f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockWrite writes[] = {
4481f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
4482f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  };
4483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4484f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4485f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4486f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockRead reads[] = {
4487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
4488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  };
4489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4490f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DeterministicSocketData data(
4491f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes));
4492f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data.set_connect_data(connect_data);
4493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
4494f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CreateDeterministicNetworkSession();
4496f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4497f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::WeakPtr<SpdySession> session =
4498f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateInsecureSpdySession(http_session_, key_, BoundNetLog());
4499f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4500f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GURL url(kDefaultURL);
4501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
4502f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
4503f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ASSERT_TRUE(spdy_stream.get() != NULL);
4504f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  test::StreamDelegateDoNothing delegate(spdy_stream);
4505f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  spdy_stream->SetDelegate(&delegate);
4506f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4507f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
4508f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_util_.ConstructGetHeaderBlock(url.spec()));
4509f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  spdy_stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
4510f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4511f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data.RunFor(1);  // Write request.
4512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Put session on the edge of overflowing it's recv window.
4514f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  session->session_recv_window_size_ = 1;
4515f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Read response headers & body. Body overflows the session window, and a
4517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // goaway is written.
4518f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  data.RunFor(3);
4519f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
4520f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4521f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(ERR_SPDY_FLOW_CONTROL_ERROR, delegate.WaitForClose());
4522f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(session == NULL);
4523f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
4524f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4525f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_P(SpdySessionTest, SplitHeaders) {
4526f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GURL kStreamUrl("http://www.google.com/foo.dat");
4527f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SpdyHeaderBlock headers;
4528f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  spdy_util_.AddUrlToHeaderBlock(kStreamUrl.spec(), &headers);
4529f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  headers["alpha"] = "beta";
4530f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4531f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SpdyHeaderBlock request_headers;
4532f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SpdyHeaderBlock response_headers;
4533f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4534f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SplitPushedHeadersToRequestAndResponse(
4535f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      headers, spdy_util_.spdy_version(), &request_headers, &response_headers);
4536f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4537f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SpdyHeaderBlock::const_iterator it = response_headers.find("alpha");
4538f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::string alpha_val =
4539f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      (it == response_headers.end()) ? std::string() : it->second;
4540f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ("beta", alpha_val);
4541f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4542f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GURL request_url =
4543f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
4544f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(kStreamUrl, request_url);
4545f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
4546f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
45475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MapFramerErrorToProtocolError, MapsValues) {
4548f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(
4549f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SPDY_ERROR_INVALID_CONTROL_FRAME,
4550f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4551f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(
4552f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
4553f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MapFramerErrorToProtocolError(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
4554f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(
4555f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SPDY_ERROR_GOAWAY_FRAME_CORRUPT,
4556f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MapFramerErrorToProtocolError(SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
4557a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CHECK_EQ(SPDY_ERROR_UNEXPECTED_FRAME,
4558f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapFramerErrorToProtocolError(SpdyFramer::SPDY_UNEXPECTED_FRAME));
4559f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
4560f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4561f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST(MapFramerErrorToNetError, MapsValue) {
4562f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(ERR_SPDY_PROTOCOL_ERROR,
4563f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapFramerErrorToNetError(SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
4564f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4565f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapFramerErrorToNetError(SpdyFramer::SPDY_COMPRESS_FAILURE));
4566f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(ERR_SPDY_COMPRESSION_ERROR,
4567f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapFramerErrorToNetError(SpdyFramer::SPDY_DECOMPRESS_FAILURE));
4568f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(
4569f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ERR_SPDY_FRAME_SIZE_ERROR,
4570f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MapFramerErrorToNetError(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
45715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
45725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
45735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MapRstStreamStatusToProtocolError, MapsValues) {
45745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK_EQ(STATUS_CODE_PROTOCOL_ERROR,
4575f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapRstStreamStatusToProtocolError(RST_STREAM_PROTOCOL_ERROR));
45765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(STATUS_CODE_FRAME_SIZE_ERROR,
4577f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapRstStreamStatusToProtocolError(RST_STREAM_FRAME_SIZE_ERROR));
45785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_EQ(STATUS_CODE_ENHANCE_YOUR_CALM,
4579f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapRstStreamStatusToProtocolError(RST_STREAM_ENHANCE_YOUR_CALM));
4580f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
4581f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4582f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST(MapNetErrorToGoAwayStatus, MapsValue) {
4583f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_INADEQUATE_SECURITY,
4584f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY));
4585f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_FLOW_CONTROL_ERROR,
4586f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_FLOW_CONTROL_ERROR));
4587f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_PROTOCOL_ERROR,
4588f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_PROTOCOL_ERROR));
4589f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_COMPRESSION_ERROR,
4590f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_COMPRESSION_ERROR));
4591f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_FRAME_SIZE_ERROR,
4592f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           MapNetErrorToGoAwayStatus(ERR_SPDY_FRAME_SIZE_ERROR));
4593f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(GOAWAY_PROTOCOL_ERROR, MapNetErrorToGoAwayStatus(ERR_UNEXPECTED));
45945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
45955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
45965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
4597